Merge branch '2836-only-clean-gitter.im-orphaned-rooms' into 'develop'
[gitter.git] / build-scripts / update-submodule-dependencies.js
blobf5a93967d80c7c9d0b57c81dca1dd200bf8415fa
1 #!/usr/bin/env node
2 'use strict';
4 var fs = require('fs');
5 var path = require('path');
7 // Note, this script can't use any third-party dependencies
8 // as we don't know the status of the package when we
9 // run it
11 function die(err) {
12   console.error(err.stack);
13   process.exit(1);
16 var basePackage = require(path.join(__dirname, '..', 'package.json'));
18 function stat(baseDirectory, files, callback) {
19   if (!files.length) return callback(null, {});
20   var stats = {};
21   var count = 0;
23   files.forEach(function(file) {
24     var fileName = path.join(baseDirectory, file);
25     fs.stat(fileName, function(err, stat) {
26       if (err) return callback(err);
27       stats[file] = stat;
28       count++;
29       if (count === files.length) {
30         callback(null, stats);
31       }
32     });
33   });
36 function checkDirectory(baseDirectory, callback) {
37   fs.readdir(baseDirectory, function(err, files) {
38     if (err) return die(err);
40     stat(baseDirectory, files, function(err, filesStat) {
41       if (filesStat['package.json']) {
42         return callback(null, path.join(baseDirectory, 'package.json'));
43       } else {
44         var directories = files
45           .filter(function(f) {
46             if (f === 'node_modules') return false;
47             return filesStat[f].isDirectory();
48           })
49           .map(function(f) {
50             return path.join(baseDirectory, f);
51           });
53         return callback(null, null, directories);
54       }
55     });
56   });
59 function searchNext(queue, results, callback) {
60   var next = queue.pop();
61   checkDirectory(next, function(err, packageJson, subDirectories) {
62     if (err) return callback(err);
63     if (packageJson) {
64       results.push(packageJson);
65     } else {
66       queue = queue.concat(subDirectories);
67     }
69     if (queue.length) {
70       searchNext(queue, results, callback);
71     } else {
72       callback(null, results);
73     }
74   });
77 function findChildModulePackages(queue, callback) {
78   if (queue.length === 0) return callback(null, []);
79   searchNext(queue, [], callback);
82 function findBaseDependency(name) {
83   if (basePackage.dependencies[name]) {
84     return basePackage.dependencies[name];
85   }
87   if (basePackage.devDependencies[name]) {
88     return basePackage.devDependencies[name];
89   }
92 function normalise(version, relativeTo) {
93   if (version.indexOf('file:') !== 0) return version;
94   var location = version.substring(5);
95   var j = path.normalize(path.join(__dirname, '../', location));
96   var relLocation = path.relative(path.dirname(relativeTo), j);
97   return 'file:' + relLocation;
100 function processDepsHash(hash, packageFile) {
101   var results = [];
102   if (!hash) return results;
103   Object.keys(hash).forEach(function(dependency) {
104     var baseVersion = findBaseDependency(dependency);
106     var baseVersionNormalised = normalise(baseVersion, packageFile);
107     if (baseVersionNormalised !== hash[dependency]) {
108       results.push({
109         name: dependency,
110         correctVersion: baseVersionNormalised,
111         currentVersion: hash[dependency]
112       });
113     }
114   });
116   return results;
119 function installUpdates(packageFile, isDev, changes) {
120   var wd = path.dirname(packageFile);
122   if (!changes || !changes.length) return;
124   var versions = changes
125     .map(function(c) {
126       var correctVersion = c.correctVersion;
127       if (correctVersion.charAt(0) === '^') {
128         correctVersion = correctVersion.substring(1);
129       }
130       return c.name + '@' + correctVersion;
131     })
132     .join(' ');
134   console.log(
135     '(cd ' +
136       wd +
137       '; npm i ' +
138       versions +
139       (isDev ? ' --save-dev' : ' --save') +
140       '; rm -rf node_modules)'
141   );
144 function updateDependenciesForPackage(packageFile) {
145   var packageJson = require(packageFile);
146   var prodChanges = processDepsHash(packageJson.dependencies, packageFile);
147   var devChanges = processDepsHash(packageJson.devDependencies, packageFile);
149   installUpdates(packageFile, false, prodChanges);
150   installUpdates(packageFile, true, devChanges);
153 findChildModulePackages(
154   [path.join(__dirname, '..', 'shared'), path.join(__dirname, '..', 'modules')],
155   function(err, results) {
156     if (err) return die(err);
158     results.forEach(function(packageFile) {
159       updateDependenciesForPackage(packageFile);
160     });
161   }