function fetchPlugin()

in src/plugman/fetch.js [40:173]


function fetchPlugin (plugin_src, plugins_dir, options) {
    // Ensure the containing directory exists.
    fs.ensureDirSync(plugins_dir);
    options = options || {};
    options.subdir = options.subdir || '.';
    options.searchpath = options.searchpath || [];
    if (typeof options.searchpath === 'string') {
        options.searchpath = options.searchpath.split(path.delimiter);
    }

    const pluginInfoProvider = options.pluginInfoProvider || new PluginInfoProvider();

    // clone from git repository
    // @todo Use 'url.URL' constructor instead since 'url.parse' was deprecated since v11.0.0
    var uri = url.parse(plugin_src); // eslint-disable-line

    // If the hash exists, it has the form from npm: http://foo.com/bar#git-ref[:subdir]
    // git-ref can be a commit SHA, a tag, or a branch
    // NB: No leading or trailing slash on the subdir.
    if (uri.hash) {
        const result = uri.hash.match(/^#([^:]*)(?::\/?(.*?)\/?)?$/);
        if (result) {
            if (result[1]) { options.git_ref = result[1]; }
            if (result[2]) { options.subdir = result[2]; }
        }
    }
    return Promise.resolve().then(function () {
        let plugin_dir = cordovaUtil.fixRelativePath(path.join(plugin_src, options.subdir));
        return Promise.resolve().then(function () {
            // check if it is a local path
            if (fs.existsSync(plugin_dir)) {
                if (!fs.existsSync(path.join(plugin_dir, 'package.json'))) {
                    return Promise.reject(new CordovaError('Invalid Plugin! ' + plugin_dir + ' needs a valid package.json'));
                }

                projectRoot = path.join(plugins_dir, '..');
                // Plugman projects need to go up two directories to reach project root.
                // Plugman projects have an options.projectRoot variable
                if (options.projectRoot) {
                    projectRoot = options.projectRoot;
                }
                return fetch(path.resolve(plugin_dir), projectRoot, options)
                    .then(function (directory) {
                        return {
                            pinfo: pluginInfoProvider.get(directory),
                            fetchJsonSource: {
                                type: 'local',
                                path: directory
                            }
                        };
                    }).catch(function (error) {
                        // something went wrong with cordova-fetch
                        return Promise.reject(new CordovaError(error.message));
                    });
            }
            // If there is no such local path or it's a git URL, it's a plugin id or id@versionspec.
            // First look for it in the local search path (if provided).
            const pinfo = findLocalPlugin(plugin_src, options.searchpath, pluginInfoProvider);
            if (pinfo) {
                events.emit('verbose', 'Found ' + plugin_src + ' at ' + pinfo.dir);
                return {
                    pinfo,
                    fetchJsonSource: {
                        type: 'local',
                        path: pinfo.dir
                    }
                };
            } else if (options.noregistry) {
                return Promise.reject(new CordovaError(
                    'Plugin ' + plugin_src + ' not found locally. ' +
                    'Note, plugin registry was disabled by --noregistry flag.'
                ));
            }
            // If not found in local search path, fetch from the registry.
            const parsedSpec = pluginSpec.parse(plugin_src);
            let P;
            let skipCopyingPlugin;
            plugin_dir = path.join(plugins_dir, parsedSpec.id);
            // if the plugin has already been fetched, use it.
            if (fs.existsSync(plugin_dir)) {
                P = Promise.resolve(plugin_dir);
                skipCopyingPlugin = true;
            } else {
                // use cordova-fetch
                projectRoot = path.join(plugins_dir, '..');
                // Plugman projects need to go up two directories to reach project root.
                // Plugman projects have an options.projectRoot variable
                if (options.projectRoot) {
                    projectRoot = options.projectRoot;
                }

                P = fetch(plugin_src, projectRoot, options);
                skipCopyingPlugin = false;
            }
            return P
                .catch(function (error) {
                    const message = 'Failed to fetch plugin ' + plugin_src + ' via registry.' +
                        '\nProbably this is either a connection problem, or plugin spec is incorrect.' +
                        '\nCheck your connection and plugin name/version/URL.' +
                        '\n' + error;
                    return Promise.reject(new CordovaError(message));
                })
                .then(function (dir) {
                    return {
                        pinfo: pluginInfoProvider.get(dir),
                        fetchJsonSource: {
                            type: 'registry',
                            id: plugin_src
                        },
                        skipCopyingPlugin
                    };
                });
        }).then(function (result) {
            options.plugin_src_dir = result.pinfo.dir;
            let P;
            if (result.skipCopyingPlugin) {
                P = Promise.resolve(options.plugin_src_dir);
            } else {
                P = Promise.resolve(copyPlugin(result.pinfo, plugins_dir, options.link && result.fetchJsonSource.type === 'local'));
            }
            return P.then(function (dir) {
                result.dest = dir;
                return result;
            });
        });
    }).then(function (result) {
        checkID(options.expected_id, result.pinfo);
        const data = { source: result.fetchJsonSource };
        data.is_top_level = options.is_top_level;
        data.variables = options.variables || {};
        metadata.save_fetch_metadata(plugins_dir, result.pinfo.id, data);
        return result.dest;
    });
}