diff --git a/lib/gitremote.js b/lib/gitremote.js index 812d93b..239d035 100644 --- a/lib/gitremote.js +++ b/lib/gitremote.js @@ -93,29 +93,57 @@ exports.getRemoteBranches = function(cwd) { return remoteBranches; }; -var RE_CURRENT_BASE_BRANCHES = /^[ -+]*\*/; -var RE_BASE_BRANCHE_NAME = /.*?\[([^\]\^~]+).*/; // " +* [MS170216105211~2^2] test: fixed lint" +/** + * 解析 `git show-branch` 的输出,得到当前分支的基准分支。 + * @param {String} showBranch 当前分支 `git show-branch` 的输出。 + * @return {Array} base branch name + */ +exports.parseBaseBranchName = function(showBranch) { + // 上下上个部分使用 -- 分隔。 + const info = showBranch.split(/^-+$/m); + // 查找当前分支。 + // -- 上面的部分包含当前分支。 + const RE_CURRENT_BRANCH = /^(\s*)\*\s+\[([^\]]+)\]/m; + const m = RE_CURRENT_BRANCH.exec(info[0]); + // 输入异常,没有找到当前分支。 + if (!m) { + return ''; + } + // 当前分支所在的列数 + const currBranchIndent = m[1].length; + const currBranchName = m[2]; + + // 从 -- 下面的部分查找当前分支所在列有 *+- 符号的行所在的分支。 + const brs = info[1].split(/\r\n|\r|\n/); + return brs + .map(br => { + var RE_BASE_BRANCHE_NAME = /^[ *+-]*\[([^\]\^~]+)/; // " +* [MS170216105211~2^2] test: fixed lint" + const m2 = RE_BASE_BRANCHE_NAME.exec(br); + // 解析异常,没有找到分支信息,一般是 \n 导致的空行。 + if (!m2) { + return null; + } + const brName = m2[1]; + return { + brName, + currBranchEffect: '*+-'.includes(br.charAt(currBranchIndent)), + }; + }) + .filter(br => { + return br && + br.brName !== currBranchName && + br.currBranchEffect; + }) + .map(br => br.brName); +}; + exports.getBaseBranches = function(cwd) { - var cwb = exports.getCurrentBranch(cwd); - var baseBranches = child_process.execSync( + var showBranch = child_process.execSync( 'git show-branch --no-color', {cwd: cwd} - ).toString() - .trim() - .split(/\r\n|\r|\n/) - .filter(function(line) { - return RE_CURRENT_BASE_BRANCHES.test(line); - }) - .map(function(line) { - var m = RE_BASE_BRANCHE_NAME.exec(line); - return m ? m[1] : null; - }) - .filter(function(branchName) { - return branchName !== cwb; - }); - // TODO: 获取当前分支的所有祖先分支列表,并按照倒序排列,最近切出的祖先分支排第一。 - return baseBranches.length >= 0 ? [baseBranches[0]] : []; - // return unique(baseBranches); + ).toString(); + const baseBranches = exports.parseBaseBranchName(showBranch); + return baseBranches; }; // 转义分支名称。 diff --git a/test/gitopen.test.js b/test/gitopen.test.js index 6dd3fee..42eba77 100644 --- a/test/gitopen.test.js +++ b/test/gitopen.test.js @@ -397,6 +397,49 @@ describe('gitremote()', function() { it('gitremote.getRemoteName()', function() { resolve(gitremote.getRemoteName()).should.be.eql('origin'); }); + + + describe('gitremote.parseBaseBranchName()', function() { + it('gitremote.parseBaseBranchName(1)', function() { + const showBranch = `* [feat/hand-guide] feat: hand guide + ! [master] sprint_demo_S915482907_20200903_merge_master:Merge branch 'sprint_demo_S915482907_20200903' into 'master' + ! [sprint_demo_3_3_S916642948_20201022] PullRequest: something. + ! [v3.3] PullRequest: 314 nothing +---- +* [feat/hand-guide] feat: hand guide + - [master] sprint_demo_S915482907_20200903_merge_master:Merge branch 'sprint_demo_S915482907_20200903' into 'master' +---- [sprint_demo_3_3_S916642948_20201022] PullRequest: 314 something`; + gitremote.parseBaseBranchName(showBranch).should.be.eql(['sprint_demo_3_3_S916642948_20201022']); + }); + + it('gitremote.parseBaseBranchName(2)', function() { + const showBranch = `! [develop-1] master 2 + ! [develop-2] feat: 2-1 + ! [feat/1-1] master 2 + ! [feat/2-1] feat: 2-1 + * [feat/2-2] feat: 2-2 + ! [master] master 2 +------ + * [feat/2-2] feat: 2-2 + + +* [develop-2] feat: 2-1 +++++*+ [develop-1] master 2`; + gitremote.parseBaseBranchName(showBranch).should.be.eql(['develop-2', 'develop-1']); + }); + + it('gitremote.parseBaseBranchName(3)', function() { + const showBranch = `! [develop-1] master 2 + ! [develop-2] feat: 2-1 + * [feat/1-1] master 2 + ! [feat/2-1] feat: 2-1 + ! [feat/2-2] feat: 2-2 + ! [master] master 2 +------ + + [feat/2-2] feat: 2-2 + + ++ [develop-2] feat: 2-1 +++*+++ [develop-1] master 2`; + gitremote.parseBaseBranchName(showBranch).should.be.eql(['develop-1']); + }); + }); }); describe('$ cd non-git-dir && gitopen', function() {