UNPKG

@cliz/gpm

Version:
252 lines (251 loc) 9.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Project = exports.ProjectManager = void 0; const cli_1 = require("@cliz/cli"); const path = require("path"); const parseGitUrl = require("git-url-parse"); const utils_1 = require("../utils"); const config_1 = require("./config"); class ProjectManager { constructor(workdir) { this.workdir = workdir; this.config = new config_1.ConfigManager(cli_1.api.path.homedir(`.gpm/project.yml`)); // } // create('zcorky.com/myapp', 'zcorky/xxx') async create(target, template) { let target_url = target; let template_url = template; // example: // zcorky/zodash // github.com/zcorky/zodahs if (!/^(https?|git@)/.test(target)) { if (target.split('/').length === 2) { target_url = `https://github.com/${target}`; } else if (target.split('/').length === 3) { target_url = `https://${target}`; } else { throw new Error(`invalid target: ${target}`); } } if (!/^(https?|git@)/.test(template)) { if (template.split('/').length === 2) { template_url = `https://github.com/${template}`; } else if (template.split('/').length === 3) { template_url = `https://${template}`; } else { throw new Error(`invalid template: ${template}`); } } const project = new Project({ url: target_url, workdir: this.workdir }); if (await this.has(project)) { throw new Error(`project ${project.name}(${project.repo}) found in ${project.path}, use another`); } if (await this.existDir(project)) { // save info this.config.set(project.id, project.toJSON(), true); throw new Error(`project ${project.name}(${project.repo}) found in ${project.path}, use another`); } await (0, utils_1.runInShell)(`git clone --progress ${template_url} ${project.path}`); // @TODO define template this.config.set(project.id, project.toJSON(), true); } async add(url, options) { let shouldClone = true; const project = new Project({ url, workdir: this.workdir }); // save data if (!this.config.get(project.id)) { this.config.set(project.id, project.toJSON(), true); } if (await this.has(project) && await this.existDir(project)) { throw new Error(`project ${project.name}(${project.repo}) found in ${project.path}`); } else if (await this.existDir(project)) { shouldClone = false; } if (shouldClone) { let cmd = `git clone --progress ${project.url} ${project.path}`; if (options === null || options === void 0 ? void 0 : options.depth) { cmd += ` --depth=${options.depth}`; } await (0, utils_1.runInShell)(cmd); } this.config.set(project.id, project.toJSON(), true); } async remove(provider, owner, name) { const project = new Project({ provider, name, owner, workdir: this.workdir, }); if (!(await this.has(project))) { throw new Error(`project ${project.name}(${project.repo}) not found`); } // @TODO if (!project.path || project.path === '/') { throw new Error(`project path (${project.path}) is not vaild`); } if (await this.existDir(project)) { await cli_1.api.fs.rimraf(project.path); } this.config.set(project.id, null, true); } async sync(provider, owner, name) { const project = new Project({ provider, name, owner, workdir: this.workdir, }); if (!(await this.has(project))) { throw new Error(`project ${project.name}(${project.repo}) not found`); } // add first if (!(await this.existDir(project))) { await this.add(project.url); } // use original created at const _project = this.config.get(project.id); project.createdAt = new Date(_project.createdAt); return new Promise((resolve) => { cli_1.api.$.cd(project.path); const child = cli_1.api.$.spawn(`git pull --progress`); child.on('error', (e) => process.stderr.write(e)); child.on('data', (e) => process.stdout.write(e)); child.on('exit', () => { project.updatedAt = new Date(); this.config.set(project.id, project.toJSON(), true); resolve(); }); }); } async list() { const config = this.config.getAll(); return Object.values(config).sort((a, b) => a.id.localeCompare(b.id)); } async search(keyword) { const config = this.config.getAll(); const projects = Object.values(config).sort((a, b) => { var _a; return (_a = a === null || a === void 0 ? void 0 : a.id) === null || _a === void 0 ? void 0 : _a.localeCompare(b === null || b === void 0 ? void 0 : b.id); }); if (!keyword) { return projects; } const re = new RegExp(keyword); return projects.filter((project) => { return re.test(project.url); }); } async validate(url) { const project = new Project({ url, workdir: this.workdir }); if (!project.owner || !project.name) { return false; } return true; } async prepare() { if (!(await cli_1.api.fs.exist(this.config.path))) { await cli_1.api.fs.mkdirp(path.dirname(this.config.path)); await cli_1.api.fs.yml.write(this.config.path, {}); } await this.config.prepare(); // @TODO await this.config.nomorlize(); } get(url) { const _url = /^(https?|git@)/.test(url) ? url : `https://github.com/${url}`; return new Project({ url: _url, workdir: this.workdir }); } async has(project) { if (!!this.config.get(project.id)) { return true; } return false; } async existDir(project) { if (await cli_1.api.fs.exist(project.path)) { return true; } return false; } } exports.ProjectManager = ProjectManager; const DEFAULT_PROVIDER = 'github.com'; class Project { constructor(options) { this.options = options; this.parsedGitUrl = this.url && parseGitUrl(this.url); this._name = this.parsedGitUrl.name; this._owner = this.parsedGitUrl.owner; this._provider = this.parsedGitUrl.resource || this.parsedGitUrl.source; this.createdAt = new Date(); this.updatedAt = new Date(); // } get id() { const { name, owner, provider } = this; return path.join(provider, owner, name); } get name() { var _a; return ((_a = this.options) === null || _a === void 0 ? void 0 : _a.name) || this._name; } get owner() { var _a; return ((_a = this.options) === null || _a === void 0 ? void 0 : _a.owner) || this._owner; } get provider() { var _a; return ((_a = this.options) === null || _a === void 0 ? void 0 : _a.provider) || this._provider; } get url() { var _a, _b, _c, _d, _e; const { name, owner, provider = DEFAULT_PROVIDER } = this; if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.url) { // http/https if (/^https?:\/\//.test((_b = this.options) === null || _b === void 0 ? void 0 : _b.url)) return this.options.url; // git@ if (/^git@/.test((_c = this.options) === null || _c === void 0 ? void 0 : _c.url)) return this.options.url; // ssh:// if (/^ssh:\/\//.test((_d = this.options) === null || _d === void 0 ? void 0 : _d.url)) return this.options.url; // owner/repo return `https://${provider}/${(_e = this.options) === null || _e === void 0 ? void 0 : _e.url.replace(/^\/(.*)/, '$1')}`; } return `https://${provider}/${owner}/${name}`; } get workdir() { var _a, _b; return (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.workdir) !== null && _b !== void 0 ? _b : cli_1.api.path.homedir('code'); } get path() { const { name, owner, provider } = this; return path.join(this.workdir, provider, owner, name); } get repo() { return `${this.owner}/${this.name}`; } toJSON() { const { id, name, owner, provider, url, path, repo, workdir, createdAt, updatedAt, } = this; return { id, name, owner, provider, repo, url, path, workdir, createdAt, updatedAt, }; } } exports.Project = Project;