UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

243 lines (195 loc) 9.56 kB
Object.defineProperty(exports, '__esModule', { value: true }); /* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })(); exports.expressionForRevisionsBeforeHead = expressionForRevisionsBeforeHead; exports.expressionForCommonAncestor = expressionForCommonAncestor; /** * @param revision The revision expression of a revision of interest. * @param workingDirectory The working directory of the Hg repository. * @return An expression for the common ancestor of the revision of interest and * the current Hg head. */ var fetchCommonAncestorOfHeadAndRevision = _asyncToGenerator(function* (revision, workingDirectory) { var ancestorExpression = expressionForCommonAncestor(revision); // shell-escape does not wrap '{rev}' in quotes unless it is double-quoted. var args = ['log', '--template', '{rev}', '--rev', ancestorExpression, '--limit', '1']; var options = { cwd: workingDirectory }; try { var _ref = yield (0, (_hgUtils2 || _hgUtils()).hgAsyncExecute)(args, options); var ancestorRevisionNumber = _ref.stdout; return ancestorRevisionNumber; } catch (e) { logger.warn('Failed to get hg common ancestor: ', e.stderr, e.command); throw new Error('Could not fetch common ancestor of head and revision: ' + revision); } }); exports.fetchCommonAncestorOfHeadAndRevision = fetchCommonAncestorOfHeadAndRevision; var fetchRevisions = _asyncToGenerator(function* (revisionExpression, workingDirectory) { var revisionLogArgs = ['log', '--template', REVISION_INFO_TEMPLATE, '--rev', revisionExpression, '--limit', '20']; var bookmarksArgs = ['bookmarks']; var options = { cwd: workingDirectory }; try { var _ref2 = yield Promise.all([(0, (_hgUtils2 || _hgUtils()).hgAsyncExecute)(revisionLogArgs, options), (0, (_hgUtils2 || _hgUtils()).hgAsyncExecute)(bookmarksArgs, options)]); var _ref22 = _slicedToArray(_ref2, 2); var revisionsResult = _ref22[0]; var bookmarksResult = _ref22[1]; var revisionsInfo = parseRevisionInfoOutput(revisionsResult.stdout); var bookmarksInfo = parseBookmarksOutput(bookmarksResult.stdout); for (var revisionInfo of revisionsInfo) { revisionInfo.bookmarks = bookmarksInfo.get(revisionInfo.id) || []; } return revisionsInfo; } catch (e) { logger.warn('Failed to get revision info for revisions' + (' ' + revisionExpression + ': ' + (e.stderr || e) + ', ' + e.command)); throw new Error('Could not fetch revision info for revisions: ' + revisionExpression); } } /** * @param revisionFrom The revision expression of the "start" (older) revision. * @param revisionTo The revision expression of the "end" (newer) revision. * @param workingDirectory The working directory of the Hg repository. * @return An array of revision info between revisionFrom and * revisionTo, plus revisionFrom and revisionTo; * "Between" means that revisionFrom is an ancestor of, and * revisionTo is a descendant of. * For each RevisionInfo, the `bookmarks` field will contain the list * of bookmark names applied to that revision. */ ); var fetchRevisionInfoBetweenRevisions = _asyncToGenerator(function* (revisionFrom, revisionTo, workingDirectory) { var revisionExpression = revisionFrom + '::' + revisionTo; return yield fetchRevisions(revisionExpression, workingDirectory); }); exports.fetchRevisionInfoBetweenRevisions = fetchRevisionInfoBetweenRevisions; var fetchRevisionInfo = _asyncToGenerator(function* (revisionExpression, workingDirectory) { var _ref3 = yield fetchRevisions(revisionExpression, workingDirectory); var _ref32 = _slicedToArray(_ref3, 1); var revisionInfo = _ref32[0]; return revisionInfo; } /** * Helper function to `fetchRevisionInfoBetweenRevisions`. */ ); exports.fetchRevisionInfo = fetchRevisionInfo; exports.parseRevisionInfoOutput = parseRevisionInfoOutput; exports.parseBookmarksOutput = parseBookmarksOutput; function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { var callNext = step.bind(null, 'next'); var callThrow = step.bind(null, 'throw'); function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(callNext, callThrow); } } callNext(); }); }; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _hgUtils2; function _hgUtils() { return _hgUtils2 = require('./hg-utils'); } var _assert2; function _assert() { return _assert2 = _interopRequireDefault(require('assert')); } var _nuclideLogging2; function _nuclideLogging() { return _nuclideLogging2 = require('../../nuclide-logging'); } var logger = (0, (_nuclideLogging2 || _nuclideLogging()).getLogger)(); /** * This file contains utilities for getting an expression to specify a certain * revision in Hg (i.e. something that can be passed to the '--rev' option of * an Hg command). * Note: "Head" in this set of helper functions refers to the "current working * directory parent" in Hg terms. */ // Section: Expression Formation var HG_CURRENT_WORKING_DIRECTORY_PARENT = '.'; var INFO_ID_PREFIX = 'id:'; var INFO_HASH_PREFIX = 'hash:'; var INFO_TITLE_PREFIX = 'title:'; var INFO_AUTHOR_PREFIX = 'author:'; var INFO_DATE_PREFIX = 'date:'; // Exported for testing. var INFO_REV_END_MARK = '<<NUCLIDE_REV_END_MARK>>'; exports.INFO_REV_END_MARK = INFO_REV_END_MARK; var REVISION_INFO_TEMPLATE = INFO_ID_PREFIX + '{rev}\n' + INFO_TITLE_PREFIX + '{desc|firstline}\n' + INFO_AUTHOR_PREFIX + '{author}\n' + INFO_DATE_PREFIX + '{date|isodate}\n' + INFO_HASH_PREFIX + '{node|short}\n{desc}\n' + INFO_REV_END_MARK + '\n'; /** * @param revisionExpression An expression that can be passed to hg as an argument * to the '--rev' option. * @param numberOfRevsBefore The number of revisions before the current revision * that you want a revision expression for. Passing 0 here will simply return 'revisionExpression'. * @return An expression for the 'numberOfRevsBefore'th revision before the given revision. */ function expressionForRevisionsBefore(revisionExpression, numberOfRevsBefore) { if (numberOfRevsBefore === 0) { return revisionExpression; } else { return revisionExpression + '~' + numberOfRevsBefore.toString(); } } function expressionForRevisionsBeforeHead(numberOfRevsBefore_) { var numberOfRevsBefore = numberOfRevsBefore_; if (numberOfRevsBefore < 0) { numberOfRevsBefore = 0; } return expressionForRevisionsBefore(HG_CURRENT_WORKING_DIRECTORY_PARENT, numberOfRevsBefore); } // Section: Revision Sets function expressionForCommonAncestor(revision) { var commonAncestorExpression = 'ancestor(' + revision + ', ' + HG_CURRENT_WORKING_DIRECTORY_PARENT + ')'; // shell-escape does not wrap ancestorExpression in quotes without this toString conversion. return commonAncestorExpression.toString(); } function parseRevisionInfoOutput(revisionsInfoOutput) { var revisions = revisionsInfoOutput.split(INFO_REV_END_MARK); var revisionInfo = []; for (var chunk of revisions) { var revisionLines = chunk.trim().split('\n'); if (revisionLines.length < 6) { continue; } revisionInfo.push({ id: parseInt(revisionLines[0].slice(INFO_ID_PREFIX.length), 10), title: revisionLines[1].slice(INFO_TITLE_PREFIX.length), author: revisionLines[2].slice(INFO_AUTHOR_PREFIX.length), date: new Date(revisionLines[3].slice(INFO_DATE_PREFIX.length)), hash: revisionLines[4].slice(INFO_HASH_PREFIX.length), description: revisionLines.slice(5).join('\n'), bookmarks: [] }); } return revisionInfo; } // Capture the local commit id and bookmark name from the `hg bookmarks` output. var BOOKMARK_MATCH_REGEX = /^ . ([^ ]+)\s+(\d+):([0-9a-f]+)$/; /** * Parse the result of `hg bookmarks` into a `Map` from * revision id to a array of bookmark names applied to revision. */ function parseBookmarksOutput(bookmarksOutput) { var bookmarksLines = bookmarksOutput.split('\n'); var commitsToBookmarks = new Map(); for (var bookmarkLine of bookmarksLines) { var match = BOOKMARK_MATCH_REGEX.exec(bookmarkLine); if (match == null) { continue; } var _match = _slicedToArray(match, 3); var bookmarkString = _match[1]; var commitIdString = _match[2]; var commitId = parseInt(commitIdString, 10); if (!commitsToBookmarks.has(commitId)) { commitsToBookmarks.set(commitId, []); } var bookmarks = commitsToBookmarks.get(commitId); (0, (_assert2 || _assert()).default)(bookmarks != null); bookmarks.push(bookmarkString); } return commitsToBookmarks; }