From ba926a10f31ee74d5c07682f82941a1aadea9f00 Mon Sep 17 00:00:00 2001 From: Chris Rebert Date: Wed, 16 Dec 2015 20:57:23 -0800 Subject: [PATCH] Port #18402 to v3: s/grunt-sed/npm script/g Fixes #18338 [skip sauce] [skip validator] --- Gruntfile.js | 24 --------- grunt/change-version.js | 106 ++++++++++++++++++++++++++++++++++++++++ package.json | 3 +- 3 files changed, 108 insertions(+), 25 deletions(-) create mode 100755 grunt/change-version.js diff --git a/Gruntfile.js b/Gruntfile.js index c01f8a8ea9..927c1d4013 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -372,25 +372,6 @@ module.exports = function (grunt) { } }, - sed: { - versionNumber: { - pattern: (function () { - var old = grunt.option('oldver'); - return old ? RegExp.quote(old) : old; - })(), - replacement: grunt.option('newver'), - exclude: [ - 'dist/fonts', - 'docs/assets', - 'fonts', - 'js/tests/vendor', - 'node_modules', - 'test-infra' - ], - recursive: true - } - }, - 'saucelabs-qunit': { all: { options: { @@ -485,11 +466,6 @@ module.exports = function (grunt) { // Default task. grunt.registerTask('default', ['clean:dist', 'copy:fonts', 'test']); - // Version numbering task. - // grunt change-version-number --oldver=A.B.C --newver=X.Y.Z - // This can be overzealous, so its changes should always be manually reviewed! - grunt.registerTask('change-version-number', 'sed'); - grunt.registerTask('build-glyphicons-data', function () { generateGlyphiconsData.call(this, grunt); }); // task for building customizer diff --git a/grunt/change-version.js b/grunt/change-version.js new file mode 100755 index 0000000000..5e1681d3f9 --- /dev/null +++ b/grunt/change-version.js @@ -0,0 +1,106 @@ +#!/usr/bin/env node +'use strict'; + +/* globals Set */ +/*! + * Script to update version number references in the project. + * Copyright 2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +var fs = require('fs'); +var path = require('path'); +var sh = require('shelljs'); +sh.config.fatal = true; +var sed = sh.sed; + +// Blame TC39... https://github.com/benjamingr/RegExp.escape/issues/37 +RegExp.quote = function (string) { + return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'); +}; +RegExp.quoteReplacement = function (string) { + return string.replace(/[$]/g, '$$'); +}; + +var DRY_RUN = false; + +function walkAsync(directory, excludedDirectories, fileCallback, errback) { + if (excludedDirectories.has(path.parse(directory).base)) { + return; + } + fs.readdir(directory, function (err, names) { + if (err) { + errback(err); + return; + } + names.forEach(function (name) { + var filepath = path.join(directory, name); + fs.lstat(filepath, function (err, stats) { + if (err) { + process.nextTick(errback, err); + return; + } + if (stats.isSymbolicLink()) { + return; + } + else if (stats.isDirectory()) { + process.nextTick(walkAsync, filepath, excludedDirectories, fileCallback, errback); + } + else if (stats.isFile()) { + process.nextTick(fileCallback, filepath); + } + }); + }); + }); +} + +function replaceRecursively(directory, excludedDirectories, allowedExtensions, original, replacement) { + original = new RegExp(RegExp.quote(original), 'g'); + replacement = RegExp.quoteReplacement(replacement); + var updateFile = !DRY_RUN ? function (filepath) { + if (allowedExtensions.has(path.parse(filepath).ext)) { + sed('-i', original, replacement, filepath); + } + } : function (filepath) { + if (allowedExtensions.has(path.parse(filepath).ext)) { + console.log('FILE: ' + filepath); + } + else { + console.log('EXCLUDED:' + filepath); + } + }; + walkAsync(directory, excludedDirectories, updateFile, function (err) { + console.error('ERROR while traversing directory!:'); + console.error(err); + process.exit(1); + }); +} + +function main(args) { + if (args.length !== 2) { + console.error('USAGE: change-version old_version new_version'); + console.error('Got arguments:', args); + process.exit(1); + } + var oldVersion = args[0]; + var newVersion = args[1]; + var EXCLUDED_DIRS = new Set([ + '.git', + 'node_modules', + 'vendor' + ]); + var INCLUDED_EXTENSIONS = new Set([ + // This extension whitelist is how we avoid modifying binary files + '', + '.css', + '.html', + '.js', + '.json', + '.md', + '.scss', + '.txt', + '.yml' + ]); + replaceRecursively('.', EXCLUDED_DIRS, INCLUDED_EXTENSIONS, oldVersion, newVersion); +} + +main(process.argv.slice(2)); diff --git a/package.json b/package.json index 998088bc40..4e42506cce 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "homepage": "http://getbootstrap.com", "author": "Twitter, Inc.", "scripts": { + "change-version": "node grunt/change-version.js", "test": "grunt test" }, "style": "dist/css/bootstrap.css", @@ -52,10 +53,10 @@ "grunt-jekyll": "~0.4.2", "grunt-jscs": "~2.3.0", "grunt-saucelabs": "~8.6.1", - "grunt-sed": "twbs/grunt-sed#v0.2.0", "load-grunt-tasks": "~3.3.0", "markdown-it": "^5.0.0", "npm-shrinkwrap": "^200.4.0", + "shelljs": "^0.5.3", "time-grunt": "^1.2.1" }, "engines": {