Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Aug 11, 2022. It is now read-only.
/npmPublic archive

Commit47f77ad

Browse files
committed
ls: stop flattening output, show the actual tree
1 parentb12056d commit47f77ad

File tree

4 files changed

+154
-106
lines changed

4 files changed

+154
-106
lines changed

‎lib/ls.js

Lines changed: 72 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ var semver = require('semver')
1515
varcolor=require('ansicolors')
1616
varnpa=require('npm-package-arg')
1717
variferr=require('iferr')
18+
varsortedObject=require('sorted-object')
19+
varextend=Object.assign||require('util')._extend
1820
varnpm=require('./npm.js')
1921
varmutateIntoLogicalTree=require('./install/mutate-into-logical-tree.js')
2022
varrecalculateMetadata=require('./install/deps.js').recalculateMetadata
@@ -76,8 +78,8 @@ var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
7678

7779
pruneNestedExtraneous(data)
7880
filterByEnv(data)
79-
varbfs=filterFound(bfsify(data),args)
80-
varlite=getLite(bfs)
81+
varunlooped=filterFound(unloop(data),args)
82+
varlite=getLite(unlooped)
8183

8284
if(silent)returncb(null,data,lite)
8385

@@ -86,7 +88,7 @@ var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
8688
varout
8789
if(json){
8890
varseen=[]
89-
vard=long ?bfs :lite
91+
vard=long ?unlooped :lite
9092
// the raw data can be circular
9193
out=JSON.stringify(d,function(k,o){
9294
if(typeofo==='object'){
@@ -96,9 +98,9 @@ var lsFromTree = ls.fromTree = function (dir, physicalTree, args, silent, cb) {
9698
returno
9799
},2)
98100
}elseif(npm.config.get('parseable')){
99-
out=makeParseable(bfs,long,dir)
101+
out=makeParseable(unlooped,long,dir)
100102
}elseif(data){
101-
out=makeArchy(bfs,long,dir)
103+
out=makeArchy(unlooped,long,dir)
102104
}
103105
output(out)
104106

@@ -247,36 +249,25 @@ function getLite (data, noname, depth) {
247249
returnlite
248250
}
249251

250-
functionbfsify(root){
251-
// walk over the data, and turn it from this:
252-
// +-- a
253-
// | `-- b
254-
// | `-- a (truncated)
255-
// `--b (truncated)
256-
// into this:
257-
// +-- a
258-
// `-- b
259-
// which looks nicer
252+
functionunloop(root){
260253
varqueue=[root]
261-
varseen=[root]
254+
varseen={}
255+
seen[root.path]=true
262256

263257
while(queue.length){
264258
varcurrent=queue.shift()
265259
vardeps=current.dependencies=current.dependencies||{}
266260
Object.keys(deps).forEach(function(d){
267261
vardep=deps[d]
268262
if(dep.missing)return
269-
if(inList(seen,dep)){
270-
if(npm.config.get('parseable')||!npm.config.get('long')){
271-
deletedeps[d]
272-
return
273-
}else{
274-
dep=deps[d]=Object.create(dep)
275-
dep.dependencies={}
276-
}
263+
if(dep.path&&seen[dep.path]){
264+
dep=deps[d]=extend({},dep)
265+
dep.dependencies={}
266+
dep._deduped=path.relative(root.path,dep.path).replace(/node_modules\//g,'')
267+
return
277268
}
269+
seen[dep.path]=true
278270
queue.push(dep)
279-
seen.push(dep)
280271
})
281272
}
282273

@@ -285,18 +276,23 @@ function bfsify (root) {
285276

286277
functionfilterFound(root,args){
287278
if(!args.length)returnroot
288-
vardeps=root.dependencies
289-
if(deps){
290-
Object.keys(deps).forEach(function(depName){
291-
vardep=filterFound(deps[depName],args)
279+
if(!root.dependencies)returnroot
280+
281+
// Mark all deps
282+
vartoMark=[root]
283+
while(toMark.length){
284+
varmarkPkg=toMark.shift()
285+
varmarkDeps=markPkg.dependencies
286+
if(!markDeps)continue
287+
Object.keys(markDeps).forEach(function(depName){
288+
vardep=markDeps[depName]
292289
if(dep.peerMissing)return
293-
294-
// see if this one itself matches
295-
varfound=false
296-
for(varii=0;!found&&ii<args.length;ii++){
290+
dep._parent=markPkg
291+
for(varii=0;ii<args.length;ii++){
297292
varargName=args[ii][0]
298293
varargVersion=args[ii][1]
299294
varargRaw=args[ii][2]
295+
varfound
300296
if(depName===argName&&argVersion){
301297
found=semver.satisfies(dep.version,argVersion,true)
302298
}elseif(depName===argName){
@@ -305,16 +301,33 @@ function filterFound (root, args) {
305301
}elseif(dep.path===argRaw){
306302
found=true
307303
}
304+
if(found){
305+
dep._found='explicit'
306+
varparent=dep._parent
307+
while(parent&&!parent._found&&!parent._deduped){
308+
parent._found='implicit'
309+
parent=parent._parent
310+
}
311+
break
312+
}
308313
}
309-
// included explicitly
310-
if(found)dep._found=true
311-
// included because a child was included
312-
if(dep._found&&!root._found)root._found=1
313-
// not included
314-
if(!dep._found)deletedeps[depName]
314+
toMark.push(dep)
315+
})
316+
}
317+
vartoTrim=[root]
318+
while(toTrim.length){
319+
vartrimPkg=toTrim.shift()
320+
vartrimDeps=trimPkg.dependencies
321+
if(!trimDeps)continue
322+
trimPkg.dependencies={}
323+
Object.keys(trimDeps).forEach(function(name){
324+
vardep=trimDeps[name]
325+
if(!dep._found)return
326+
if(dep._found==='implicit'&&dep._deduped)return
327+
trimPkg.dependencies[name]=dep
328+
toTrim.push(dep)
315329
})
316330
}
317-
if(!root._found)root._found=false
318331
returnroot
319332
}
320333

@@ -345,7 +358,7 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
345358
varout={}
346359
// the top level is a bit special.
347360
out.label=data._id||''
348-
if(data._found===true&&data._id){
361+
if(data._found==='explicit'&&data._id){
349362
if(npm.color){
350363
out.label=color.bgBlack(color.yellow(out.label.trim()))+' '
351364
}else{
@@ -354,6 +367,14 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
354367
}
355368
if(data.link)out.label+=' -> '+data.link
356369

370+
if(data._deduped){
371+
if(npm.color){
372+
out.label+=' '+color.brightBlack('deduped')
373+
}else{
374+
out.label+=' deduped'
375+
}
376+
}
377+
357378
if(data.invalid){
358379
if(data.realName!==data.name)out.label+=' ('+data.realName+')'
359380
varinvalid='invalid'
@@ -369,6 +390,7 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
369390

370391
if(data.peerMissing){
371392
varpeerMissing='UNMET PEER DEPENDENCY'
393+
372394
if(npm.color)peerMissing=color.bgBlack(color.red(peerMissing))
373395
out.label=peerMissing+' '+out.label
374396
}
@@ -415,7 +437,7 @@ function makeArchy_ (data, long, dir, depth, parent, d) {
415437
.sort(alphasort).filter(function(d){
416438
return!isCruft(data.dependencies[d])
417439
}).map(function(d){
418-
returnmakeArchy_(data.dependencies[d],long,dir,depth+1,data,d)
440+
returnmakeArchy_(sortedObject(data.dependencies[d]),long,dir,depth+1,data,d)
419441
})
420442
}
421443

@@ -444,19 +466,20 @@ function getExtras (data) {
444466
}
445467

446468
functionmakeParseable(data,long,dir,depth,parent,d){
469+
if(data._deduped)return[]
447470
depth=depth||0
448471
if(depth>npm.config.get('depth'))return[makeParseable_(data,long,dir,depth,parent,d)]
449472
return[makeParseable_(data,long,dir,depth,parent,d)]
450-
.concat(Object.keys(data.dependencies||{})
451-
.sort(alphasort).map(function(d){
452-
returnmakeParseable(data.dependencies[d],long,dir,depth+1,data,d)
453-
}))
454-
.filter(function(x){returnx})
455-
.join('\n')
473+
.concat(Object.keys(data.dependencies||{})
474+
.sort(alphasort).map(function(d){
475+
returnmakeParseable(data.dependencies[d],long,dir,depth+1,data,d)
476+
}))
477+
.filter(function(x){returnx})
478+
.join('\n')
456479
}
457480

458481
functionmakeParseable_(data,long,dir,depth,parent,d){
459-
if(data.hasOwnProperty('_found')&&data._found!==true)return''
482+
if(data.hasOwnProperty('_found')&&data._found!=='explicit')return''
460483

461484
if(data.missing){
462485
if(depth<npm.config.get('depth')){

‎test/tap/extraneous-dep-cycle-ls-ok.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ test('setup', function (t) {
5454

5555
varexpected=pkg+'\n'+
5656
'└─┬ moduleA@1.0.0\n'+
57-
' └── moduleB@1.0.0\n\n'
57+
' └─┬ moduleB@1.0.0\n'+
58+
' └── moduleA@1.0.0 deduped\n\n'
5859

5960
test('extraneous-dep-cycle',function(t){
6061
common.npm(['ls','--unicode=true'],{cwd:pkg},function(er,code,stdout,stderr){

‎test/tap/git-races.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ function setup (cb) {
162162
varoneTree=[
163163
'npm-git-test@1.0.0',[
164164
['dummy-npm-bar@4.0.0',[
165-
['dummy-npm-foo@3.0.0',[]]
165+
['dummy-npm-foo@3.0.0',[]],
166+
['dummy-npm-buzz@3.0.0',[]]
166167
]],
167168
['dummy-npm-buzz@3.0.0',[]],
168169
['dummy-npm-foo@4.0.0',[
@@ -199,17 +200,19 @@ test('setup', function (t) {
199200
})
200201

201202
test('correct versions are installed for git dependency',function(t){
202-
t.plan(3)
203203
t.comment('test for https://github.com/npm/npm/issues/7202')
204204
npm.commands.install([],function(er){
205205
t.ifError(er,'installed OK')
206206
npm.commands.ls([],true,function(er,result){
207207
t.ifError(er,'ls OK')
208208
varsimplified=toSimple(result)
209-
t.ok(
210-
deepEqual(simplified,oneTree)||deepEqual(simplified,otherTree),
211-
'install tree is correct'
212-
)
209+
if(deepEqual(simplified,oneTree)||deepEqual(simplified,otherTree)){
210+
t.pass('install tree is correct')
211+
}else{
212+
t.isDeeply(simplified,oneTree,'oneTree matches')
213+
t.isDeeply(simplified,otherTree,'otherTree matches')
214+
}
215+
t.done()
213216
})
214217
})
215218
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp