@cliz/gpm
Version:
Git Project Manager
252 lines (251 loc) • 9.27 kB
JavaScript
"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;