Skip to content

Instantly share code, notes, and snippets.

@jaygarcia
Created January 7, 2014 18:18
Show Gist options
  • Save jaygarcia/8303968 to your computer and use it in GitHub Desktop.
Save jaygarcia/8303968 to your computer and use it in GitHub Desktop.
// possible options: cli_variables, www_dir, is_top_level
// Returns a promise.
var runInstall = module.exports.runInstall = function runInstall(actions, platform, project_dir, plugin_dir, plugins_dir, options) {
var xml_path = path.join(plugin_dir, 'plugin.xml')
, plugin_et = xml_helpers.parseElementtreeSync(xml_path)
, filtered_variables = {};
var name = plugin_et.findall('name').text;
var plugin_id = plugin_et.getroot().attrib['id'];
require('../plugman').emit('log', 'Starting installation of "' + plugin_id + '" for ' + platform);
// check if platform has plugin installed already.
var platform_config = config_changes.get_platform_json(plugins_dir, platform);
var plugin_basename = path.basename(plugin_dir);
var is_installed = false;
Object.keys(platform_config.installed_plugins).forEach(function(installed_plugin_id) {
if (installed_plugin_id == plugin_id) {
is_installed = true;
}
});
Object.keys(platform_config.dependent_plugins).forEach(function(installed_plugin_id) {
if (installed_plugin_id == plugin_id) {
is_installed = true;
}
});
if (is_installed) {
require('../plugman').emit('results', 'Plugin "' + plugin_id + '" already installed, \'sall good.');
return Q();
}
var theEngines = getEngines(plugin_et, platform, project_dir, plugin_dir);
return callEngineScripts(theEngines)
.then(checkEngines)
.then(function() {
// checking preferences, if certain variables are not provided, we should throw.
prefs = plugin_et.findall('./preference') || [];
prefs = prefs.concat(plugin_et.findall('./platform[@name="'+platform+'"]/preference'));
var missing_vars = [];
prefs.forEach(function (pref) {
var key = pref.attrib["name"].toUpperCase();
options.cli_variables = options.cli_variables || {};
if (options.cli_variables[key] == undefined)
missing_vars.push(key)
else
filtered_variables[key] = options.cli_variables[key]
});
if (missing_vars.length > 0) {
return Q.reject(new Error('Variable(s) missing: ' + missing_vars.join(", ")));
}
// Check for dependencies, (co)recurse to install each one
var dependencies = plugin_et.findall('dependency') || [];
dependencies = dependencies.concat(plugin_et.findall('./platform[@name="'+platform+'"]/dependency'));
if (dependencies && dependencies.length) {
require('../plugman').emit('verbose', 'Dependencies detected, iterating through them...');
var dep_plugin_id, dep_subdir, dep_git_ref;
return dependencies.reduce(function(soFar, dep) {
return soFar.then(function() {
dep_plugin_id = dep.attrib.id;
dep_subdir = dep.attrib.subdir;
var dep_url = dep.attrib.url;
dep_git_ref = dep.attrib.commit;
if (dep_subdir) {
dep_subdir = path.join.apply(null, dep_subdir.split('/'));
}
// Handle relative dependency paths by expanding and resolving them.
// The easy case of relative paths is to have a URL of '.' and a different subdir.
// TODO: Implement the hard case of different repo URLs, rather than the special case of
// same-repo-different-subdir.
if (dep_url == '.') {
// Look up the parent plugin's fetch metadata and determine the correct URL.
var fetchdata = require('./util/metadata').get_fetch_metadata(plugin_dir);
if (!fetchdata || !(fetchdata.source && fetchdata.source.type)) {
return Q.reject(new Error('No fetch metadata found for ' + plugin_id + '. Cannot install relative dependencies.'));
}
// Now there are two cases here: local directory, and git URL.
if (fetchdata.source.type === 'local') {
dep_url = fetchdata.source.path;
var d = Q.defer();
child_process.exec('git rev-parse --show-toplevel', { cwd:dep_url }, function(err, stdout, stderr) {
if (err) {
if (err.code == 128) {
return d.reject(new Error('Plugin ' + plugin_id + ' is not in git repository. All plugins must be in a git repository.'));
} else {
return d.reject(new Error('Failed to locate git repository for ' + plugin_id + ' plugin.'));
}
}
return d.resolve(stdout.trim());
});
return d.promise.then(function(git_repo) {
//Clear out the subdir since the url now contains it
var url = path.join(git_repo, dep_subdir);
dep_subdir = "";
return url;
});
} else if (fetchdata.source.type === 'git') {
return Q(fetchdata.source.url);
}
} else {
return Q(dep_url);
}
})
.then(function(dep_url) {
var dep_plugin_dir = path.join(plugins_dir, dep_plugin_id);
if (fs.existsSync(dep_plugin_dir)) {
require('../plugman').emit('verbose', 'Dependent plugin "' + dep_plugin_id + '" already fetched, using that version.');
var opts = {
cli_variables: filtered_variables,
www_dir: options.www_dir,
is_top_level: false
};
return runInstall(actions, platform, project_dir, dep_plugin_dir, plugins_dir, opts);
} else {
require('../plugman').emit('verbose', 'Dependent plugin "' + dep_plugin_id + '" not fetched, retrieving then installing.');
var opts = {
cli_variables: filtered_variables,
www_dir: options.www_dir,
is_top_level: false,
subdir: dep_subdir,
git_ref: dep_git_ref,
expected_id: dep_plugin_id
};
// CB-4770: registry fetching
if(dep_url === undefined) {
dep_url = dep_plugin_id;
}
return possiblyFetch(actions, platform, project_dir, dep_url, plugins_dir, opts);
}
});
}, Q())
.then(function() {
return handleInstall(actions, plugin_id, plugin_et, platform, project_dir, plugins_dir, plugin_basename, plugin_dir, filtered_variables, options.www_dir, options.is_top_level);
});
} else {
return handleInstall(actions, plugin_id, plugin_et, platform, project_dir, plugins_dir, plugin_basename, plugin_dir, filtered_variables, options.www_dir, options.is_top_level);
}
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment