UNPKG

alm

Version:

The best IDE for TypeScript

200 lines (199 loc) 8.88 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [0, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var _this = this; Object.defineProperty(exports, "__esModule", { value: true }); /** * The stuff that interacts with system git */ var cp = require("child_process"); var wd = require("../../disk/workingDir"); var fmc = require("../../disk/fileModelCache"); var json_1 = require("../../../common/json"); /** Main utility function to execute a command */ var gitCmdBetter = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return new Promise(function (resolve, reject) { var child = cp.spawn('git', args, { cwd: wd.getProjectRoot() }); var output = []; child.stdout.on('data', function (data) { output.push(data.toString()); }); child.stderr.on('data', function (data) { /** * NOTE: reason for not using reject: * `git push origin head` * sends data to stderr! WTF. * tells you `origin` -> remote address e.g. (To https://github.com/alm-tools/alm.git) * tells you `head` -> branch details e.g (0cb6cae..2fe075b HEAD -> bas/gitAddCommitAndPush) */ output.push(data.toString()); }); child.on('close', function (code) { resolve(output.join('')); }); }); }; function gitStatus(args) { return gitCmdBetter('status'); } exports.gitStatus = gitStatus; /** This is a soft reset. i.e. it keeps your staged changes */ function gitReset(args) { fmc.saveOpenFile(args.filePath); // Delay because if we reset the file immediately the ^ save // makes the *change* detection in file model view to ignore what happened. return new Promise(function (resolve, reject) { return setTimeout(function () { gitCmdBetter('checkout --', args.filePath) .then(resolve, reject); }, 500); }); } exports.gitReset = gitReset; /** * Docs : * - http://stackoverflow.com/q/37097761/390330 * - https://git-scm.com/docs/git-diff * Some inspiration : https://github.com/jisaacks/GitGutter/blob/1f673cbe009e2e0f4393c25e83be895871b4923f/git_gutter_handler.py#L149-L177 */ var gitDiffRegex = /@@[^@@]*@@/g; function gitDiff(args) { // Save the file if not saved var file = fmc.getOrCreateOpenFile(args.filePath); if (!file.saved()) { fmc.saveOpenFile(args.filePath); } /** * We diff with `HEAD` to still show staged changes (as there are still in your headspace as *area you are working on*) */ return gitCmdBetter('diff', '-U0', '--no-color', '--no-ext-diff', 'HEAD', args.filePath).then(function (res) { var added = []; var removed = []; var modified = []; var matches = res.match(gitDiffRegex); if (matches) { matches.forEach(function (m) { // m is something like one of: // @@ -n1[,n2] +n3[,n4] @@ // console.log(m); // DEBUG // Remove @@: m = m.replace(/@@/g, ''); m = m.trim(); // m is now like: // -n1[,n2] +n3[,n4] var _a = m.split(' '), n1n2 = _a[0], n3n4 = _a[1]; var _b = n1n2.split(','), n1 = _b[0], n2 = _b[1]; var _c = n3n4.split(','), n3 = _c[0], n4 = _c[1]; // n2 === 0 means all addition if (n2 != null && +n2 === 0) { added.push({ from: +n3 - 1, to: +n3 + (n4 == null ? 1 : +n4) - 1 }); } else if (n4 != null && +n4 === 0) { removed.push(+n3 - 1); } else { modified.push({ from: +n3 - 1, to: +n3 + (n4 == null ? 1 : +n4) - 1 }); } }); } return { added: added, removed: removed, modified: modified }; }); } exports.gitDiff = gitDiff; exports.gitAddAllCommitAndPush = function (query) { return __awaiter(_this, void 0, void 0, function () { var addResult, commitResult, pushResult, log, ex_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 4, , 5]); return [4 /*yield*/, gitCmdBetter('add', '-A')]; case 1: addResult = _a.sent(); return [4 /*yield*/, gitCmdBetter('commit', '--message', query.message)]; case 2: commitResult = _a.sent(); /** * Sample: * error: pathspec \'when\' did not match any file(s) known to git.\nerror: pathspec \'done\' did not match any file(s) known to git.\n */ if (commitResult.startsWith('error')) { return [2 /*return*/, { type: 'error', error: commitResult }]; } return [4 /*yield*/, gitCmdBetter('push', 'origin', 'HEAD')]; case 3: pushResult = _a.sent(); log = json_1.stringify({ addResult: addResult, commitResult: commitResult, pushResult: pushResult }); return [2 /*return*/, { type: 'success', log: log }]; case 4: ex_1 = _a.sent(); return [2 /*return*/, { type: 'error', error: ex_1.message }]; case 5: return [2 /*return*/]; } }); }); }; exports.gitFetchLatestAndRebase = function (query) { return __awaiter(_this, void 0, void 0, function () { var fetchResult, pullWithRebaseResult, log, ex_2; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 3, , 4]); return [4 /*yield*/, gitCmdBetter('fetch', 'origin')]; case 1: fetchResult = _a.sent(); return [4 /*yield*/, gitCmdBetter('pull', '--rebase')]; case 2: pullWithRebaseResult = _a.sent(); log = json_1.stringify({ fetchResult: fetchResult, pullWithRebaseResult: pullWithRebaseResult }); return [2 /*return*/, { type: 'success', log: log }]; case 3: ex_2 = _a.sent(); return [2 /*return*/, { type: 'error', error: ex_2.message }]; case 4: return [2 /*return*/]; } }); }); };