Skip to content

Commit

Permalink
perf: 简化git分支获取
Browse files Browse the repository at this point in the history
Signed-off-by: jackiotyu <[email protected]>
  • Loading branch information
jackiotyu committed Oct 23, 2023
1 parent 273a01b commit be987bf
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 88 deletions.
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"treeView.tooltip.folder": "$(folder) Folder {0}\n\n",
"commit": "commit",
"branch": "branch",
"remoteBranch": "remote branch",
"tag": "tag",
"commitHash": "commit hash",
"treeView.tooltip.error": "$(error) Detached from the git version\n\n",
Expand Down
1 change: 1 addition & 0 deletions package.nls.zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"treeView.tooltip.folder": "$(folder) 路径 {0}\n\n",
"commit": "提交",
"branch": "分支",
"remoteBranch": "远程分支",
"tag": "标记",
"commitHash": "提交hash",
"treeView.tooltip.error": "$(error) 已从 git 版本中分离\n\n",
Expand Down
8 changes: 4 additions & 4 deletions src/lib/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -567,13 +567,13 @@ const searchAllWorktreeCmd = () => {
};

const pushWorkTreeCmd = (item?: WorkTreeItem) => {
if (!item) return;
pullOrPushAction('push', item.name, item.path);
if (!item?.remoteRef) return;
pullOrPushAction('push', item.remoteRef, item.path);
};

const pullWorkTreeCmd = (item?: WorkTreeItem) => {
if (!item) return;
pullOrPushAction('pull', item.name, item.path);
if (!item?.remoteRef) return;
pullOrPushAction('pull', item.remoteRef, item.path);
};

const loadAllTreeDataCmd = (item?: ILoadMoreItem) => {
Expand Down
43 changes: 27 additions & 16 deletions src/lib/quickPick.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as vscode from 'vscode';
import { getBranchList, getRemoteBranchList, getTagList, formatTime, getWorkTreeList, checkGitValid } from '@/utils';
import { formatTime, getWorkTreeList, checkGitValid, getAllRefList } from '@/utils';
import { GlobalState } from '@/lib/globalState';
import { IWorkTreeCacheItem } from '@/types';
import localize from '@/localize';
Expand Down Expand Up @@ -42,22 +42,32 @@ export const pickBranch = async (
});
quickPick.show();
quickPick.busy = true;
// TODO 使用 git for-each-ref 获取所有分支和tag
const [branchList, remoteBranchList, tagList] = await Promise.all([
getBranchList(['refname:short', 'objectname:short', 'worktreepath', 'authordate', 'HEAD'], cwd),
getRemoteBranchList(['refname:short', 'objectname:short'], cwd),
getTagList(['refname:short', 'objectname:short'], cwd),
]);

// 使用 git for-each-ref 获取所有分支和tag
const allRefList = await getAllRefList(
['refname', 'objectname:short', 'worktreepath', 'authordate', 'HEAD'],
cwd,
);
type RefList = typeof allRefList;
let branchList: RefList = [];
let remoteBranchList: RefList = [];
let tagList: RefList = [];
allRefList.forEach((item) => {
if (item.refname.startsWith('refs/heads/')) {
branchList.push(item);
} else if (item.refname.startsWith('refs/remotes/')) {
remoteBranchList.push(item);
} else if (item.refname.startsWith('refs/tags/')) {
tagList.push(item);
}
});
if (!branchList) {
quickPick.hide();
return;
}

const branchItems: BranchForWorkTree[] = branchList
.filter((i) => !i.worktreepath && i.HEAD !== '*')
.map((item) => {
const shortRefName = item['refname:short'].replace(/^heads\//, '');
const shortRefName = item['refname'].replace('refs/heads/', '');
return {
label: shortRefName,
description: `$(git-commit) ${item['objectname:short']} $(circle-small-filled) ${formatTime(
Expand All @@ -84,14 +94,15 @@ export const pickBranch = async (
...branchList
.filter((i) => i.worktreepath)
.map((item) => {
const shortName = item['refname'].replace('refs/heads/', '');
return {
label: item['refname:short'],
label: shortName,
description: `$(git-commit) ${item['objectname:short']} $(circle-small-filled) ${formatTime(
item.authordate,
)}`,
iconPath: new vscode.ThemeIcon('source-control'),
hash: item['objectname:short'],
branch: item['refname:short'],
branch: shortName,
};
}),
{
Expand All @@ -102,18 +113,18 @@ export const pickBranch = async (

const remoteBranchItems: BranchForWorkTree[] = remoteBranchList.map((item) => {
return {
label: item['refname:short'].replace(/^remotes\//, ''),
label: item['refname'].replace('refs/remotes/', ''),
iconPath: new vscode.ThemeIcon('cloud'),
description: item['objectname:short'],
description: item['objectname:short'] + ' ' + localize('remoteBranch'),
hash: item['objectname:short'],
};
});

const tagItems: BranchForWorkTree[] = tagList.map((item) => {
return {
label: item['refname:short'].replace(/^tags\//, ''),
label: item['refname'].replace('refs/tags/', ''),
iconPath: new vscode.ThemeIcon('tag'),
description: item['objectname:short'],
description: item['objectname:short'] + ' ' + localize('tag'),
hash: item['objectname:short'],
};
});
Expand Down
2 changes: 2 additions & 0 deletions src/lib/treeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class WorkTreeItem extends vscode.TreeItem {
name: string;
type = TreeItemKind.worktree;
parent?: GitFolderItem;
remoteRef?: string;
constructor(item: IWorkTreeDetail, collapsible: vscode.TreeItemCollapsibleState, parent?: GitFolderItem) {
let finalName = item.folderName ? `${item.name}${item.folderName}` : item.name;
super(finalName, collapsible);
Expand Down Expand Up @@ -54,6 +55,7 @@ export class WorkTreeItem extends vscode.TreeItem {

this.path = item.path;
this.name = item.name;
this.remoteRef = item.remoteRef;

this.tooltip = new vscode.MarkdownString('', true);
this.tooltip.appendMarkdown(localize('treeView.tooltip.folder', item.path));
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface IWorkTreeDetail {
folderName?: string;
ahead?: number;
behind?: number;
remoteRef?: string;
}

export interface IWorkTreeOutputItem {
Expand Down
82 changes: 14 additions & 68 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,11 @@ export async function getWorkTreeList(root?: string, skipRemote?: boolean): Prom
let detailList = await Promise.all(
(list as unknown as IWorkTreeOutputItem[]).map(async (item) => {
const branchName = item.branch?.replace('refs/heads/', '') || '';
const remoteBranchName = `${remoteName}/${branchName}`;
const hasRemote = remoteBranchMap.has(`refs/remotes/${remoteBranchName}`);
const [aheadBehind, nameRev] = await Promise.all([
!skipRemote &&
branchName &&
remoteName &&
remoteBranchMap.has(`refs/remotes/${remoteName}/${branchName}`)
? getAheadBehindCommitCount(
branchName,
`refs/remotes/${remoteName}/${branchName}`,
item.worktree,
)
!skipRemote && branchName && remoteName && hasRemote
? getAheadBehindCommitCount(branchName, `refs/remotes/${remoteBranchName}`, item.worktree)
: Promise.resolve(void 0),
!branchName ? getNameRev(item.worktree) : Promise.resolve(''),
]);
Expand Down Expand Up @@ -170,6 +165,7 @@ export async function getWorkTreeList(root?: string, skipRemote?: boolean): Prom
ahead: aheadBehind?.ahead,
behind: aheadBehind?.behind,
hash: item.HEAD,
remoteRef: hasRemote ? remoteBranchName : void 0,
};
}),
);
Expand Down Expand Up @@ -199,52 +195,12 @@ export function parseOutput<T extends string>(output: string, keyList: T[]): Rec
return workTrees;
}

export async function getBranchList<T extends string>(keys: T[], cwd?: string) {
try {
let output = await executeGitCommandAuto(cwd, [
'branch',
`--format=${formatQuery(keys)}`,
'--sort=-committerdate',
]);
return parseOutput(output, keys);
} catch {
return [];
}
}

export async function getRemoteBranchList<T extends string>(keys: T[], cwd?: string) {
try {
let output = await executeGitCommandAuto(cwd, [
'branch',
'-r',
`--format=${formatQuery(keys)}`,
'--sort=-committerdate',
]);
return parseOutput(output, keys);
} catch {
return [];
}
}

export async function getTagList<T extends string>(keys: T[], cwd?: string) {
try {
let output = await executeGitCommandAuto(cwd, [
'tag',
'--list',
`--format=${formatQuery(keys)}`,
'--sort=-committerdate',
]);
return parseOutput(output, keys);
} catch {
return [];
}
}

export async function getAllRefList<T extends string>(keys: T[], cwd?: string) {
try {
let output = await executeGitCommandAuto(cwd, [
'for-each-ref',
`--format=${formatQuery(keys)}`,
'--sort=-refname:lstrip=2',
'--sort=-committerdate',
]);
return parseOutput(output, keys);
Expand Down Expand Up @@ -351,21 +307,21 @@ export const checkoutBranch = (cwd: string, branchName: string, ...args: string[
return executeGitCommandAuto(cwd, ['switch', '--ignore-other-worktrees', ...list]);
};

export const pullBranch = (remoteName: string, branchName: string, remoteBranchName: string, cwd?: string) => {
export const pullBranch = (remoteName: string, branchName: string, cwd?: string) => {
const token = new vscode.CancellationTokenSource();
actionProgressWrapper(
localize('cmd.pullWorkTree'),
() => executeGitCommandAuto(cwd, ['pull', remoteName, `${remoteBranchName}:${branchName}`], token.token),
() => executeGitCommandAuto(cwd, ['pull', remoteName, `${branchName}:${branchName}`], token.token),
updateTreeDataEvent.fire.bind(updateTreeDataEvent),
token,
);
};

export const pushBranch = (remoteName: string, localBranchName: string, remoteBranchName: string, cwd?: string) => {
export const pushBranch = (remoteName: string, branchName: string, cwd?: string) => {
const token = new vscode.CancellationTokenSource();
actionProgressWrapper(
localize('cmd.pushWorkTree'),
() => executeGitCommandAuto(cwd, ['push', remoteName, `${localBranchName}:${remoteBranchName}`], token.token),
() => executeGitCommandAuto(cwd, ['push', remoteName, `${branchName}:${branchName}`], token.token),
updateTreeDataEvent.fire.bind(updateTreeDataEvent),
token,
);
Expand Down Expand Up @@ -393,18 +349,8 @@ export const checkExist = (path: string) => {
.catch(() => false);
};

export const pullOrPushAction = async (action: 'pull' | 'push', branchName: string, cwd: string) => {
const remoteBranchList = await getRemoteBranchList(['refname:short'], cwd);
const item = remoteBranchList.find((row) => {
const [remoteName, ...remoteBranchNameArgs] = row['refname:short'].replace(/^remotes\//, '').split('/');
return remoteBranchNameArgs.join('/').toLowerCase() === branchName.toLowerCase();
});
if (!item) {
return false;
}
const [remoteName, ...remoteBranchNameArgs] = item['refname:short'].replace(/^remotes\//, '').split('/');
const remoteBranchName = remoteBranchNameArgs.join('/');
return action === 'pull'
? pullBranch(remoteName, branchName, remoteBranchName, cwd)
: pushBranch(remoteName, branchName, remoteBranchName, cwd);
export const pullOrPushAction = async (action: 'pull' | 'push', refName: string, cwd: string) => {
const [remoteName, ...remoteBranchNameArgs] = refName.split('/');
const branchName = remoteBranchNameArgs.join('/');
return action === 'pull' ? pullBranch(remoteName, branchName, cwd) : pushBranch(remoteName, branchName, cwd);
};

0 comments on commit be987bf

Please sign in to comment.