change-version.js 2.8 KB

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