diff --git a/src/config.coffee b/src/config.coffee index 3cf04d011..04a30254e 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -1,6 +1,7 @@ child_process = require 'child_process' fs = require 'fs' path = require 'path' +npm = require 'npm' module.exports = getHomeDirectory: -> @@ -81,3 +82,9 @@ module.exports = vs2010Path = path.join(@x86ProgramFilesDirectory(), "Microsoft Visual Studio 10.0", "Common7", "IDE") return '2010' if fs.existsSync(vs2010Path) + + getSetting: (key, callback) -> + npmOptions = + userconfig: @getUserConfigPath() + globalconfig: @getGlobalConfigPath() + npm.load npmOptions, -> callback(npm.config.get(key)) diff --git a/src/develop.coffee b/src/develop.coffee index bf475b793..e6d1811b7 100644 --- a/src/develop.coffee +++ b/src/develop.coffee @@ -54,16 +54,17 @@ class Develop extends Command callback("Request for package information failed: #{message}") cloneRepository: (repoUrl, packageDirectory, options) -> - command = "git" - args = ['clone', '--recursive', repoUrl, packageDirectory] - process.stdout.write "Cloning #{repoUrl} " - @spawn command, args, (code, stderr='', stdout='') => - if code is 0 - @logSuccess() - @installDependencies(packageDirectory, options) - else - @logFailure() - options.callback("#{stdout}\n#{stderr}".trim()) + config.getSetting 'git', (command) => + command ?= "git" + args = ['clone', '--recursive', repoUrl, packageDirectory] + process.stdout.write "Cloning #{repoUrl} " + @spawn command, args, (code, stderr='', stdout='') => + if code is 0 + @logSuccess() + @installDependencies(packageDirectory, options) + else + @logFailure() + options.callback("#{stdout}\n#{stderr}".trim()) installDependencies: (packageDirectory, options) -> process.chdir(packageDirectory) diff --git a/src/publish.coffee b/src/publish.coffee index c44f3e085..32abf2577 100644 --- a/src/publish.coffee +++ b/src/publish.coffee @@ -24,6 +24,7 @@ class Publish extends Command Usage: apm publish [ | major | minor | patch | build] apm publish --tag + apm publish --rename Publish a new version of the package in the current working directory. @@ -32,12 +33,16 @@ class Publish extends Command it is published to the apm registry. The HEAD branch and the new tag are pushed up to the remote repository automatically using this option. + If a new name is provided via the --rename flag, the package.json file is + updated with the new name and the package's name is updated on Atom.io. + Run `apm featured` to see all the featured packages or `apm view ` to see information about your package after you have published it. """ options.alias('h', 'help').describe('help', 'Print this usage message') options.alias('t', 'tag').string('tag').describe('tag', 'Specify a tag to publish') + options.alias('r', 'rename').string('rename').describe('rename', 'Specify a new name for the package') showHelp: (argv) -> @parseOptions(argv).showHelp() @@ -166,7 +171,7 @@ class Publish extends Command # tag - The string Git tag of the new version. # callback - The callback function to invoke with an error as the first # argument. - createPackageVersion: (packageName, tag, callback) -> + createPackageVersion: (packageName, tag, options, callback) -> Login.getTokenOrLogin (error, token) -> if error? callback(error) @@ -177,6 +182,7 @@ class Publish extends Command json: true body: tag: tag + rename: options.rename headers: authorization: token request.post requestSettings, (error, response, body={}) -> @@ -194,9 +200,12 @@ class Publish extends Command # tag - The Git tag string of the package version to publish. # callback - The callback function to invoke when done with an error as the # first argument. - publishPackage: (pack, tag, callback) -> - process.stdout.write "Publishing #{pack.name}@#{tag} " - @createPackageVersion pack.name, tag, (error) => + publishPackage: (pack, tag, remaining...) -> + options = remaining.shift() if remaining.length >= 2 + callback = remaining.shift() + + process.stdout.write "Publishing #{options.rename or pack.name}@#{tag} " + @createPackageVersion pack.name, tag, options, (error) => if error? @logFailure() callback(error) @@ -222,6 +231,11 @@ class Publish extends Command catch error throw new Error("Error parsing package.json file: #{error.message}") + saveMetadata: (pack, callback) -> + metadataPath = path.resolve('package.json') + metadataJson = JSON.stringify(pack, null, 2) + fs.writeFile(metadataPath, "#{metadataJson}\n", callback) + loadRepository: -> currentDirectory = process.cwd() @@ -240,11 +254,47 @@ class Publish extends Command unless upstreamUrl throw new Error('Package must pushed up to GitHub before publishing: https://help.github.com/articles/create-a-repo') + # Rename package if necessary + renamePackage: (pack, name, callback) -> + if name?.length > 0 + return callback('The new package name must be different than the name in the package.json file') if pack.name is name + + message = "Renaming #{pack.name} to #{name} " + process.stdout.write(message) + @setPackageName pack, name, (error) => + if error? + @logFailure() + return callback(error) + + config.getSetting 'git', (gitCommand) => + gitCommand ?= 'git' + @spawn gitCommand, ['add', 'package.json'], (code, stderr='', stdout='') => + unless code is 0 + @logFailure() + addOutput = "#{stdout}\n#{stderr}".trim() + return callback("`git add package.json` failed: #{addOutput}") + + @spawn gitCommand, ['commit', '-m', message], (code, stderr='', stdout='') => + if code is 0 + @logSuccess() + callback() + else + @logFailure() + commitOutput = "#{stdout}\n#{stderr}".trim() + callback("Failed to commit package.json: #{commitOutput}") + else + # Just fall through if the name is empty + callback() + + setPackageName: (pack, name, callback) -> + pack.name = name + @saveMetadata(pack, callback) + # Run the publish command with the given options run: (options) -> {callback} = options options = @parseOptions(options.commandArgs) - {tag} = options.argv + {tag, rename} = options.argv [version] = options.argv._ try @@ -257,22 +307,33 @@ class Publish extends Command catch error return callback(error) - if version?.length > 0 + if version?.length > 0 or rename?.length > 0 + version = 'patch' unless version?.length > 0 + originalName = pack.name if rename?.length > 0 + @registerPackage pack, (error, firstTimePublishing) => return callback(error) if error? - @versionPackage version, (error, tag) => + @renamePackage pack, rename, (error) => return callback(error) if error? - @pushVersion tag, (error) => + @versionPackage version, (error, tag) => return callback(error) if error? - @waitForTagToBeAvailable pack, tag, => + @pushVersion tag, (error) => + return callback(error) if error? + + @waitForTagToBeAvailable pack, tag, => - @publishPackage pack, tag, (error) => - if firstTimePublishing and not error? - @logFirstTimePublishMessage(pack) - callback(error) + if originalName? + # If we're renaming a package, we have to hit the API with the + # current name, not the new one, or it will 404. + rename = pack.name + pack.name = originalName + @publishPackage pack, tag, {rename: rename}, (error) => + if firstTimePublishing and not error? + @logFirstTimePublishMessage(pack) + callback(error) else if tag?.length > 0 @registerPackage pack, (error, firstTimePublishing) => return callback(error) if error? @@ -282,4 +343,4 @@ class Publish extends Command @logFirstTimePublishMessage(pack) callback(error) else - callback('Missing required tag to publish') + callback('A version, tag, or new package name is required')