| |
| module.exports = owner |
| |
| owner.usage = "npm owner add <username> <pkg>" |
| + "\nnpm owner rm <username> <pkg>" |
| + "\nnpm owner ls <pkg>" |
| |
| owner.completion = function (opts, cb) { |
| var argv = opts.conf.argv.remain |
| if (argv.length > 4) return cb() |
| if (argv.length <= 2) { |
| var subs = ["add", "rm"] |
| if (opts.partialWord === "l") subs.push("ls") |
| else subs.push("ls", "list") |
| return cb(null, subs) |
| } |
| var un = encodeURIComponent(npm.config.get("username")) |
| switch (argv[2]) { |
| case "ls": |
| if (argv.length > 3) return cb() |
| else return registry.get("/-/short", cb) |
| |
| case "rm": |
| if (argv.length > 3) { |
| var theUser = encodeURIComponent(argv[3]) |
| , uri = "/-/by-user/"+theUser+"|"+un |
| console.error(uri) |
| return registry.get(uri, function (er, d) { |
| if (er) return cb(er) |
| // return the intersection |
| return cb(null, d[theUser].filter(function (p) { |
| // kludge for server adminery. |
| return un === "isaacs" || d[un].indexOf(p) === -1 |
| })) |
| }) |
| } |
| // else fallthrough |
| case "add": |
| if (argv.length > 3) { |
| var theUser = encodeURIComponent(argv[3]) |
| , uri = "/-/by-user/"+theUser+"|"+un |
| console.error(uri) |
| return registry.get(uri, function (er, d) { |
| console.error(uri, er || d) |
| // return mine that they're not already on. |
| if (er) return cb(er) |
| var mine = d[un] || [] |
| , theirs = d[theUser] || [] |
| return cb(null, mine.filter(function (p) { |
| return theirs.indexOf(p) === -1 |
| })) |
| }) |
| } |
| // just list all users who aren't me. |
| return registry.get("/-/users", function (er, list) { |
| if (er) return cb() |
| return cb(null, Object.keys(list).filter(function (n) { |
| return n !== un |
| })) |
| }) |
| |
| default: |
| return cb() |
| } |
| } |
| |
| var npm = require("./npm.js") |
| , registry = npm.registry |
| , log = require("npmlog") |
| , readJson = require("read-package-json") |
| |
| function owner (args, cb) { |
| var action = args.shift() |
| switch (action) { |
| case "ls": case "list": return ls(args[0], cb) |
| case "add": return add(args[0], args[1], cb) |
| case "rm": case "remove": return rm(args[0], args[1], cb) |
| default: return unknown(action, cb) |
| } |
| } |
| |
| function ls (pkg, cb) { |
| if (!pkg) return readLocalPkg(function (er, pkg) { |
| if (er) return cb(er) |
| if (!pkg) return cb(owner.usage) |
| ls(pkg, cb) |
| }) |
| |
| registry.get(pkg, function (er, data) { |
| var msg = "" |
| if (er) { |
| log.error("owner ls", "Couldn't get owner data", pkg) |
| return cb(er) |
| } |
| var owners = data.maintainers |
| if (!owners || !owners.length) msg = "admin party!" |
| else msg = owners.map(function (o) { return o.name +" <"+o.email+">" }).join("\n") |
| console.log(msg) |
| cb(er, owners) |
| }) |
| } |
| |
| function add (user, pkg, cb) { |
| if (!user) return cb(owner.usage) |
| if (!pkg) return readLocalPkg(function (er, pkg) { |
| if (er) return cb(er) |
| if (!pkg) return cb(new Error(owner.usage)) |
| add(user, pkg, cb) |
| }) |
| |
| log.verbose("owner add", "%s to %s", user, pkg) |
| mutate(pkg, user, function (u, owners) { |
| if (!owners) owners = [] |
| for (var i = 0, l = owners.length; i < l; i ++) { |
| var o = owners[i] |
| if (o.name === u.name) { |
| log.info( "owner add" |
| , "Already a package owner: "+o.name+" <"+o.email+">") |
| return false |
| } |
| } |
| owners.push(u) |
| return owners |
| }, cb) |
| } |
| |
| function rm (user, pkg, cb) { |
| if (!pkg) return readLocalPkg(function (er, pkg) { |
| if (er) return cb(er) |
| if (!pkg) return cb(new Error(owner.usage)) |
| rm(user, pkg, cb) |
| }) |
| |
| log.verbose("owner rm", "%s from %s", user, pkg) |
| mutate(pkg, null, function (u, owners) { |
| var found = false |
| , m = owners.filter(function (o) { |
| var match = (o.name === user) |
| found = found || match |
| return !match |
| }) |
| if (!found) { |
| log.info("owner rm", "Not a package owner: "+user) |
| return false |
| } |
| if (!m.length) return new Error( |
| "Cannot remove all owners of a package. Add someone else first.") |
| return m |
| }, cb) |
| } |
| |
| function mutate (pkg, user, mutation, cb) { |
| if (user) { |
| registry.get("/-/user/org.couchdb.user:"+user, mutate_) |
| } else { |
| mutate_(null, null) |
| } |
| |
| function mutate_ (er, u) { |
| if (!er && user && (!u || u.error)) er = new Error( |
| "Couldn't get user data for "+user+": "+JSON.stringify(u)) |
| |
| if (er) { |
| log.error("owner mutate", "Error getting user data for %s", user) |
| return cb(er) |
| } |
| |
| if (u) u = { "name" : u.name, "email" : u.email } |
| registry.get(pkg, function (er, data) { |
| if (er) { |
| log.error("owner mutate", "Error getting package data for %s", pkg) |
| return cb(er) |
| } |
| var m = mutation(u, data.maintainers) |
| if (!m) return cb() // handled |
| if (m instanceof Error) return cb(m) // error |
| data = { _id : data._id |
| , _rev : data._rev |
| , maintainers : m |
| } |
| registry.request("PUT" |
| , pkg+"/-rev/"+data._rev, data |
| , function (er, data) { |
| if (!er && data.error) er = new Error( |
| "Failed to update package metadata: "+JSON.stringify(data)) |
| if (er) { |
| log.error("owner mutate", "Failed to update package metadata") |
| } |
| cb(er, data) |
| }) |
| }) |
| } |
| } |
| |
| function readLocalPkg (cb) { |
| if (npm.config.get("global")) return cb() |
| var path = require("path") |
| readJson(path.resolve(npm.prefix, "package.json"), function (er, d) { |
| return cb(er, d && d.name) |
| }) |
| } |
| |
| function unknown (action, cb) { |
| cb("Usage: \n"+owner.usage) |
| } |