ソースを参照

Adds better remote compare for PR remote matching

main
Eric Amodio 1年前
コミット
3db5bd62f3
3個のファイルの変更62行の追加52行の削除
  1. +1
    -1
      src/commands/ghpr/createWorktree.ts
  2. +11
    -1
      src/git/models/remote.ts
  3. +50
    -50
      src/git/parsers/remoteParser.ts

+ 1
- 1
src/commands/ghpr/createWorktree.ts ファイルの表示

@ -81,7 +81,7 @@ export class CreateWorktreeCommand extends Command {
const remoteUrl = remoteUri.toString();
let remote: GitRemote | undefined;
[remote] = await repo.getRemotes({ filter: r => r.url === remoteUrl });
[remote] = await repo.getRemotes({ filter: r => r.matches(remoteUrl) });
if (remote == null) {
const result = await window.showInformationMessage(
`Unable to find a remote for '${remoteUrl}'. Would you like to add a new remote?`,

+ 11
- 1
src/git/models/remote.ts ファイルの表示

@ -2,8 +2,10 @@ import type { ColorTheme } from 'vscode';
import { Uri, window } from 'vscode';
import { GlyphChars } from '../../constants';
import { Container } from '../../container';
import { sortCompare } from '../../system/string';
import { memoize } from '../../system/decorators/memoize';
import { equalsIgnoreCase, sortCompare } from '../../system/string';
import { isLightTheme } from '../../system/utils';
import { parseGitRemoteUrl } from '../parsers/remoteParser';
import type { RemoteProvider } from '../remotes/remoteProvider';
import type { RichRemoteProvider } from '../remotes/richRemoteProvider';
@ -68,6 +70,7 @@ export class GitRemote
return this.id === defaultRemote;
}
@memoize()
get url(): string {
let bestUrl: string | undefined;
for (const remoteUrl of this.urls) {
@ -87,6 +90,13 @@ export class GitRemote
return this.provider?.hasRichIntegration() ?? false;
}
matches(url: string): boolean {
if (equalsIgnoreCase(url, this.url)) return true;
const [, domain, path] = parseGitRemoteUrl(url);
return equalsIgnoreCase(domain, this.domain) && equalsIgnoreCase(path, this.path);
}
async setAsDefault(value: boolean = true) {
const repository = Container.instance.git.getRepository(this.repoPath);
await repository?.setRemoteAsDefault(this, value);

+ 50
- 50
src/git/parsers/remoteParser.ts ファイルの表示

@ -6,46 +6,6 @@ import type { getRemoteProviderMatcher } from '../remotes/remoteProviders';
const emptyStr = '';
const remoteRegex = /^(.*)\t(.*)\s\((.*)\)$/gm;
const urlRegex =
/^(?:(git:\/\/)(.*?)\/|(https?:\/\/)(?:.*?@)?(.*?)\/|git@(.*):|(ssh:\/\/)(?:.*@)?(.*?)(?::.*?)?(?:\/|(?=~))|(?:.*?@)(.*?):)(.*)$/;
// Test git urls
/*
http://host.xz/user/project.git
http://host.xz/path/to/repo.git
http://host.xz/path/to/repo.git/
http://username@host.xz/user/project.git
http://username:password@host.xz/user/project.git
https://host.xz/user/project.git
https://host.xz/path/to/repo.git
https://host.xz/path/to/repo.git/
https://username@host.xz/user/project.git
https://username:password@host.xz/user/project.git
git@host.xz:user/project.git
git://host.xz/path/to/repo.git/
git://host.xz/~user/path/to/repo.git/
ssh://host.xz/project.git
ssh://host.xz/path/to/repo.git
ssh://host.xz/path/to/repo.git/
ssh://host.xz:~project.git
ssh://host.xz:port/path/to/repo.git/
ssh://user@host.xz/project.git
ssh://user@host.xz/path/to/repo.git
ssh://user@host.xz/path/to/repo.git/
ssh://user@host.xz:port/path/to/repo.git/
ssh://user:password@host.xz/project.git
ssh://user:password@host.xz/path/to/repo.git
ssh://user:password@host.xz/path/to/repo.git/
user@host.xz:project.git
user@host.xz:path/to/repo.git
user@host.xz:/path/to/repo.git/
user:password@host.xz:project.git
user:password@host.xz:/path/to/repo.git
user:password@host.xz:/path/to/repo.git/
*/
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class GitRemoteParser {
@ -81,7 +41,7 @@ export class GitRemoteParser {
// Stops excessive memory usage -- https://bugs.chromium.org/p/v8/issues/detail?id=2869
url = ` ${url}`.substr(1);
[scheme, domain, path] = this.parseGitUrl(url);
[scheme, domain, path] = parseGitRemoteUrl(url);
uniqueness = `${domain ? `${domain}/` : ''}${path}`;
remote = groups[uniqueness];
@ -110,15 +70,55 @@ export class GitRemoteParser {
return remotes;
}
}
static parseGitUrl(url: string): [string, string, string] {
const match = urlRegex.exec(url);
if (match == null) return [emptyStr, emptyStr, url];
// Test git urls
/*
http://host.xz/user/project.git
http://host.xz/path/to/repo.git
http://host.xz/path/to/repo.git/
http://username@host.xz/user/project.git
http://username:password@host.xz/user/project.git
https://host.xz/user/project.git
https://host.xz/path/to/repo.git
https://host.xz/path/to/repo.git/
https://username@host.xz/user/project.git
https://username:password@host.xz/user/project.git
return [
match[1] || match[3] || match[6],
match[2] || match[4] || match[5] || match[7] || match[8],
match[9].replace(/\.git\/?$/, emptyStr),
];
}
git@host.xz:user/project.git
git://host.xz/path/to/repo.git/
git://host.xz/~user/path/to/repo.git/
ssh://host.xz/project.git
ssh://host.xz/path/to/repo.git
ssh://host.xz/path/to/repo.git/
ssh://host.xz:~project.git
ssh://host.xz:port/path/to/repo.git/
ssh://user@host.xz/project.git
ssh://user@host.xz/path/to/repo.git
ssh://user@host.xz/path/to/repo.git/
ssh://user@host.xz:port/path/to/repo.git/
ssh://user:password@host.xz/project.git
ssh://user:password@host.xz/path/to/repo.git
ssh://user:password@host.xz/path/to/repo.git/
user@host.xz:project.git
user@host.xz:path/to/repo.git
user@host.xz:/path/to/repo.git/
user:password@host.xz:project.git
user:password@host.xz:/path/to/repo.git
user:password@host.xz:/path/to/repo.git/
*/
const urlRegex =
/^(?:(git:\/\/)(.*?)\/|(https?:\/\/)(?:.*?@)?(.*?)\/|git@(.*):|(ssh:\/\/)(?:.*@)?(.*?)(?::.*?)?(?:\/|(?=~))|(?:.*?@)(.*?):)(.*)$/;
export function parseGitRemoteUrl(url: string): [scheme: string, domain: string, path: string] {
const match = urlRegex.exec(url);
if (match == null) return [emptyStr, emptyStr, url];
return [
match[1] || match[3] || match[6],
match[2] || match[4] || match[5] || match[7] || match[8],
match[9].replace(/\.git\/?$/, emptyStr),
];
}

読み込み中…
キャンセル
保存