src/plugman/uninstall.js
function runUninstallPlatform (actions, platform, project_dir, plugin_dir, plugins_dir, options) {
    var pluginInfoProvider = options.pluginInfoProvider;
    // If this plugin is not really installed, return (CB-7004).
    if (!fs.existsSync(plugin_dir)) {
        return Promise.resolve(true);
    }

    var pluginInfo = pluginInfoProvider.get(plugin_dir);
    var plugin_id = pluginInfo.id;

    // Merge cli_variables and plugin.xml variables
    var variables = variableMerge.mergeVariables(plugin_dir, platform, options);

    // Deps info can be passed recusively
    var platformJson = PlatformJson.load(plugins_dir, platform);
    var depsInfo = options.depsInfo || dependencies.generateDependencyInfo(platformJson, plugins_dir, pluginInfoProvider);

    // Check that this plugin has no dependents.
    var dependents = dependencies.dependents(plugin_id, depsInfo, platformJson, pluginInfoProvider);

    if (options.is_top_level && dependents && dependents.length > 0) {
        var msg = 'The plugin \'' + plugin_id + '\' is required by (' + dependents.join(', ') + ')';
        if (options.force) {
            events.emit('warn', msg + ' but forcing removal');
        } else {
            return Promise.reject(new CordovaError(msg + ', skipping uninstallation. (try --force if trying to update)'));
        }
    }

    // Check how many dangling dependencies this plugin has.
    var deps = depsInfo.graph.getChain(plugin_id);
    var danglers = dependencies.danglers(plugin_id, depsInfo, platformJson, pluginInfoProvider);

    var promise;
    if (deps && deps.length && danglers && danglers.length) {

        // @tests - important this event is checked spec/uninstall.spec.js
        events.emit('log', 'Uninstalling ' + danglers.length + ' dependent plugins.');
        promise = promiseutil.Q_chainmap(danglers, function (dangler) {
            var dependent_path = path.join(plugins_dir, dangler);
            var opts = underscore.extend({}, options, {
                is_top_level: depsInfo.top_level_plugins.indexOf(dangler) > -1,
                depsInfo: depsInfo
            });

            return runUninstallPlatform(actions, platform, project_dir, dependent_path, plugins_dir, opts);
        });
    } else {
        promise = Promise.resolve();
    }

    var projectRoot = cordovaUtil.isCordova();

    if (projectRoot) {
        // CB-10708 This is the case when we're trying to uninstall plugin using plugman from specific
        // platform inside of the existing CLI project. This option is usually set by cordova-lib for CLI projects
        // but since we're running this code through plugman, we need to set it here implicitly
        options.usePlatformWww = true;
        options.cli_variables = variables;
    }

    return promise.then(function () {
        if (!projectRoot) return;

        var hooksRunner = new HooksRunner(projectRoot);
        var hooksRunnerOptions = {
            cordova: { platforms: [ platform ] },
            plugin: {
                id: pluginInfo.id,
                pluginInfo: pluginInfo,
                platform: platform,
                dir: plugin_dir
            }
        };
        return hooksRunner.fire('before_plugin_uninstall', hooksRunnerOptions);
    }).then(function () {
        return handleUninstall(actions, platform, pluginInfo, project_dir, options.www_dir, plugins_dir, options.is_top_level, options);
    });
}
function runUninstallPlatform (actions, platform, project_dir, plugin_dir, plugins_dir, options) {
    var pluginInfoProvider = options.pluginInfoProvider;
    // If this plugin is not really installed, return (CB-7004).
    if (!fs.existsSync(plugin_dir)) {
        return Promise.resolve(true);
    }

    var pluginInfo = pluginInfoProvider.get(plugin_dir);
    var plugin_id = pluginInfo.id;

    // Merge cli_variables and plugin.xml variables
    var variables = variableMerge.mergeVariables(plugin_dir, platform, options);

    // Deps info can be passed recusively
    var platformJson = PlatformJson.load(plugins_dir, platform);
    var depsInfo = options.depsInfo || dependencies.generateDependencyInfo(platformJson, plugins_dir, pluginInfoProvider);

    // Check that this plugin has no dependents.
    var dependents = dependencies.dependents(plugin_id, depsInfo, platformJson, pluginInfoProvider);

    if (options.is_top_level && dependents && dependents.length > 0) {
        var msg = 'The plugin \'' + plugin_id + '\' is required by (' + dependents.join(', ') + ')';
        if (options.force) {
            events.emit('warn', msg + ' but forcing removal');
        } else {
            return Promise.reject(new CordovaError(msg + ', skipping uninstallation. (try --force if trying to update)'));
        }
    }

    // Check how many dangling dependencies this plugin has.
    var deps = depsInfo.graph.getChain(plugin_id);
    var danglers = dependencies.danglers(plugin_id, depsInfo, platformJson, pluginInfoProvider);

    var promise;
    if (deps && deps.length && danglers && danglers.length) {

        // @tests - important this event is checked spec/uninstall.spec.js
        events.emit('log', 'Uninstalling ' + danglers.length + ' dependent plugins.');
        promise = promiseutil.Q_chainmap(danglers, function (dangler) {
            var dependent_path = path.join(plugins_dir, dangler);
            var opts = underscore.extend({}, options, {
                is_top_level: depsInfo.top_level_plugins.indexOf(dangler) > -1,
                depsInfo: depsInfo
            });

            return runUninstallPlatform(actions, platform, project_dir, dependent_path, plugins_dir, opts);
        });
    } else {
        promise = Promise.resolve();
    }

    var projectRoot = cordovaUtil.isCordova();

    if (projectRoot) {
        // CB-10708 This is the case when we're trying to uninstall plugin using plugman from specific
        // platform inside of the existing CLI project. This option is usually set by cordova-lib for CLI projects
        // but since we're running this code through plugman, we need to set it here implicitly
        options.usePlatformWww = true;
        options.cli_variables = variables;
    }

    return promise.then(function () {
        if (!projectRoot) return;

        var hooksRunner = new HooksRunner(projectRoot);
        var hooksRunnerOptions = {
            cordova: { platforms: [ platform ] },
            plugin: {
                id: pluginInfo.id,
                pluginInfo: pluginInfo,
                platform: platform,
                dir: plugin_dir
            }
        };
        return hooksRunner.fire('before_plugin_uninstall', hooksRunnerOptions);
    }).then(function () {
        return handleUninstall(actions, platform, pluginInfo, project_dir, options.www_dir, plugins_dir, options.is_top_level, options);
    });
}
possible options: cli_variables, www_dir, is_top_level Returns a promise