<commit_before>var glob = require('glob');
var path = require('path');
var fs = require('graceful-fs');
var Q = require('q');
var mout = require('mout');
var rimraf = require('rimraf');
var endpointParser = require('bower-endpoint-parser');
var Logger = require('bower-logger');
var Manager = require('./Manager');
var defaultConfig = require('../config');
var semver = require('../util/semver');
var md5 = require('../util/md5');
var createError = require('../util/createError');
var readJson = require('../util/readJson');
var validLink = require('../util/validLink');
var scripts = require('./scripts');

function Project(config, logger) {
    // This is the only architecture component that ensures defaults
    // on config and logger
    // The reason behind it is that users can likely use this component
    // directly if commands do not fulfil their needs
    this._config = defaultConfig(config);
    this._logger = logger || new Logger();
    this._manager = new Manager(this._config, this._logger);

    this._options = {};
}

// -----------------

Project.prototype.install = function (decEndpoints, options, config) {
    var that = this;
    var targets = [];
    var resolved = {};
    var incompatibles = [];

    // If already working, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    this._options = options || {};
    this._config = config || {};
    this._working = true;

    // Analyse the project
    return this._analyse()
    .spread(function (json, tree) {
        // It shows an error when issuing `bower install`
        // and no bower.json is present in current directory
        if(!that._jsonFile && decEndpoints.length === 0 ) {
            throw createError('No bower.json present', 'ENOENT');
        }

        // Recover tree
        that.walkTree(tree, function (node, name) {
            if (node.incompatible) {
                incompatibles.push(node);
            } else if (node.missing || node.different || that._config.force) {
                targets.push(node);
            } else {
                resolved[name] = node;
            }
        }, true);

        // Add decomposed endpoints as targets
        decEndpoints = decEndpoints || [];
        decEndpoints.forEach(function (decEndpoint) {
            // Mark as new so that a conflict for this target
            // always require a choice
            // Also allows for the target to be converted in case
            // of being *
            decEndpoint.newly = true;
            targets.push(decEndpoint);
        });

        // Bootstrap the process
        return that._bootstrap(targets, resolved, incompatibles);
    })
    .then(function () {
        return that._manager.preinstall(that._json);
    })
    .then(function () {
        return that._manager.install(that._json);
    })
    .then(function (installed) {
        // Handle save and saveDev options
        if (that._options.save || that._options.saveDev) {
            // Cycle through the specified endpoints
            decEndpoints.forEach(function (decEndpoint) {
                var jsonEndpoint;

                jsonEndpoint = endpointParser.decomposed2json(decEndpoint);

                if (that._options.save) {
                    that._json.dependencies = mout.object.mixIn(that._json.dependencies || {}, jsonEndpoint);
                }

                if (that._options.saveDev) {
                    that._json.devDependencies = mout.object.mixIn(that._json.devDependencies || {}, jsonEndpoint);
                }
            });
        }

        // Save JSON, might contain changes to dependencies and resolutions
        return that.saveJson()
        .then(function () {
            return that._manager.postinstall(that._json).then(function () {
                return installed;
            });
        });
    })
    .fin(function () {
        that._installed = null;
        that._working = false;
    });
};

Project.prototype.update = function (names, options) {
    var that = this;
    var targets = [];
    var resolved = {};
    var incompatibles = [];

    // If already working, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    this._options = options || {};
    this._working = true;

    // Analyse the project
    return this._analyse()
    .spread(function (json, tree, flattened) {
        // If no names were specified, update every package
        if (!names) {
            // Mark each root dependency as targets
            that.walkTree(tree, function (node) {
                // We don't know the real source of linked packages
                // Instead we read its dependencies
                if (node.linked) {
                    targets.push.apply(targets, mout.object.values(node.dependencies));
                } else {
                    targets.push(node);
                }

                return false;
            }, true);
        // Otherwise, selectively update the specified ones
        } else {
            // Error out if some of the specified names
            // are not installed
            names.forEach(function (name) {
                if (!flattened[name]) {
                    throw createError('Package ' + name + ' is not installed', 'ENOTINS', {
                        name: name
                    });
                }
            });

            // Add packages whose names are specified to be updated
            that.walkTree(tree, function (node, name) {
                if (names.indexOf(name) !== -1) {
                    // We don't know the real source of linked packages
                    // Instead we read its dependencies
                    if (node.linked) {
                        targets.push.apply(targets, mout.object.values(node.dependencies));
                    } else {
                        targets.push(node);
                    }

                    return false;
                }
            }, true);

            // Recover tree
            that.walkTree(tree, function (node, name) {
                if (node.missing || node.different) {
                    targets.push(node);
                } else if (node.incompatible) {
                    incompatibles.push(node);
                } else {
                    resolved[name] = node;
                }
            }, true);
        }

        // Bootstrap the process
        return that._bootstrap(targets, resolved, incompatibles)
        .then(function () {
            return that._manager.preinstall(that._json);
        })
        .then(function (installed) {
            // Save JSON, might contain changes to resolutions
            return that.saveJson()
            .then(function () {
                return that._manager.postinstall(that._json).then(function () {
                    return installed;
                });
            });
        });
    })
    .fin(function () {
        that._installed = null;
        that._working = false;
    });
};

Project.prototype.uninstall = function (names, options) {
    var that = this;
    var packages = {};

    // If already working, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    this._options = options || {};
    this._working = true;

    // Analyse the project<commit_msg>Added the missing install command to the update task Fixes #1518<commit_after>var glob = require('glob');
var path = require('path');
var fs = require('graceful-fs');
var Q = require('q');
var mout = require('mout');
var rimraf = require('rimraf');
var endpointParser = require('bower-endpoint-parser');
var Logger = require('bower-logger');
var Manager = require('./Manager');
var defaultConfig = require('../config');
var semver = require('../util/semver');
var md5 = require('../util/md5');
var createError = require('../util/createError');
var readJson = require('../util/readJson');
var validLink = require('../util/validLink');
var scripts = require('./scripts');

function Project(config, logger) {
    // This is the only architecture component that ensures defaults
    // on config and logger
    // The reason behind it is that users can likely use this component
    // directly if commands do not fulfil their needs
    this._config = defaultConfig(config);
    this._logger = logger || new Logger();
    this._manager = new Manager(this._config, this._logger);

    this._options = {};
}

// -----------------

Project.prototype.install = function (decEndpoints, options, config) {
    var that = this;
    var targets = [];
    var resolved = {};
    var incompatibles = [];

    // If already working, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    this._options = options || {};
    this._config = config || {};
    this._working = true;

    // Analyse the project
    return this._analyse()
    .spread(function (json, tree) {
        // It shows an error when issuing `bower install`
        // and no bower.json is present in current directory
        if(!that._jsonFile && decEndpoints.length === 0 ) {
            throw createError('No bower.json present', 'ENOENT');
        }

        // Recover tree
        that.walkTree(tree, function (node, name) {
            if (node.incompatible) {
                incompatibles.push(node);
            } else if (node.missing || node.different || that._config.force) {
                targets.push(node);
            } else {
                resolved[name] = node;
            }
        }, true);

        // Add decomposed endpoints as targets
        decEndpoints = decEndpoints || [];
        decEndpoints.forEach(function (decEndpoint) {
            // Mark as new so that a conflict for this target
            // always require a choice
            // Also allows for the target to be converted in case
            // of being *
            decEndpoint.newly = true;
            targets.push(decEndpoint);
        });

        // Bootstrap the process
        return that._bootstrap(targets, resolved, incompatibles);
    })
    .then(function () {
        return that._manager.preinstall(that._json);
    })
    .then(function () {
        return that._manager.install(that._json);
    })
    .then(function (installed) {
        // Handle save and saveDev options
        if (that._options.save || that._options.saveDev) {
            // Cycle through the specified endpoints
            decEndpoints.forEach(function (decEndpoint) {
                var jsonEndpoint;

                jsonEndpoint = endpointParser.decomposed2json(decEndpoint);

                if (that._options.save) {
                    that._json.dependencies = mout.object.mixIn(that._json.dependencies || {}, jsonEndpoint);
                }

                if (that._options.saveDev) {
                    that._json.devDependencies = mout.object.mixIn(that._json.devDependencies || {}, jsonEndpoint);
                }
            });
        }

        // Save JSON, might contain changes to dependencies and resolutions
        return that.saveJson()
        .then(function () {
            return that._manager.postinstall(that._json).then(function () {
                return installed;
            });
        });
    })
    .fin(function () {
        that._installed = null;
        that._working = false;
    });
};

Project.prototype.update = function (names, options) {
    var that = this;
    var targets = [];
    var resolved = {};
    var incompatibles = [];

    // If already working, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    this._options = options || {};
    this._working = true;

    // Analyse the project
    return this._analyse()
    .spread(function (json, tree, flattened) {
        // If no names were specified, update every package
        if (!names) {
            // Mark each root dependency as targets
            that.walkTree(tree, function (node) {
                // We don't know the real source of linked packages
                // Instead we read its dependencies
                if (node.linked) {
                    targets.push.apply(targets, mout.object.values(node.dependencies));
                } else {
                    targets.push(node);
                }

                return false;
            }, true);
        // Otherwise, selectively update the specified ones
        } else {
            // Error out if some of the specified names
            // are not installed
            names.forEach(function (name) {
                if (!flattened[name]) {
                    throw createError('Package ' + name + ' is not installed', 'ENOTINS', {
                        name: name
                    });
                }
            });

            // Add packages whose names are specified to be updated
            that.walkTree(tree, function (node, name) {
                if (names.indexOf(name) !== -1) {
                    // We don't know the real source of linked packages
                    // Instead we read its dependencies
                    if (node.linked) {
                        targets.push.apply(targets, mout.object.values(node.dependencies));
                    } else {
                        targets.push(node);
                    }

                    return false;
                }
            }, true);

            // Recover tree
            that.walkTree(tree, function (node, name) {
                if (node.missing || node.different) {
                    targets.push(node);
                } else if (node.incompatible) {
                    incompatibles.push(node);
                } else {
                    resolved[name] = node;
                }
            }, true);
        }

        // Bootstrap the process
        return that._bootstrap(targets, resolved, incompatibles)
        .then(function () {
            return that._manager.preinstall(that._json);
        })
        .then(function () {
            return that._manager.install(that._json);
        })
        .then(function (installed) {
            // Save JSON, might contain changes to resolutions
            return that.saveJson()
            .then(function () {
                return that._manager.postinstall(that._json).then(function () {
                    return installed;
                });
            });
        });
    })
    .fin(function () {
        that._installed = null;
        that._working = false;
    });
};

Project.prototype.uninstall = function (names, options) {
    var that = this;
    var packages = {};

    // If already working, error out
    if (this._working) {
        return Q.reject(createError('Already working', 'EWORKING'));
    }

    this._options = options || {};
    this._working = true;

    // Analyse the project
{'fraction_non_alphanumeric': 0.11832418685584259, 'fraction_numerical': 0.0009369562307589345, 'mean_word_length': 1.6948602344454464, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4510829', 'n_tokens_mistral': 3856, 'n_tokens_neox': 3639, 'n_words': 1022}