change-version.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #!/usr/bin/env node
  2. 'use strict';
  3. /*!
  4. * Script to update version number references in the project.
  5. * Copyright 2015 The Bootstrap Authors
  6. * Copyright 2015 Twitter, Inc.
  7. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  8. */
  9. var fs = require('fs');
  10. var path = require('path');
  11. var sh = require('shelljs');
  12. sh.config.fatal = true;
  13. var sed = sh.sed;
  14. // Blame TC39... https://github.com/benjamingr/RegExp.escape/issues/37
  15. RegExp.quote = function (string) {
  16. return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
  17. };
  18. RegExp.quoteReplacement = function (string) {
  19. return string.replace(/[$]/g, '$$');
  20. };
  21. var DRY_RUN = false;
  22. function walkAsync(directory, excludedDirectories, fileCallback, errback) {
  23. if (excludedDirectories.has(path.parse(directory).base)) {
  24. return;
  25. }
  26. fs.readdir(directory, function (err, names) {
  27. if (err) {
  28. errback(err);
  29. return;
  30. }
  31. names.forEach(function (name) {
  32. var filepath = path.join(directory, name);
  33. fs.lstat(filepath, function (err, stats) {
  34. if (err) {
  35. process.nextTick(errback, err);
  36. return;
  37. }
  38. if (stats.isSymbolicLink()) {
  39. return;
  40. }
  41. else if (stats.isDirectory()) {
  42. process.nextTick(walkAsync, filepath, excludedDirectories, fileCallback, errback);
  43. }
  44. else if (stats.isFile()) {
  45. process.nextTick(fileCallback, filepath);
  46. }
  47. });
  48. });
  49. });
  50. }
  51. function replaceRecursively(directory, excludedDirectories, allowedExtensions, original, replacement) {
  52. original = new RegExp(RegExp.quote(original), 'g');
  53. replacement = RegExp.quoteReplacement(replacement);
  54. var updateFile = !DRY_RUN ? function (filepath) {
  55. if (allowedExtensions.has(path.parse(filepath).ext)) {
  56. sed('-i', original, replacement, filepath);
  57. }
  58. } : function (filepath) {
  59. if (allowedExtensions.has(path.parse(filepath).ext)) {
  60. console.log('FILE: ' + filepath);
  61. }
  62. else {
  63. console.log('EXCLUDED:' + filepath);
  64. }
  65. };
  66. walkAsync(directory, excludedDirectories, updateFile, function (err) {
  67. console.error('ERROR while traversing directory!:');
  68. console.error(err);
  69. process.exit(1);
  70. });
  71. }
  72. function main(args) {
  73. if (args.length !== 2) {
  74. console.error('USAGE: change-version old_version new_version');
  75. console.error('Got arguments:', args);
  76. process.exit(1);
  77. }
  78. var oldVersion = args[0];
  79. var newVersion = args[1];
  80. var EXCLUDED_DIRS = new Set([
  81. '.git',
  82. 'node_modules',
  83. 'vendor'
  84. ]);
  85. var INCLUDED_EXTENSIONS = new Set([
  86. // This extension whitelist is how we avoid modifying binary files
  87. '',
  88. '.css',
  89. '.html',
  90. '.js',
  91. '.json',
  92. '.md',
  93. '.scss',
  94. '.txt',
  95. '.yml'
  96. ]);
  97. replaceRecursively('.', EXCLUDED_DIRS, INCLUDED_EXTENSIONS, oldVersion, newVersion);
  98. }
  99. main(process.argv.slice(2));