Skip to content

Commit cd86177

Browse files
committed
Omit filenames containing asterisks
Filenames containing * chars break windows and create incompatible archives in the npm registry. In the next major release, this should raise an error instead of silently omitting them, so that authors can be alerted. Fix #9
1 parent bc1d66b commit cd86177

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed

index.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ const defaultRules = [
5151
'core.+([0-9])',
5252
]
5353

54+
// There may be others, but :?|<> are handled by node-tar
55+
const nameIsBadForWindows = file => /\*/.test(file)
56+
5457
// a decorator that applies our custom rules to an ignore walker
5558
const npmWalker = Class => class Walker extends Class {
5659
constructor (opt) {
@@ -191,6 +194,16 @@ const npmWalker = Class => class Walker extends Class {
191194
then()
192195
}
193196

197+
// override parent stat function to completely skip any filenames
198+
// that will break windows entirely.
199+
// XXX(isaacs) Next major version should make this an error instead.
200+
stat (entry, file, dir, then) {
201+
if (nameIsBadForWindows(entry))
202+
then()
203+
else
204+
super.stat(entry, file, dir, then)
205+
}
206+
194207
// override parent onstat function to nix all symlinks
195208
onstat (st, entry, file, dir, then) {
196209
if (st.isSymbolicLink())

test/star-names.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
'use strict'
2+
const fs = require('fs')
3+
4+
const readdir = fs.readdir
5+
fs.readdir = (path, cb) => {
6+
readdir(path, (er, entries) => {
7+
if (er)
8+
cb(er)
9+
else
10+
cb(null, entries.concat('made*of*stars'))
11+
})
12+
}
13+
14+
const readdirSync = fs.readdirSync
15+
fs.readdirSync = path => readdirSync(path).concat('made*of*stars')
16+
17+
const path = require('path')
18+
19+
const mkdirp = require('mkdirp')
20+
const rimraf = require('rimraf')
21+
const t = require('tap')
22+
23+
const pack = require('../')
24+
25+
const pkg = path.join(__dirname, path.basename(__filename, '.js'))
26+
t.teardown(_ => rimraf.sync(pkg))
27+
28+
const elfJS = `
29+
module.exports = elf =>
30+
console.log("i'm a elf")
31+
`
32+
33+
const json = {
34+
'name': 'test-package',
35+
'version': '3.1.4',
36+
'main': 'elf.js'
37+
}
38+
39+
const expect = [
40+
'package.json',
41+
'elf.js',
42+
'deps/foo/config/config.gypi'
43+
]
44+
45+
t.test('setup', t => {
46+
rimraf.sync(pkg)
47+
mkdirp.sync(pkg)
48+
fs.writeFileSync(
49+
path.join(pkg, 'package.json'),
50+
JSON.stringify(json, null, 2)
51+
)
52+
53+
fs.writeFileSync(
54+
path.join(pkg, 'elf.js'),
55+
elfJS
56+
)
57+
58+
fs.writeFileSync(
59+
path.join(pkg, '.npmrc'),
60+
'packaged=false'
61+
)
62+
63+
fs.writeFileSync(
64+
path.join(pkg, '.npmignore'),
65+
'.npmignore\ndummy\npackage.json'
66+
)
67+
68+
fs.writeFileSync(
69+
path.join(pkg, 'dummy'),
70+
'foo'
71+
)
72+
73+
// empty dir should be ignored
74+
mkdirp.sync(pkg + '/this/dir/is/empty/and/ignored')
75+
76+
const buildDir = path.join(pkg, 'build')
77+
mkdirp.sync(buildDir)
78+
fs.writeFileSync(
79+
path.join(buildDir, 'config.gypi'),
80+
"i_wont_be_included='with any luck'"
81+
)
82+
83+
const depscfg = path.join(pkg, 'deps/foo/config')
84+
mkdirp.sync(depscfg)
85+
fs.writeFileSync(
86+
path.join(depscfg, 'config.gypi'),
87+
"i_will_be_included='with any luck'"
88+
)
89+
90+
fs.writeFileSync(
91+
path.join(buildDir, 'npm-debug.log'),
92+
'0 lol\n'
93+
)
94+
95+
const gitDir = path.join(pkg, '.git')
96+
mkdirp.sync(gitDir)
97+
fs.writeFileSync(
98+
path.join(gitDir, 'gitstub'),
99+
"won't fool git, also won't be included"
100+
)
101+
102+
const historyDir = path.join(pkg, 'node_modules/history')
103+
mkdirp.sync(historyDir)
104+
fs.writeFileSync(
105+
path.join(historyDir, 'README.md'),
106+
"please don't include me"
107+
)
108+
109+
t.end()
110+
})
111+
112+
t.test('follows npm package ignoring rules', function (t) {
113+
const check = (files, t) => {
114+
t.same(files, expect)
115+
t.end()
116+
}
117+
118+
t.test('sync', t => check(pack.sync({ path: pkg }), t))
119+
t.test('async', t => pack({ path: pkg }).then(files => check(files, t)))
120+
121+
t.end()
122+
})

0 commit comments

Comments
 (0)