version.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. var semver = require('semver');
  2. var which = require('which');
  3. var fs = require('fs');
  4. var path = require('path');
  5. var Q = require('q');
  6. var execFile = require('child_process').execFile;
  7. var Project = require('../core/Project');
  8. var cli = require('../util/cli');
  9. var defaultConfig = require('../config');
  10. var createError = require('../util/createError');
  11. function version(logger, versionArg, options, config) {
  12. var project;
  13. config = defaultConfig(config);
  14. project = new Project(config, logger);
  15. return bump(project, versionArg, options.message);
  16. }
  17. function bump(project, versionArg, message) {
  18. var newVersion;
  19. var doGitCommit = false;
  20. return checkGit()
  21. .then(function (hasGit) {
  22. doGitCommit = hasGit;
  23. })
  24. .then(project.getJson.bind(project))
  25. .then(function (json) {
  26. newVersion = getNewVersion(json.version, versionArg);
  27. json.version = newVersion;
  28. })
  29. .then(project.saveJson.bind(project))
  30. .then(function () {
  31. if (doGitCommit) {
  32. return gitCommitAndTag(newVersion, message);
  33. }
  34. })
  35. .then(function () {
  36. console.log('v' + newVersion);
  37. });
  38. }
  39. function getNewVersion(currentVersion, versionArg) {
  40. var newVersion = semver.valid(versionArg);
  41. if (!newVersion) {
  42. newVersion = semver.inc(currentVersion, versionArg);
  43. }
  44. if (!newVersion) {
  45. throw createError('Invalid version argument: `' + versionArg + '`. Usage: `bower version [<newversion> | major | minor | patch]`', 'EINVALIDVERSION');
  46. }
  47. if (currentVersion === newVersion) {
  48. throw createError('Version not changed', 'EVERSIONNOTCHANGED');
  49. }
  50. return newVersion;
  51. }
  52. function checkGit() {
  53. var gitDir = path.join(process.cwd(), '.git');
  54. return Q.nfcall(fs.stat, gitDir)
  55. .then(function (stat) {
  56. if (stat.isDirectory()) {
  57. return checkGitStatus();
  58. }
  59. return false;
  60. }, function () {
  61. //Ignore not found .git directory
  62. return false;
  63. });
  64. }
  65. function checkGitStatus() {
  66. return Q.nfcall(which, 'git')
  67. .fail(function (err) {
  68. err.code = 'ENOGIT';
  69. throw err;
  70. })
  71. .then(function () {
  72. return Q.nfcall(execFile, 'git', ['status', '--porcelain'], {env: process.env});
  73. })
  74. .then(function (value) {
  75. var stdout = value[0];
  76. var lines = filterModifiedStatusLines(stdout);
  77. if (lines.length) {
  78. throw createError('Git working directory not clean.\n' + lines.join('\n'), 'EWORKINGDIRECTORYDIRTY');
  79. }
  80. return true;
  81. });
  82. }
  83. function filterModifiedStatusLines(stdout) {
  84. return stdout.trim().split('\n')
  85. .filter(function (line) {
  86. return line.trim() && !line.match(/^\?\? /);
  87. }).map(function (line) {
  88. return line.trim();
  89. });
  90. }
  91. function gitCommitAndTag(newVersion, message) {
  92. var tag = 'v' + newVersion;
  93. message = message || tag;
  94. message = message.replace(/%s/g, newVersion);
  95. return Q.nfcall(execFile, 'git', ['add', 'bower.json'], {env: process.env})
  96. .then(function () {
  97. return Q.nfcall(execFile, 'git', ['commit', '-m', message], {env: process.env});
  98. })
  99. .then(function () {
  100. return Q.nfcall(execFile, 'git', ['tag', tag, '-am', message], {env: process.env});
  101. });
  102. }
  103. // -------------------
  104. version.line = function (logger, argv) {
  105. var options = version.options(argv);
  106. return version(logger, options.argv.remain[1], options);
  107. };
  108. version.options = function (argv) {
  109. return cli.readOptions({
  110. 'message': { type: String, shorthand: 'm'}
  111. }, argv);
  112. };
  113. version.completion = function () {
  114. // TODO:
  115. };
  116. module.exports = version;