Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Allow installations from git+file:// if the package is private

Throw error, in case packages are going to be published
See #3868
  • Loading branch information...
commit fbd5189f74f055c62e0eff776f0951f91ac36414 1 parent 8608df0
@robertkowalski authored
View
32 lib/publish.js
@@ -11,6 +11,8 @@ var npm = require("./npm.js")
, chain = require("slide").chain
, Conf = require("npmconf").Conf
, RegClient = require("npm-registry-client")
+ , isGitFileUrl = require("./utils/is-git-file-url.js")
+ , asyncMap = require("slide").asyncMap
publish.usage = "npm publish <tarball>"
+ "\nnpm publish <folder>"
@@ -34,12 +36,16 @@ function publish (args, isRetry, cb) {
readJson(path.resolve(arg, "package.json"), function (er, data) {
er = needVersion(er, data)
if (er && er.code !== "ENOENT" && er.code !== "ENOTDIR") return cb(er)
- // error is ok. could be publishing a url or tarball
- // however, that means that we will not have automatically run
- // the prepublish script, since that gets run when adding a folder
- // to the cache.
- if (er) return cacheAddPublish(arg, false, isRetry, cb)
- cacheAddPublish(arg, true, isRetry, cb)
+ // do not allow packages with git+file:// deps to be published
+ needPrivate(data, function (err) {
+ if (err) return cb(err)
+ // error is ok. could be publishing a url or tarball
+ // however, that means that we will not have automatically run
+ // the prepublish script, since that gets run when adding a folder
+ // to the cache.
+ if (er) return cacheAddPublish(arg, false, isRetry, cb)
+ cacheAddPublish(arg, true, isRetry, cb)
+ })
})
}
@@ -115,3 +121,17 @@ function needVersion(er, data) {
: (data && !data.version) ? new Error("No version provided")
: null
}
+
+function needPrivate (data, cb) {
+ var types = [ "dependencies"
+ , "devDependencies"
+ , "optionalDependencies" ]
+ asyncMap(types, function (type, cb) {
+ Object.keys(data[type] || {}).forEach(function (k) {
+ if (isGitFileUrl(data.dependencies[k]))
+ return cb(new Error("Publishing modules with git+file:// " +
+ "dependencies is not allowed."))
+ })
+ cb()
+ }, cb)
+}
View
9 lib/utils/is-git-file-url.js
@@ -0,0 +1,9 @@
+
+module.exports = isGitFileUrl
+
+var url = require("url")
+
+function isGitFileUrl (s) {
+ if (url.parse(s).protocol === "git+file:")
+ return true
+}
View
1  lib/utils/is-git-url.js
@@ -8,6 +8,7 @@ function isGitUrl (url) {
case "git+rsync:":
case "git+ftp:":
case "git+ssh:":
+ case "git+file:":
return true
}
}
View
93 test/tap/install-file-private.js
@@ -0,0 +1,93 @@
+// this test needs git installed
+
+var test = require("tap").test
+var npm = require("../../")
+var osenv = require("osenv")
+var path = require("path")
+var fs = require("fs")
+var rimraf = require("rimraf")
+var mkdirp = require("mkdirp")
+var path = require("path")
+
+var spawn = require("child_process").spawn
+var node = process.execPath
+
+var pkg = process.env.npm_config_tmp || osenv.tmpdir()
+pkg += path.sep + "install-file-private"
+
+var gitPkg = "npm-test-git"
+var gitPath = osenv.tmpdir() + path.sep + gitPkg
+
+test("it installs local gitrepos", function (t) {
+ writePackageJson()
+ prepareGitRepo(cb)
+
+ process.chdir(pkg)
+
+ function cb () {
+ npm.load({cache: pkg + "/cache"}, function () {
+ npm.install(".", function (err) {
+ var md = pkg + "/node_modules/git-file/README.md"
+ var content = fs.readFileSync(md, "utf8")
+ t.equal("just a test with git", content)
+ t.end()
+ })
+ })
+ }
+})
+
+test("cleanup", function (t) {
+ // windows fix for locked files
+ process.chdir(osenv.tmpdir())
+
+ rimraf.sync(pkg)
+ rimraf.sync(gitPath)
+ t.end()
+})
+
+// this package.json will require the git repo
+function writePackageJson () {
+ rimraf.sync(pkg)
+ mkdirp.sync(pkg)
+ mkdirp.sync(pkg + "/cache")
+
+ fs.writeFileSync(pkg + "/package.json", JSON.stringify({
+ "author": "Rocko Artischocko",
+ "private": true,
+ "name": "git-file",
+ "version": "0.0.0",
+ "dependencies": {
+ "testpackage": "git+file://" + gitPath
+ }
+ }), 'utf8')
+}
+
+// prepare git repo
+function prepareGitRepo (cb) {
+ rimraf.sync(gitPath)
+ mkdirp.sync(gitPath)
+ var opts = { cwd: gitPath }
+ fs.writeFileSync(gitPath + "/package.json", JSON.stringify({
+ "author": "Rocko Artischocko",
+ "private": true,
+ "name": "git-file",
+ "version": "0.0.0",
+ "description": "fixture"
+ }), 'utf8')
+
+ fs.writeFileSync(gitPath + "/README.md"
+ , "just a test with git", 'utf8')
+
+ var childInit = spawn("git", ["init"], opts)
+ var childAdd, childCommit
+ childInit.on("close", function () {
+ childAdd = spawn("git", ["add", "."], opts)
+ childAdd.on("close", function () {
+ childCommit = spawn("git"
+ , ["commit", "-n", "-m", "test"], opts)
+ childCommit.on("close", function () {
+ cb()
+ })
+ })
+ })
+}
View
26 test/tap/publish-file-nonprivate.js
@@ -0,0 +1,26 @@
+var fs = require("fs")
+var test = require("tap").test
+var rimraf = require("rimraf")
+var npm = require("../../")
+
+var pkg = __dirname + "/publish-file-nonprivate"
+
+test("it should return an error", function (t) {
+ rimraf.sync(pkg + "/node_modules")
+ process.chdir(pkg)
+
+ npm.load({cache: pkg + "/cache"}, function () {
+ npm.publish(".", function (err) {
+ t.ok(err)
+ t.equal(err.message, "Publishing modules with git+file:// " +
+ "dependencies is not allowed.")
+ t.end()
+ })
+ })
+})
+
+test("cleanup", function (t) {
+ rimraf.sync(pkg + "/node_modules")
+ rimraf.sync(pkg + "/cache")
+ t.end()
+})
View
1  test/tap/publish-file-nonprivate/README.md
@@ -0,0 +1 @@
+just a test
View
9 test/tap/publish-file-nonprivate/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "publish-file-nonprivate",
+ "author": "Rockbert",
+ "description": "fixture",
+ "version": "0.0.0",
+ "dependencies": {
+ "foo": "git+file://"
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.