lib/actions.js
function (app, callback) {
    var cozyLight = require('./cozy-light');
    logger.info('Fetching data...');
    npmHelpers.fetchManifest(app,
      function addAppToConfig (fetchErr, manifest, type) {

        if (fetchErr) {
          logger.raw(fetchErr);
          logger.error('Cannot find given app manifest.');
          logger.error('Make sure it lives on Github');
          logger.error('or in the given directory.');
          logger.error(app + ' installation failed.');
          nodeHelpers.invoke(callback, fetchErr);

        } else {
          var config = configHelpers.getConfig();
          var appName = manifest.name;

          if (config.apps[appName]) {
            logger.info('App ' + appName + ' already installed...');
            return nodeHelpers.invoke(callback, null, manifest, type);

          } else {
            logger.info('Installing app ' + appName + '...');
            var setupCb = function(installErr){
              if (installErr) {
                logger.raw(installErr);
                logger.error(appName + ' installation failed.');
                nodeHelpers.invoke(callback, installErr, manifest, type);
              } else {
                logger.info(appName + ' installed. Enjoy!');

                if(cozyLight.getStatus() !== 'started') {
                  configHelpers.addApp(appName, manifest);
                  nodeHelpers.invoke(callback, null, manifest, type);
                } else {
                  configHelpers.watcher.one(function() {
                    callback();
                  });
                  configHelpers.addApp(appName, manifest);
                }
              }
            };

            if (type === 'file') {
              return npmHelpers.link(app, setupCb);
            } else if (type === 'url') {
              /* Checking if a branch of the github repo is specified
               * within the application path parameter (separated with a @).
               */
              if (app.split('@') > 1) {
                app = app.split('@')[0];
              }
              return npmHelpers.install(app, setupCb);
            }
          }
        }
      });
  }
function (app, callback) {
    var cozyLight = require('./cozy-light');
    logger.info('Fetching data...');
    npmHelpers.fetchManifest(app,
      function addAppToConfig (fetchErr, manifest, type) {

        if (fetchErr) {
          logger.raw(fetchErr);
          logger.error('Cannot find given app manifest.');
          logger.error('Make sure it lives on Github');
          logger.error('or in the given directory.');
          logger.error(app + ' installation failed.');
          nodeHelpers.invoke(callback, fetchErr);

        } else {
          var config = configHelpers.getConfig();
          var appName = manifest.name;

          if (config.apps[appName]) {
            logger.info('App ' + appName + ' already installed...');
            return nodeHelpers.invoke(callback, null, manifest, type);

          } else {
            logger.info('Installing app ' + appName + '...');
            var setupCb = function(installErr){
              if (installErr) {
                logger.raw(installErr);
                logger.error(appName + ' installation failed.');
                nodeHelpers.invoke(callback, installErr, manifest, type);
              } else {
                logger.info(appName + ' installed. Enjoy!');

                if(cozyLight.getStatus() !== 'started') {
                  configHelpers.addApp(appName, manifest);
                  nodeHelpers.invoke(callback, null, manifest, type);
                } else {
                  configHelpers.watcher.one(function() {
                    callback();
                  });
                  configHelpers.addApp(appName, manifest);
                }
              }
            };

            if (type === 'file') {
              return npmHelpers.link(app, setupCb);
            } else if (type === 'url') {
              /* Checking if a branch of the github repo is specified
               * within the application path parameter (separated with a @).
               */
              if (app.split('@') > 1) {
                app = app.split('@')[0];
              }
              return npmHelpers.install(app, setupCb);
            }
          }
        }
      });
  }
App names correspond to Github repo.
An app name is composed of a user name
and a repository name.
Installation starts by fetching the manifest
from the repository (package.json located at the root).
Then it installs sources and
dependencies in the cozy-light folder.

@param {String} app App to install (ex: cozy-labs/calendar).
@param {Function} callback Termination.