1export function parseRemoteNamesInGitOrder(stdout: string): ReadonlyArray<string> {
2 const remoteNames: Array<string> = [];
3 for (const line of stdout.split("\n")) {
4 const remoteName = line.trim();
5 if (remoteName.length > 0) {
6 remoteNames.push(remoteName);
7 }
8 }
9 return remoteNames;
10}
11
12export function parseRemoteNames(stdout: string): ReadonlyArray<string> {
13 return parseRemoteNamesInGitOrder(stdout).toSorted((a, b) => b.length - a.length);
14}
15
16export function parseRemoteRefWithRemoteNames(
17 ref: string,
18 remoteNames: ReadonlyArray<string>,
19): { remoteRef: string; remoteName: string; branchName: string } | null {
20 const trimmedRef = ref.trim();
21 if (trimmedRef.length === 0) {
22 return null;
23 }
24
25 for (const remoteName of remoteNames) {
26 const remotePrefix = `${remoteName}/`;
27 if (!trimmedRef.startsWith(remotePrefix)) {
28 continue;
29 }
30 const branchName = trimmedRef.slice(remotePrefix.length).trim();
31 if (branchName.length === 0) {
32 return null;
33 }
34 return {
35 remoteRef: trimmedRef,
36 remoteName,
37 branchName,
38 };
39 }
40
41 return null;
42}
43
44export function extractBranchNameFromRemoteRef(
45 ref: string,
46 options?: {
47 remoteName?: string | null;
48 remoteNames?: ReadonlyArray<string>;
49 },
50): string {
51 const normalized = ref.trim();
52 if (normalized.length === 0) {
53 return "";
54 }
55
56 if (normalized.startsWith("refs/remotes/")) {
57 return extractBranchNameFromRemoteRef(normalized.slice("refs/remotes/".length), options);
58 }
59
60 const remoteNames = options?.remoteName ? [options.remoteName] : (options?.remoteNames ?? []);
61 const parsedRemoteRef = parseRemoteRefWithRemoteNames(normalized, remoteNames);
62 if (parsedRemoteRef) {
63 return parsedRemoteRef.branchName;
64 }
65
66 const firstSlash = normalized.indexOf("/");
67 if (firstSlash === -1) {
68 return normalized;
69 }
70 return normalized.slice(firstSlash + 1).trim();
71}