最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【记录】研究搞懂gitbook内部调用npm去install插件的逻辑和相关代码

插件 crifan 3832浏览 0评论
折腾:
【未解决】给gitbook install的npm添加代理无效
期间,去研究
1
git install
输出的log
1
2
3
4
5
xxx@xxx  ~/dev/crifan/gitbook/gitbook_template/books/gitbook_demo   master ●  gitbook install
info: installing 18 plugins using npm@3.9.2
info:
info: installing plugin "google-adsense"
info: install plugin "google-adsense" (*) from NPM with version 0.1.0
另外,从报错中:
1
2
3
4
5
6
7
8
9
10
   at ReadStream.Readable.on (_stream_readable.js:849:29)
    at untarStream (/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/lib/fetch-package-metadata.js:304:8)
    at addShrinkwrap (/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/lib/fetch-package-metadata.js:200:3)
    at /Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/lib/fetch-package-metadata.js:185:14
    at /Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/node_modules/iferr/index.js:13:50
    at RES (/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/node_modules/inflight/inflight.js:23:14)
    at f (/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/node_modules/once/once.js:17:25)
    at /Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/lib/cache.js:362:16
    at /Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/node_modules/write-file-atomic/index.js:29:9
    at LOOP (/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/node_modules/slide/lib/chain.js:7:26)
可以看出:
内部调用到了:
1
/Users/xxx/.gitbook/versions/3.2.3
下面的npm
1
node_modules/npm
想要搞清楚内部npm内部如何用上代理。
/Users/xxx/.gitbook/versions/3.2.3/package.json
1
2
3
4
5
{
  "name": "gitbook",
  "version": "3.2.3",
  "homepage": "https://www.gitbook.com",
  "description": "Library and cmd utility to generate GitBooks",
其中的:
3.2.3是gitbook的版本
搜:
install
找到了:
/Users/xxx/.gitbook/versions/3.2.3/lib/cli/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
var buildEbook = require('./buildEbook');
 
 
module.exports = [
    require('./build'),
    require('./serve'),
    require('./install'),
    require('./parse'),
    require('./init'),
    buildEbook('pdf'),
    buildEbook('epub'),
    buildEbook('mobi')
];
除了install
还要很多,比如pdf/epub/mobi等格式,和之前的build/serve/init等命令
引用的是
/Users/xxx/.gitbook/versions/3.2.3/lib/cli/install.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var options = require('./options');
var getBook = require('./getBook');
 
 
var Parse = require('../parse');
var Plugins = require('../plugins');
 
 
module.exports = {
    name: 'install [book]',
    description: 'install all plugins dependencies',
    options: [
        options.log
    ],
    exec: function(args, kwargs) {
        var book = getBook(args, kwargs);
 
 
        return Parse.parseConfig(book)
        .then(function(resultBook) {
            return Plugins.installPlugins(resultBook);
        });
    }
};
此处引用的是:
Plugins.installPlugins
通过加了:
1
console.info("book=%o", book)
调试打印出:
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
 gitbook install
book=Record { "logger": [object Object], "fs": Record { "root": "/Users/xxx/dev/crifan/gitbook/gitbook_template/books/gitbook_demo", "fsExists": function fileExists(filename) {
    var d = Promise.defer();
 
 
    fs.exists(filename, function(exists) {
        d.resolve(exists);
    });
 
 
    return d.promise;
}, "fsReadFile": function () {
        var nodeArgs = baseArgs.concat(array_slice(arguments));
        var deferred = defer();
        nodeArgs.push(deferred.makeNodeResolver());
        Q(callback).fapply(nodeArgs).fail(deferred.reject);
        return deferred.promise;
    }, "fsStatFile": function () {
        var nodeArgs = baseArgs.concat(array_slice(arguments));
        var deferred = defer();
        nodeArgs.push(deferred.makeNodeResolver());
        Q(callback).fapply(nodeArgs).fail(deferred.reject);
        return deferred.promise;
    }, "fsReadDir": function fsReadDir(folder) {
    return fs.readdir(folder)
    .then(function(files) {
        files = Immutable.List(files);
 
 
        return files
            .map(function(file) {
                if (file == '.' || file == '..') return;
 
 
                var stat = fs.statSync(path.join(folder, file));
                if (stat.isDirectory()) file = file + path.sep;
                return file;
            })
            .filter(function(file) {
                return Boolean(file);
            });
    });
}, "fsLoadObject": function fsLoadObject(filename) {
    return fresh(filename, require);
}, "fsReadAsStream": function createReadStream (path, options) {
    return new ReadStream(path, options)
  } }, "ignore": Ignore { "ignore": [object Object] }, "config": Config { "file": Record { "path": "", "mtime": "Wed Jan 20 2021 21:04:04 GMT+0800 (中国标准时间)" }, "values": Map { "gitbook": "*", "theme": "default", "variables": Map {}, "plugins": List [], "pluginsConfig": Map {}, "structure": Map { "langs": "LANGS.md", "readme": "README.md", "glossary": "GLOSSARY.md", "summary": "SUMMARY.md" }, "pdf": Map { "pageNumbers": true, "fontSize": 12, "fontFamily": "Arial", "paperSize": "a4", "chapterMark": "pagebreak", "pageBreaksBefore": "/", "margin": Map { "right": 62, "left": 62, "top": 56, "bottom": 56 } } } }, "readme": Record { "file": Record { "path": "", "mtime": "Wed Jan 20 2021 21:04:04 GMT+0800 (中国标准时间)" }, "title": "", "description": "" }, "summary": Summary { "file": Record { "path": "", "mtime": "Wed Jan 20 2021 21:04:04 GMT+0800 (中国标准时间)" }, "parts": List [] }, "glossary": Record { "file": Record { "path": "", "mtime": "Wed Jan 20 2021 21:04:04 GMT+0800 (中国标准时间)" }, "entries": OrderedMap {} }, "languages": Record { "file": Record { "path": "", "mtime": "Wed Jan 20 2021 21:04:04 GMT+0800 (中国标准时间)" }, "list": OrderedMap {} }, "language": "", "books": OrderedMap {} }
(node:1340) [DEP0079] DeprecationWarning: Custom inspection function on Objects via .inspect() is deprecated
。。。
另外:
1
console.info("resultBook=%o", resultBook)
输出类似。
/Users/xxx/.gitbook/versions/3.2.3/lib/plugins/installPlugins.js
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
var npmi = require('npmi');
 
 
var DEFAULT_PLUGINS = require('../constants/defaultPlugins');
var Promise = require('../utils/promise');
var installPlugin = require('./installPlugin');
 
 
/**
    Install plugin requirements for a book
 
 
    @param {Book}
    @return {Promise<Number>}
*/
function installPlugins(book) {
    var logger = book.getLogger();
    var config = book.getConfig();
    var plugins = config.getPluginDependencies();
 
 
    // Remove default plugins
    // (only if version is same as installed)
    plugins = plugins.filterNot(function(plugin) {
        var dependency = DEFAULT_PLUGINS.find(function(dep) {
            return dep.getName() === plugin.getName();
        });
 
 
        return (
            // Disabled plugin
            !plugin.isEnabled() ||
 
 
            // Or default one installed in GitBook itself
            (dependency &&
            plugin.getVersion() === dependency.getVersion())
        );
    });
 
 
    if (plugins.size == 0) {
        logger.info.ln('nothing to install!');
        return Promise();
    }
 
 
    logger.info.ln('installing', plugins.size, 'plugins using npm@' + npmi.NPM_VERSION);
 
 
    return Promise.forEach(plugins, function(plugin) {
        return installPlugin(book, plugin);
    })
    .thenResolve(plugins.size);
}
 
 
module.exports = installPlugins;
去打印:
1
console.info("config=%o", config)
出:
1
config=Config { "file": Record { "path": "book.json", "mtime": Wed Jan 20 2021 16:47:19 GMT+0800 (中国标准时间) }, "values": Map { "plugins": List [ "google-adsense", "theme-comscore", "anchors", "-lunr", "-search", "search-plus", "disqus", "-highlight", "prism", "prism-themes", "github-buttons", "splitter", "-sharing", "sharing-plus", "tbfed-pagefooter", "expandable-chapters-small", "ga", "donate", "sitemap-general", "copy-code-button", "callouts", "toolbar-button" ], "root": "./src", "pluginsConfig": Map { "tbfed-pagefooter": Map { "copyright": "crifan.com,使用<a href='https://creativecommons.org/licenses/by/4.0/deed.zh'>署名4.0国际(CC BY 4.0)协议</a>发布", "modify_label": "最后更新:", "modify_format": "YYYY-MM-DD HH:mm:ss" }, "prism": Map { "css": List [ "prism-themes/themes/prism-atom-dark.css" ] }, "disqus": Map { "shortName": "crifan" }, "callouts": Map { "showTypeInHeader": false }, "toolbar-button": Map { "url": "http://book.crifan.com/books/gitbook_demo/pdf/gitbook_demo.pdf", "icon": "fa-file-pdf-o", "label": "下载PDF" }, "autocover": Map { "title": "Gitbook演示", "author": "Crifan Li <xxx>", "font": Map { "size": null, "family": "Impact", "color": "#FFF" }, "size": Map { "w": 1800, "h": 2360 }, "background": Map { "color": "#09F" } }, "donate": Map { "wechat": "https://www.crifan.com/files/res/crifan_com/crifan_wechat_pay.jpg", "alipay": "https://www.crifan.com/files/res/crifan_com/crifan_alipay_pay.jpg", "title": "", "button": "打赏", "alipayText": "支付宝打赏给Crifan", "wechatText": "微信打赏给Crifan" }, "sitemap-general": Map { "prefix": "https://book.crifan.com/gitbook/gitbook_demo/website/" }, "google-adsense": Map { "ads": List [ Map { "client": "ca-pub-6626240105039250" } ] }, "github-buttons": Map { "buttons": List [ Map { "repo": "gitbook_demo", "user": "crifan", "type": "star", "count": true, "size": "small" }, Map { "user": "crifan", "type": "follow", "width": "120", "count": false, "size": "small" } ] }, "ga": Map { "token": "UA-28297199-1" }, "sharing": Map { "qq": true, "all": List [ "douban", "facebook", "google", "instapaper", "line", "linkedin", "messenger", "pocket", "qq", "qzone", "stumbleupon", "twitter", "viber", "vk", "weibo", "whatsapp" ], "douban": false, "facebook": true, "weibo": true, "instapaper": false, "whatsapp": false, "hatenaBookmark": false, "twitter": true, "messenger": false, "line": false, "vk": false, "pocket": false, "google": false, "viber": false, "stumbleupon": false, "qzone": false, "linkedin": false }, "theme-default": Map { "showLevel": true } }, "theme": "default", "author": "Crifan Li <xxx>", "pdf": Map { "pageNumbers": true, "fontSize": 12, "fontFamily": "Arial", "paperSize": "a4", "chapterMark": "pagebreak", "pageBreaksBefore": "/", "margin": Map { "right": 62, "left": 62, "top": 56, "bottom": 56 } }, "structure": Map { "langs": "LANGS.md", "readme": "README.md", "glossary": "GLOSSARY.md", "summary": "SUMMARY.md" }, "variables": Map {}, "title": "Gitbook演示", "language": "zh-hans", "links": Map { "sidebar": Map { "主页": "https://www.crifan.com" } }, "gitbook": "3.2.3", "description": "crifan的Gitbook模版,用于演示如何用Gitbook创建一个自己的book电子书" } }
就是我们的gitbook_demo的配置
1
console.info("plugins=%o", plugins)
输出:
1
plugins=List [ PluginDependency { "name": "google-adsense", "version": "*", "enabled": true }, PluginDependency { "name": "theme-comscore", "version": "*", "enabled": true }, PluginDependency { "name": "anchors", "version": "*", "enabled": true }, PluginDependency { "name": "search-plus", "version": "*", "enabled": true }, PluginDependency { "name": "disqus", "version": "*", "enabled": true }, PluginDependency { "name": "prism", "version": "*", "enabled": true }, PluginDependency { "name": "prism-themes", "version": "*", "enabled": true }, PluginDependency { "name": "github-buttons", "version": "*", "enabled": true }, PluginDependency { "name": "splitter", "version": "*", "enabled": true }, PluginDependency { "name": "sharing-plus", "version": "*", "enabled": true }, PluginDependency { "name": "tbfed-pagefooter", "version": "*", "enabled": true }, PluginDependency { "name": "expandable-chapters-small", "version": "*", "enabled": true }, PluginDependency { "name": "ga", "version": "*", "enabled": true }, PluginDependency { "name": "donate", "version": "*", "enabled": true }, PluginDependency { "name": "sitemap-general", "version": "*", "enabled": true }, PluginDependency { "name": "copy-code-button", "version": "*", "enabled": true }, PluginDependency { "name": "callouts", "version": "*", "enabled": true }, PluginDependency { "name": "toolbar-button", "version": "*", "enabled": true } ]
是此处的插件列表
继续:
/Users/xxx/.gitbook/versions/3.2.3/lib/plugins/installPlugin.js
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
var npmi = require('npmi');
 
 
var Promise = require('../utils/promise');
var resolveVersion = require('./resolveVersion');
 
 
/**
    Install a plugin for a book
 
 
    @param {Book}
    @param {PluginDependency}
    @return {Promise}
*/
function installPlugin(book, plugin) {
    var logger = book.getLogger();
 
 
    var installFolder = book.getRoot();
    var name = plugin.getName();
    var requirement = plugin.getVersion();
 
 
    logger.info.ln('');
    logger.info.ln('installing plugin "' + name + '"');
 
 
    // Find a version to install
    return resolveVersion(plugin)
    .then(function(version) {
        if (!version) {
            throw new Error('Found no satisfactory version for plugin "' + name + '" with requirement "' + requirement + '"');
        }
 
 
        logger.info.ln('install plugin "' + name +'" (' + requirement + ') from NPM with version', version);
        return Promise.nfcall(npmi, {
            'name': plugin.getNpmID(),
            'version': version,
            'path': installFolder,
            'npmLoad': {
                'loglevel': 'silent',
                'loaded': true,
                'prefix': installFolder
            }
        });
    })
    .then(function() {
        logger.info.ok('plugin "' + name + '" installed with success');
    });
}
 
 
module.exports = installPlugin;
貌似核心的是:
1
return Promise.nfcall(npmi, {
看到函数原型是:
/Users/xxx/Library/Caches/typescript/4.1/node_modules/@types/q/index.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
    /**
     * Calls a Node.js-style function with the given variadic arguments, returning a promise that is fulfilled if the
     * Node.js function calls back with a result, or rejected if it calls back with an error
     * (or throws one synchronously). An example:
     *
     * @example
     * Q.nfcall(FS.readFile, "foo.txt", "utf-8").done(function (text) {
     * });
     *
     * The same warning about functions vs. methods applies for nfcall as it does for nfapply. In this case, the better
     * strategy would be to use Q.ninvoke.
     */
    export function nfcall<T>(nodeFunction: (...args: any[]) => any, ...args: any[]): Promise<T>;
此处:
  • nodeFunction=npmi
  • args = 此处json=dict
1
2
3
4
5
6
7
8
9
{
            'name': plugin.getNpmID(),
            'version': version,
            'path': installFolder,
            'npmLoad': {
                'loglevel': 'silent',
                'loaded': true,
                'prefix': installFolder
            }
/Users/xxx/.gitbook/versions/3.2.3/node_modules/npmi/npmi.js
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
var npm    = require('npm');
var fs     = require('fs');
var path   = require('path');
var semver = require('semver');
 
 
var LOAD_ERR    = 'NPM_LOAD_ERR',
    INSTALL_ERR = 'NPM_INSTALL_ERR',
    VIEW_ERR    = 'NPM_VIEW_ERR';
 
 
/**
 * Created with IntelliJ IDEA.
 * User: leiko
 * Date: 30/01/14
 * Time: 10:28
 */
var npmi = function (options, callback) {
    callback = callback || function () {};
 
 
    var name         = options.name,
        pkgName      = options.pkgName || name,
        version      = options.version || 'latest',
        installPath  = options.path || '.',
        forceInstall = options.forceInstall || false,
        localInstall = options.localInstall || false,
        npmLoad      = options.npmLoad || {loglevel: 'silent'},
        savedPrefix  = null;
 
    function viewCallback(installedVersion)  {
 
。。。
    function checkInstalled(isTarball) {
 
。。。
    function installCallback(err, result) {
        // reset npm.prefix to saved value
        npm.prefix = savedPrefix;
 
 
        if (err) {
            err.code = INSTALL_ERR;
        }
 
 
        callback(err, result);
    }
 
。。。
    function loadCallback(err) {
。。。
npmi.LOAD_ERR    = LOAD_ERR;
npmi.INSTALL_ERR = INSTALL_ERR;
npmi.VIEW_ERR    = VIEW_ERR;
 
 
npmi.NPM_VERSION = npm.version;
 
 
module.exports = npmi;
感觉是:
此处报错就是调用了installCallback,发生了error
试试:
1
2
3
        // callback(err, result);
        console.info("err=%o", err)
        console.info("result=%o", result)
输出:
好像没有多余输出。
另外去看:
loadCallback
1
        console.info("loadCallback:err=%o", err)
没有
1
        console.info("checkInstalled: isTarball=%o", isTarball)
结果:
没有
1
2
    function viewCallback(installedVersion)  {
        console.info("viewCallback: installedVersion=%o", installedVersion)
也没有。
1
2
var npmi = function (options, callback) {
    console.info("npmi: options=%o", options)
结果:也没有。
看来不是这个文件。
1
console.info("in npmi")
有输出,确定是加载了:
/Users/xxx/.gitbook/versions/3.2.3/node_modules/npmi/npmi.js
搜npmi
找到
/Users/xxx/.gitbook/versions/3.2.3/package.json
1
2
    "npm": "3.9.2",
    "npmi": "2.0.1",
1
2
3
    console.info("npmLoad=%o", npmLoad)
    console.info("loadCallback=%o", loadCallback)
    npm.load(npmLoad, loadCallback);
结果:没有
/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/package.json
1
2
3
  "bin": {
    "npm": "./bin/npm-cli.js"
  },
去看看
/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/bin/npm-cli.js
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#!/usr/bin/env node
;(function () { // wrapper in case we're in module_context mode
  // windows: running "npm blah" in this folder will invoke WSH, not node.
  /*global WScript*/
  if (typeof WScript !== 'undefined') {
    WScript.echo(
      'npm does not work when run\n' +
        'with the Windows Scripting Host\n\n' +
        "'cd' to a different directory,\n" +
        "or type 'npm.cmd <args>',\n" +
        "or type 'node npm <args>'."
    )
    WScript.quit(1)
    return
  }
 
 
  process.title = 'npm'
 
 
  var log = require('npmlog')
  log.pause() // will be unpaused when config is loaded.
 
 
  log.info('it worked if it ends with', 'ok')
 
 
  var path = require('path')
  var npm = require('../lib/npm.js')
  var npmconf = require('../lib/config/core.js')
  var errorHandler = require('../lib/utils/error-handler.js')
 
 
  var configDefs = npmconf.defs
  var shorthands = configDefs.shorthands
  var types = configDefs.types
  var nopt = require('nopt')
 
 
  // if npm is called as "npmg" or "npm_g", then
  // run in global mode.
  if (path.basename(process.argv[1]).slice(-1) === 'g') {
    process.argv.splice(1, 1, 'npm', '-g')
  }
 
 
  log.verbose('cli', process.argv)
 
 
  var conf = nopt(types, shorthands)
  npm.argv = conf.argv.remain
  if (npm.deref(npm.argv[0])) npm.command = npm.argv.shift()
  else conf.usage = true
 
 
  if (conf.version) {
    console.log(npm.version)
    return
  }
 
 
  if (conf.versions) {
    npm.command = 'version'
    conf.usage = false
    npm.argv = []
  }
 
 
  log.info('using', 'npm@%s', npm.version)
  log.info('using', 'node@%s', process.version)
 
 
  process.on('uncaughtException', errorHandler)
 
 
  if (conf.usage && npm.command !== 'help') {
    npm.argv.unshift(npm.command)
    npm.command = 'help'
  }
 
 
  // now actually fire up npm and run the command.
  // this is how to use npm programmatically:
  conf._exit = true
  npm.load(conf, function (er) {
    if (er) return errorHandler(er)
    npm.commands[npm.command](npm.argv, errorHandler)
  })
})()
 
#!/usr/bin/env node
;(function () { // wrapper in case we're in module_context mode
  // windows: running "npm blah" in this folder will invoke WSH, not node.
  /*global WScript*/
  if (typeof WScript !== 'undefined') {
    WScript.echo(
      'npm does not work when run\n' +
        'with the Windows Scripting Host\n\n' +
        "'cd' to a different directory,\n" +
        "or type 'npm.cmd <args>',\n" +
        "or type 'node npm <args>'."
    )
    WScript.quit(1)
    return
  }
 
 
  process.title = 'npm'
 
 
  var log = require('npmlog')
  log.pause() // will be unpaused when config is loaded.
 
 
  log.info('it worked if it ends with', 'ok')
 
 
  var path = require('path')
  var npm = require('../lib/npm.js')
  var npmconf = require('../lib/config/core.js')
  var errorHandler = require('../lib/utils/error-handler.js')
 
 
  var configDefs = npmconf.defs
  var shorthands = configDefs.shorthands
  var types = configDefs.types
  var nopt = require('nopt')
 
 
  // if npm is called as "npmg" or "npm_g", then
  // run in global mode.
  if (path.basename(process.argv[1]).slice(-1) === 'g') {
    process.argv.splice(1, 1, 'npm', '-g')
  }
 
 
  log.verbose('cli', process.argv)
 
 
  var conf = nopt(types, shorthands)
  npm.argv = conf.argv.remain
  if (npm.deref(npm.argv[0])) npm.command = npm.argv.shift()
  else conf.usage = true
 
 
  if (conf.version) {
    console.log(npm.version)
    return
  }
 
 
  if (conf.versions) {
    npm.command = 'version'
    conf.usage = false
    npm.argv = []
  }
 
 
  log.info('using', 'npm@%s', npm.version)
  log.info('using', 'node@%s', process.version)
 
 
  process.on('uncaughtException', errorHandler)
 
 
  if (conf.usage && npm.command !== 'help') {
    npm.argv.unshift(npm.command)
    npm.command = 'help'
  }
 
 
  // now actually fire up npm and run the command.
  // this is how to use npm programmatically:
  conf._exit = true
  npm.load(conf, function (er) {
    if (er) return errorHandler(er)
    npm.commands[npm.command](npm.argv, errorHandler)
  })
})()
另外还有
/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/bin/npm.cmd
/Users/xxx/.gitbook/versions/3.2.3/node_modules/npm/bin/npm
1
  console.info("in versions/3.2.3/node_modules/npm/bin/npm-cli.js")
结果:没输出。
回去注意到
/Users/xxx/.gitbook/versions/3.2.3/lib/plugins/installPlugin.js
1
2
3
    // Find a version to install
    return resolveVersion(plugin)
    .then(function(version) {
去看看
/Users/xxx/.gitbook/versions/3.2.3/lib/plugins/resolveVersion.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
    Resolve a plugin dependency to a version
 
 
    @param {PluginDependency} plugin
    @return {Promise<String>}
*/
function resolveVersion(plugin) {
    var npmId = Plugin.nameToNpmID(plugin.getName());
    var requiredVersion = plugin.getVersion();
 
 
    if (plugin.isGitDependency()) {
        return Promise.resolve(requiredVersion);
    }
...
用:
1
2
function resolveVersion(plugin) {
    console.info("plugin=%o", plugin)
输出:
1
plugin=PluginDependency { "name": "google-adsense", "version": "*", "enabled": true }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function resolveVersion(plugin) {
    console.info("plugin=%o", plugin)
     
    var npmId = Plugin.nameToNpmID(plugin.getName());
    console.info("npmId=%o", npmId)
    var requiredVersion = plugin.getVersion();
    console.info("requiredVersion=%o", requiredVersion)
 
 
    if (plugin.isGitDependency()) {
        console.info("plugin.isGitDependency is True")
        return Promise.resolve(requiredVersion);
    }
 
 
    return initNPM()
    .then(function() {
        console.info("complete initNPM")
        console.info("npm.commands=%o", npm.commands)
        console.info("npm.commands.view=%o", npm.commands.view)
        return Promise.nfcall(npm.commands.view, [npmId + '@' + requiredVersion, 'engines'], true);
    })
输出:
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
plugin=PluginDependency { "name": "google-adsense", "version": "*", "enabled": true }
npmId='gitbook-plugin-google-adsense'
requiredVersion='*'
(node:2659) [DEP0079] DeprecationWarning: Custom inspection function on Objects via .inspect() is deprecated
complete initNPM
npm.commands={ [ac]: [Getter],
  [acc]: [Getter],
  [acce]: [Getter],
  [acces]: [Getter],
  access: [Getter],
  [add-]: [Getter],
  [add-u]: [Getter],
。。。
  [whoam]: [Getter],
  whoami: [Getter],
  [build]: [Getter],
  [unbuild]: [Getter],
  [xmas]: [Getter],
  [substack]: [Getter],
  [visnup]: [Getter] }
npm.commands.view={ [Function]
  [length]: 0,
  [name]: '',
  [arguments]: null,
  [caller]: null,
  [prototype]: { [constructor]: [Circular] },
  usage:
   'npm view [<@scope>/]<pkg>[@<version>] [<field>[.subfield]...]\n\naliases: v, info, show',
  completion:
   { [Function]
     [length]: 2,
     [name]: '',
     [arguments]: null,
     [caller]: null,
     [prototype]: { [constructor]: [Circular] } } }
看到是:
1
npm view [<@scope>/]<pkg>[@<version>] [<field>[.subfield]...]\n\naliases: v, info, show
想到去:
1
2
3
xxx@xxx  ~/.gitbook/versions/3.2.3/node_modules/npm  bin/npm-cli.js --version
in versions/3.2.3/node_modules/npm/bin/npm-cli.js
3.9.2
-》实现了我们希望的,至少找到了:npm对应的二进制是哪个

转载请注明:在路上 » 【记录】研究搞懂gitbook内部调用npm去install插件的逻辑和相关代码

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
80 queries in 0.510 seconds, using 22.24MB memory