Skip to content
This repository has been archived by the owner on Jan 19, 2022. It is now read-only.

Commit

Permalink
Sorted tarball contents
Browse files Browse the repository at this point in the history
This will make `npm pack` output the tarball contents
in an alphabetically and natural sort order.

The current implementation uses `localeCompare` with
the following options:

1. **sensitivity**: `base`, to correctly handle non-ascii letters
  using their base ascii, so that `á`,`â`, `ä`, `ã`, `å` are
  all handled like `a`

1. **numbers**: `true`, to handle numeric filenames as natural
  ascending order so that, for instance, file `10.txt` appears after `9.txt`

---

Convo from npm/rfcs#96

cc @ruyadorno @isaacs
  • Loading branch information
eridal authored and claudiahdz committed Mar 26, 2020
1 parent 716a397 commit 6d72149
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
57 changes: 57 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,60 @@ t.test('packs from registry spec', async t => {
await rimraf(testDir)
})
})

t.test('files packed are alphabetically sorted', async (t) => {
const testDir = t.testdir({
index: 'index',
dist: {
'foo.js': 'foo',
'foo.ts': 'foo',
bar: 'bar',
baz: 'baz'
},
numbers: {
1: '1',
11: '1',
'01': '0',
20: '2',
2: '2',
10: '1',
0: '0'
},
'package.json': JSON.stringify({
name: 'pkg'
}),
lib: {
'index.js': 'lib/index',
'foo.js': 'lib/foo'
},
'README.md': 'readme-1',
'readme.txt': 'readme-2'
})

const target = `${testDir}/my-cool-pkg-1.0.0.tgz`
const tarContents = await pack(testDir, { target })
const tarFilePaths = tarContents.files.map(file => file.path)
const expectedOrder = [
'README.md',
'dist/bar',
'dist/baz',
'dist/foo.js',
'dist/foo.ts',
'index',
'lib/foo.js',
'lib/index.js',
'numbers/0',
'numbers/01',
'numbers/1',
'numbers/2',
'numbers/10',
'numbers/11',
'numbers/20',
'package.json',
'readme.txt'
]

t.deepEqual(tarFilePaths, expectedOrder,
'files packed matches order expectations'
)
})
20 changes: 19 additions & 1 deletion utils/tar.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,24 @@ async function getContents (manifest, target) {
})
])

const comparator = (a, b) => {
return a.path.localeCompare(b.path, undefined, {
sensitivity: 'case',
numeric: true
})
}

const isUpper = (str) => {
const ch = str.charAt(0)
return ch >= 'A' && ch <= 'Z'
}

const uppers = files.filter(file => isUpper(file.path))
const others = files.filter(file => !isUpper(file.path))

uppers.sort(comparator)
others.sort(comparator)

const shasum = integrity.sha1[0].hexDigest()
return {
id: manifest._id || `${manifest.name}@${manifest.version}`,
Expand All @@ -96,7 +114,7 @@ async function getContents (manifest, target) {
shasum,
integrity: ssri.parse(integrity.sha512[0]),
filename: `${manifest.name}-${manifest.version}.tgz`,
files,
files: uppers.concat(others),
entryCount: totalEntries,
bundled: Array.from(bundled)
}
Expand Down

0 comments on commit 6d72149

Please sign in to comment.