lib/plugins/install/install.js/Install/install
class Install:  install() {
    const url = URL.parse(this.options.url.replace(/\/$/, ''));

    // check if url parameter is a valid url
    if (!url.host) {
      throw new this.serverless.classes.Error('The URL you passed is not a valid URL');
    }

    const parts = url.pathname.split('/');
    const parsedGitHubUrl = {
      owner: parts[1],
      repo: parts[2],
      branch: parts[4] || 'master',
    };

    // validate if given url is a valid GitHub url
    if (url.hostname !== 'github.com' || !parsedGitHubUrl.owner || !parsedGitHubUrl.repo) {
      const errorMessage = [
        'The URL must be a valid GitHub URL in the following format:',
        ' https://github.com/serverless/serverless',
      ].join('');
      throw new this.serverless.classes.Error(errorMessage);
    }

    const downloadUrl = [
      'https://github.com/',
      parsedGitHubUrl.owner,
      '/',
      parsedGitHubUrl.repo,
      '/archive/',
      parsedGitHubUrl.branch,
      '.zip',
    ].join('');

    const endIndex = parts.length - 1;
    let dirName;
    let serviceName;
    let downloadServicePath;

    // check if it's a directory or the whole repository
    if (parts.length > 4) {
      serviceName = parts[endIndex];
      dirName = this.options.name || parts[endIndex];
      // download the repo into a temporary directory
      downloadServicePath = path.join(os.tmpdir(), parsedGitHubUrl.repo);
    } else {
      serviceName = parsedGitHubUrl.repo;
      dirName = this.options.name || parsedGitHubUrl.repo;
      downloadServicePath = path.join(process.cwd(), dirName);
    }

    const servicePath = path.join(process.cwd(), dirName);
    const renamed = dirName !== (parts.length > 4 ? parts[endIndex] : parsedGitHubUrl.repo);

    if (this.serverless.utils.dirExistsSync(path.join(process.cwd(), dirName))) {
      const errorMessage = `A folder named "${dirName}" already exists.`;
      throw new this.serverless.classes.Error(errorMessage);
    }

    this.serverless.cli.log(`Downloading and installing "${serviceName}"...`);

    const that = this;

    // download service
    return download(
      downloadUrl,
      downloadServicePath,
      { timeout: 30000, extract: true, strip: 1, mode: '755' }
    ).then(() => {
    // if it's a directory inside of git
      if (parts.length > 4) {
        let directory = downloadServicePath;
        for (let i = 5; i <= endIndex; i++) {
          directory = path.join(directory, parts[i]);
        }
        that.serverless.utils
          .copyDirContentsSync(directory, servicePath);
        fse.removeSync(downloadServicePath);
      }
    }).then(() => {
      if (!renamed) return BbPromise.resolve();

      return this.renameService(dirName, servicePath);
    }).then(() => {
      let message = `Successfully installed "${serviceName}"`;
      userStats.track('service_installed', {
        data: { // will be updated with core analtyics lib
          url: this.options.url,
        },
      });
      if (renamed) message = `${message} as "${dirName}"`;

      that.serverless.cli.log(message);
    });
  }