Blame view

node_modules/bower/lib/core/scripts.js 3.36 KB
2dda2e10   Administrator   generator ignore
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  var mout = require('mout');
  var cmd = require('../util/cmd');
  var Q = require('q');
  var shellquote = require('shell-quote');
  
  var orderByDependencies = function (packages, installed, json) {
      var ordered = [];
      installed = mout.object.keys(installed);
  
      var depsSatisfied = function (packageName) {
          return mout.array.difference(mout.object.keys(packages[packageName].dependencies), installed, ordered).length === 0;
      };
  
      var depsFromBowerJson = json && json.dependencies ? mout.object.keys(json.dependencies) : [];
      var packageNames = mout.object.keys(packages);
  
      //get the list of the packages that are specified in bower.json in that order
      //its nice to maintain that order for users
      var desiredOrder = mout.array.intersection(depsFromBowerJson, packageNames);
      //then add to the end any remaining packages that werent in bower.json
      desiredOrder = desiredOrder.concat(mout.array.difference(packageNames, desiredOrder));
  
      //the desired order isn't necessarily a correct dependency specific order
      //so we ensure that below
      var resolvedOne = true;
      while (resolvedOne) {
  
          resolvedOne = false;
  
          for (var i = 0; i < desiredOrder.length; i++) {
              var packageName = desiredOrder[i];
              if (depsSatisfied(packageName)) {
                  ordered.push(packageName);
                  mout.array.remove(desiredOrder, packageName);
                  //as soon as we resolve a package start the loop again
                  resolvedOne = true;
                  break;
              }
          }
  
          if (!resolvedOne && desiredOrder.length > 0) {
              //if we're here then some package(s) doesn't have all its deps satisified
              //so lets just jam those names on the end
              ordered = ordered.concat(desiredOrder);
          }
  
      }
  
      return ordered;
  };
  
  var run = function (cmdString, action, logger, config) {
      logger.action(action, cmdString);
  
      //pass env + BOWER_PID so callees can identify a preinstall+postinstall from the same bower instance
      var env = mout.object.mixIn({ 'BOWER_PID': process.pid }, process.env);
      var args = shellquote.parse(cmdString, env);
      var cmdName = args[0];
      mout.array.remove(args, cmdName); //no rest() in mout
  
      var options = {
          cwd: config.cwd,
          env: env
      };
  
      var promise = cmd(cmdName, args, options);
  
      promise.progress(function (progress) {
          progress.split('\n').forEach(function (line) {
              if (line) {
                  logger.action(action, line);
              }
          });
      });
  
      return promise;
  };
  
  var hook = function (action, ordered, config, logger, packages, installed, json) {
      if (mout.object.keys(packages).length === 0 || !config.scripts || !config.scripts[action]) {
          return Q();
      }
  
      var orderedPackages = ordered ? orderByDependencies(packages, installed, json) : mout.object.keys(packages);
      var placeholder = new RegExp('%', 'g');
      var cmdString = mout.string.replace(config.scripts[action], placeholder, orderedPackages.join(' '));
      return run(cmdString, action, logger, config);
  };
  
  module.exports = {
      preuninstall: mout.function.partial(hook, 'preuninstall', false),
      preinstall: mout.function.partial(hook, 'preinstall', true),
      postinstall: mout.function.partial(hook, 'postinstall', true),
      //only exposed for test
      _orderByDependencies: orderByDependencies
  };