<commit_before>'use strict';
const Base = require('yeoman-generator').Base;
const chalk = require('chalk');
const fs = require('fs-extra');
const path = require('path');
const yeoman = require('yeoman-environment');
const {toHTTPRepoUrl, toSSHRepoUrl} = require('../../utils/repo');

function toBaseName(name) {
  if (name.includes('/')) {
    return name;
  }
  return `Caleydo/${name}`;
}

function failed(spawnResult) {
  return spawnResult.status !== 0;
}

function toCWD(basename) {
  let match = basename.match(/.*\/(.*)/)[1];
  if (match.endsWith('_product')) {
    match = match.slice(0, -8);
  }
  return match;
}

function findDefaultApp(product) {
  if (!product) {
    return null;
  }
  for (let p of product) {
    if (p.type === 'web') {
      return p.repo.slice(p.repo.lastIndexOf('/') + 1);
    }
  }
  return null;
}

function downloadFileImpl(url, dest) {
  const http = require(url.startsWith('https') ? 'https' : 'http');
  console.log(chalk.blue('download file', url));
  return new Promise((resolve, reject) => {
    const file = fs.createWriteStream(dest);
    http.get(url, (response) => {
      response.pipe(file);
      file.on('finish', () => {
        file.close(resolve);
      });
    }).on('error', reject);
  });
}

function downloadDataUrl(url, dest) {
  if (!url.startsWith('http')) {
    url = `https://s3.eu-central-1.amazonaws.com/phovea-data-packages/${url}`;
  }
  return downloadFileImpl(url, dest);
}

function downloadBackupUrl(url, dest) {
  if (!url.startsWith('http')) {
    url = `https://s3.eu-central-1.amazonaws.com/phovea-volume-backups/${url}`;
  }
  return downloadFileImpl(url, dest);
}

function toDownloadName(url) {
  if (!url.startsWith('http')) {
    return url;
  }
  return url.substring(url.lastIndexOf('/') + 1);
}

class Generator extends Base {

  constructor(args, options) {
    super(args, options);

    this.option('ssh', {
      alias: 's',
      defaults: false,
      type: Boolean
    });

    this.argument('product', {
      required: true
    });
  }

  prompting() {
    return this.prompt([{
      type: 'input',
      name: 'productName',
      message: 'Product',
      default: this.args.length > 0 ? this.args[0] : undefined,
      when: this.args.length === 0,
      validate: (d) => d.length > 0
    }, {
      type: 'confirm',
      name: 'cloneSSH',
      message: 'SSH clone',
      store: true,
      default: this.options.ssh,
      when: !this.options.ssh
    }]).then((props) => {
      this.productName = toBaseName(props.productName || this.args[0]);
      this.cwd = toCWD(this.productName);
      this.cloneSSH = props.cloneSSH || this.options.ssh;
    });
  }

  _yo(generator, options) {
    // call yo internally
    const env = yeoman.createEnv([], {
      cwd: this.cwd
    }, this.env.adapter);
    env.register(require.resolve('../' + generator), 'phovea:' + generator);
    return new Promise((resolve, reject) => {
      try {
        this.log('running yo phovea:' + generator);
        env.run('phovea:' + generator, options || {}, () => {
          // wait a second after running yo to commit the files correctly
          setTimeout(() => resolve(), 500);
        });
      } catch (e) {
        console.error('error', e, e.stack);
        reject(e);
      }
    });
  }

  _abort(msg) {
    return Promise.reject(msg ? msg : 'Step Failed: Aborting');
  }

  _spawn(cmd, argline, cwd) {
    const options = cwd === false ? {} : Object.assign({cwd: this.cwd}, cwd || {});
    return this.spawnCommandSync(cmd, Array.isArray(argline) ? argline : argline.split(' '), options);
  }

  _spawnOrAbort(cmd, argline, cwd) {
    const r = this._spawn(cmd, argline, cwd);
    if (failed(r)) {
      this.log(r);
      return this._abort('failed: ' + cmd + ' - status code: ' + r.status);
    }
    return Promise.resolve(cmd);
  }

  _cloneRepo(repo, branch, extras) {
    const repoUrl = this.cloneSSH ? toSSHRepoUrl(repo) : toHTTPRepoUrl(repo);
    const line = `clone -b ${branch}${extras || ''} ${repoUrl}`;
    this.log(chalk.blue(`clone repository:`), `git ${line}`);
    return this._spawnOrAbort('git', line.split(' '));
  }

  _getProduct() {
    return this._cloneRepo(this.productName, 'master', ' --depth 1')
      .then(() => {
        const name = this.productName.slice(this.productName.lastIndexOf('/') + 1);
        this.product = fs.readJSONSync(`${this.cwd}/${name}/phovea_product.json`);

        // pass through the docker overrides
        if (fs.existsSync(`${this.cwd}/${name}/docker-compose-patch.yaml`)) {
          fs.copySync(`${this.cwd}/${name}/docker-compose-patch.yaml`, this.destinationPath(`${this.cwd}/docker-compose-patch.yaml`));
        }

        const defaultApp = this.product.find((v) => v.type === 'web');
        if (defaultApp) {
          fs.writeJsonSync(this.destinationPath(`${this.cwd}/.yo-rc-workspace.json`), {
            modules: [],
            defaultApp: defaultApp.repo.slice(defaultApp.repo.lastIndexOf('/') + 1)
          });
        }

        return this.product;
      }).then((product) => {
        const name = this.productName.slice(this.productName.lastIndexOf('/') + 1);
        // clean up again
        fs.removeSync(`${this.cwd}/${name}`);
        return product;
      });
  }
<commit_msg>add option to specify product branch<commit_after>'use strict';
const Base = require('yeoman-generator').Base;
const chalk = require('chalk');
const fs = require('fs-extra');
const path = require('path');
const yeoman = require('yeoman-environment');
const {toHTTPRepoUrl, toSSHRepoUrl} = require('../../utils/repo');

function toBaseName(name) {
  if (name.includes('/')) {
    return name;
  }
  return `Caleydo/${name}`;
}

function failed(spawnResult) {
  return spawnResult.status !== 0;
}

function toCWD(basename) {
  let match = basename.match(/.*\/(.*)/)[1];
  if (match.endsWith('_product')) {
    match = match.slice(0, -8);
  }
  return match;
}

function findDefaultApp(product) {
  if (!product) {
    return null;
  }
  for (let p of product) {
    if (p.type === 'web') {
      return p.repo.slice(p.repo.lastIndexOf('/') + 1);
    }
  }
  return null;
}

function downloadFileImpl(url, dest) {
  const http = require(url.startsWith('https') ? 'https' : 'http');
  console.log(chalk.blue('download file', url));
  return new Promise((resolve, reject) => {
    const file = fs.createWriteStream(dest);
    http.get(url, (response) => {
      response.pipe(file);
      file.on('finish', () => {
        file.close(resolve);
      });
    }).on('error', reject);
  });
}

function downloadDataUrl(url, dest) {
  if (!url.startsWith('http')) {
    url = `https://s3.eu-central-1.amazonaws.com/phovea-data-packages/${url}`;
  }
  return downloadFileImpl(url, dest);
}

function downloadBackupUrl(url, dest) {
  if (!url.startsWith('http')) {
    url = `https://s3.eu-central-1.amazonaws.com/phovea-volume-backups/${url}`;
  }
  return downloadFileImpl(url, dest);
}

function toDownloadName(url) {
  if (!url.startsWith('http')) {
    return url;
  }
  return url.substring(url.lastIndexOf('/') + 1);
}

class Generator extends Base {

  constructor(args, options) {
    super(args, options);

    this.option('ssh', {
      alias: 's',
      defaults: false,
      type: Boolean
    });

    this.option('branch', {
      alias: 'b',
      defaults: 'master',
      type: String
    });

    this.argument('product', {
      required: true
    });
  }

  prompting() {
    return this.prompt([{
      type: 'input',
      name: 'productName',
      message: 'Product',
      default: this.args.length > 0 ? this.args[0] : undefined,
      when: this.args.length === 0,
      validate: (d) => d.length > 0
    }, {
      type: 'confirm',
      name: 'cloneSSH',
      message: 'SSH clone',
      store: true,
      default: this.options.ssh,
      when: !this.options.ssh
    }]).then((props) => {
      this.productName = toBaseName(props.productName || this.args[0]);
      this.cwd = toCWD(this.productName);
      this.cloneSSH = props.cloneSSH || this.options.ssh;
    });
  }

  _yo(generator, options) {
    // call yo internally
    const env = yeoman.createEnv([], {
      cwd: this.cwd
    }, this.env.adapter);
    env.register(require.resolve('../' + generator), 'phovea:' + generator);
    return new Promise((resolve, reject) => {
      try {
        this.log('running yo phovea:' + generator);
        env.run('phovea:' + generator, options || {}, () => {
          // wait a second after running yo to commit the files correctly
          setTimeout(() => resolve(), 500);
        });
      } catch (e) {
        console.error('error', e, e.stack);
        reject(e);
      }
    });
  }

  _abort(msg) {
    return Promise.reject(msg ? msg : 'Step Failed: Aborting');
  }

  _spawn(cmd, argline, cwd) {
    const options = cwd === false ? {} : Object.assign({cwd: this.cwd}, cwd || {});
    return this.spawnCommandSync(cmd, Array.isArray(argline) ? argline : argline.split(' '), options);
  }

  _spawnOrAbort(cmd, argline, cwd) {
    const r = this._spawn(cmd, argline, cwd);
    if (failed(r)) {
      this.log(r);
      return this._abort('failed: ' + cmd + ' - status code: ' + r.status);
    }
    return Promise.resolve(cmd);
  }

  _cloneRepo(repo, branch, extras) {
    const repoUrl = this.cloneSSH ? toSSHRepoUrl(repo) : toHTTPRepoUrl(repo);
    const line = `clone -b ${branch}${extras || ''} ${repoUrl}`;
    this.log(chalk.blue(`clone repository:`), `git ${line}`);
    return this._spawnOrAbort('git', line.split(' '));
  }

  _getProduct() {
    return this._cloneRepo(this.productName, this.options.branch || 'master', ' --depth 1')
      .then(() => {
        const name = this.productName.slice(this.productName.lastIndexOf('/') + 1);
        this.product = fs.readJSONSync(`${this.cwd}/${name}/phovea_product.json`);

        // pass through the docker overrides
        if (fs.existsSync(`${this.cwd}/${name}/docker-compose-patch.yaml`)) {
          fs.copySync(`${this.cwd}/${name}/docker-compose-patch.yaml`, this.destinationPath(`${this.cwd}/docker-compose-patch.yaml`));
        }

        const defaultApp = this.product.find((v) => v.type === 'web');
        if (defaultApp) {
          fs.writeJsonSync(this.destinationPath(`${this.cwd}/.yo-rc-workspace.json`), {
            modules: [],
            defaultApp: defaultApp.repo.slice(defaultApp.repo.lastIndexOf('/') + 1)
          });
        }

        return this.product;
      }).then((product) => {
        const name = this.productName.slice(this.productName.lastIndexOf('/') + 1);
        // clean up again
        fs.removeSync(`${this.cwd}/${name}`);
        return product;
      });
  }

{'fraction_non_alphanumeric': 0.18410198725159355, 'fraction_numerical': 0.004124484439445069, 'mean_word_length': 2.808996786861835, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 29, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '110234', 'n_tokens_mistral': 3630, 'n_tokens_neox': 3590, 'n_words': 687}