mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-24 18:12:48 +03:00
fix: improve git remoteUrl parsing (#4147)
This commit is contained in:
parent
cf2adf4d68
commit
d013b7baf7
@ -58,6 +58,7 @@
|
||||
"@types/diff": "^5.2.1",
|
||||
"@types/diff-match-patch": "^1.0.36",
|
||||
"@types/eslint__js": "^8.42.3",
|
||||
"@types/git-url-parse": "^9.0.3",
|
||||
"@types/lscache": "^1.3.4",
|
||||
"@types/marked": "^5.0.2",
|
||||
"@typescript-eslint/parser": "^7.13.1",
|
||||
@ -72,6 +73,7 @@
|
||||
"eslint-plugin-import-x": "^0.5.1",
|
||||
"eslint-plugin-square-svelte-store": "^1.0.0",
|
||||
"eslint-plugin-svelte": "2.40.0",
|
||||
"git-url-parse": "^14.0.0",
|
||||
"globals": "^15.6.0",
|
||||
"inter-ui": "^4.0.2",
|
||||
"leven": "^4.0.0",
|
||||
|
42
app/src/lib/github/service.test.ts
Normal file
42
app/src/lib/github/service.test.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { GitHubService } from './service';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { expect, test, describe } from 'vitest';
|
||||
|
||||
const exampleRemoteUrls = [
|
||||
'ssh://user@host.xz:123/org/repo.git/',
|
||||
'ssh://user@host.xz/org/repo.git/',
|
||||
'ssh://host.xz:123/org/repo.git/',
|
||||
'ssh://host.xz:123/org/repo',
|
||||
'ssh://host.xz/org/repo.git/',
|
||||
'ssh://host.xz/org/repo.git',
|
||||
'ssh://host.xz/org/repo',
|
||||
'ssh://user@host.xz/org/repo.git/',
|
||||
'ssh://user@host.xz/org/repo.git',
|
||||
'ssh://user@host.xz/org/repo',
|
||||
'host.xz:org/repo.git/',
|
||||
'host.xz:org/repo.git',
|
||||
'host.xz:org/repo',
|
||||
'user@host.xz:org/repo.git/',
|
||||
'user@host.xz:org/repo.git',
|
||||
'user@host.xz:org/repo',
|
||||
'git@github.com:org/repo.git/',
|
||||
'git@github.com:org/repo.git',
|
||||
'git@github.com:org/repo',
|
||||
'https://github.com/org/repo.git/',
|
||||
'https://github.com/org/repo.git',
|
||||
'https://github.com/org/repo'
|
||||
];
|
||||
|
||||
describe.concurrent('GitHubService', () => {
|
||||
describe.concurrent('parse GitHub remote URL', () => {
|
||||
test.each(exampleRemoteUrls)('%s', (remoteUrl) => {
|
||||
const accessToken$ = new BehaviorSubject<string | undefined>('token');
|
||||
const remoteUrl$ = new BehaviorSubject<string | undefined>(remoteUrl);
|
||||
|
||||
const githubService = new GitHubService(accessToken$, remoteUrl$);
|
||||
|
||||
expect(githubService.owner).toBe('org');
|
||||
expect(githubService.repo).toBe('repo');
|
||||
});
|
||||
});
|
||||
});
|
@ -12,6 +12,7 @@ import { showError, showToast, type Toast } from '$lib/notifications/toasts';
|
||||
import { sleep } from '$lib/utils/sleep';
|
||||
import * as toasts from '$lib/utils/toasts';
|
||||
import { Octokit } from '@octokit/rest';
|
||||
import GitUrlParse from 'git-url-parse';
|
||||
import lscache from 'lscache';
|
||||
import posthog from 'posthog-js';
|
||||
import {
|
||||
@ -78,8 +79,8 @@ export class GitHubService {
|
||||
baseUrl: 'https://api.github.com'
|
||||
});
|
||||
if (remoteUrl) {
|
||||
const [owner, repo] = remoteUrl.split(/.git$/)[0].split(/\/|:/).slice(-2);
|
||||
this._repo = repo;
|
||||
const { owner, name } = GitUrlParse(remoteUrl);
|
||||
this._repo = name;
|
||||
this._owner = owner;
|
||||
}
|
||||
}),
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { convertRemoteToWebUrl } from '$lib/utils/url';
|
||||
import { remoteUrlIsHttp, convertRemoteToWebUrl } from '$lib/utils/url';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
describe.concurrent('cleanUrl', () => {
|
||||
@ -25,4 +25,20 @@ describe.concurrent('cleanUrl', () => {
|
||||
'https://github.com/user/repo'
|
||||
);
|
||||
});
|
||||
|
||||
const httpRemoteUrls = ['https://github.com/user/repo.git', 'http://192.168.1.1/user/repo.git'];
|
||||
|
||||
test.each(httpRemoteUrls)('HTTP Remote - %s', (remoteUrl) => {
|
||||
expect(remoteUrlIsHttp(remoteUrl)).toBe(true);
|
||||
});
|
||||
|
||||
const nonHttpRemoteUrls = [
|
||||
'git@github.com:user/repo.git',
|
||||
'ssh://git@github.com:22/user/repo.git',
|
||||
'git://github.com/user/repo.git'
|
||||
];
|
||||
|
||||
test.each(nonHttpRemoteUrls)('Non HTTP Remote - %s', (remoteUrl) => {
|
||||
expect(remoteUrlIsHttp(remoteUrl)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { showToast } from '$lib/notifications/toasts';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
import GitUrlParse from 'git-url-parse';
|
||||
import { posthog } from 'posthog-js';
|
||||
|
||||
export function openExternalUrl(href: string) {
|
||||
@ -25,20 +26,16 @@ export function openExternalUrl(href: string) {
|
||||
|
||||
// turn a git remote url into a web url (github, gitlab, bitbucket, etc)
|
||||
export function convertRemoteToWebUrl(url: string): string {
|
||||
if (url.startsWith('http')) {
|
||||
return url.replace('.git', '').trim();
|
||||
} else if (url.startsWith('ssh')) {
|
||||
url = url.replace('ssh://git@', '');
|
||||
const [host, ...paths] = url.split('/');
|
||||
const path = paths.join('/').replace('.git', '');
|
||||
const protocol = /\d+\.\d+\.\d+\.\d+/.test(host) ? 'http' : 'https';
|
||||
const [hostname, _port] = host.split(':');
|
||||
return `${protocol}://${hostname}/${path}`;
|
||||
} else {
|
||||
return url.replace(':', '/').replace('git@', 'https://').replace('.git', '').trim();
|
||||
}
|
||||
const gitRemote = GitUrlParse(url);
|
||||
const ipv4Regex = new RegExp(/^([0-9]+(\.|$)){4}/);
|
||||
const protocol = ipv4Regex.test(gitRemote.resource) ? 'http' : 'https';
|
||||
|
||||
return `${protocol}://${gitRemote.resource}/${gitRemote.owner}/${gitRemote.name}`;
|
||||
}
|
||||
|
||||
export function remoteUrlIsHttp(url: string): boolean {
|
||||
return url.startsWith('http');
|
||||
const httpProtocols = ['http', 'https'];
|
||||
const gitRemote = GitUrlParse(url);
|
||||
|
||||
return httpProtocols.includes(gitRemote.protocol);
|
||||
}
|
||||
|
@ -114,6 +114,9 @@ importers:
|
||||
'@types/eslint__js':
|
||||
specifier: ^8.42.3
|
||||
version: 8.42.3
|
||||
'@types/git-url-parse':
|
||||
specifier: ^9.0.3
|
||||
version: 9.0.3
|
||||
'@types/lscache':
|
||||
specifier: ^1.3.4
|
||||
version: 1.3.4
|
||||
@ -156,6 +159,9 @@ importers:
|
||||
eslint-plugin-svelte:
|
||||
specifier: 2.40.0
|
||||
version: 2.40.0(eslint@9.5.0)(svelte@5.0.0-next.149)
|
||||
git-url-parse:
|
||||
specifier: ^14.0.0
|
||||
version: 14.0.0
|
||||
globals:
|
||||
specifier: ^15.6.0
|
||||
version: 15.6.0
|
||||
@ -1312,6 +1318,9 @@ packages:
|
||||
'@types/express@4.17.21':
|
||||
resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==}
|
||||
|
||||
'@types/git-url-parse@9.0.3':
|
||||
resolution: {integrity: sha512-Wrb8zeghhpKbYuqAOg203g+9YSNlrZWNZYvwxJuDF4dTmerijqpnGbI79yCuPtHSXHPEwv1pAFUB4zsSqn82Og==}
|
||||
|
||||
'@types/http-assert@1.5.5':
|
||||
resolution: {integrity: sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g==}
|
||||
|
||||
@ -2091,6 +2100,12 @@ packages:
|
||||
get-tsconfig@4.7.5:
|
||||
resolution: {integrity: sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==}
|
||||
|
||||
git-up@7.0.0:
|
||||
resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==}
|
||||
|
||||
git-url-parse@14.0.0:
|
||||
resolution: {integrity: sha512-NnLweV+2A4nCvn4U/m2AoYu0pPKlsmhK9cknG7IMwsjFY1S2jxM+mAhsDxyxfCIGfGaD+dozsyX4b6vkYc83yQ==}
|
||||
|
||||
glob-parent@5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -2318,6 +2333,9 @@ packages:
|
||||
resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-ssh@1.4.0:
|
||||
resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==}
|
||||
|
||||
is-string@1.0.7:
|
||||
resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2625,6 +2643,12 @@ packages:
|
||||
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
parse-path@7.0.0:
|
||||
resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==}
|
||||
|
||||
parse-url@8.1.0:
|
||||
resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==}
|
||||
|
||||
path-exists@4.0.0:
|
||||
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
|
||||
engines: {node: '>=8'}
|
||||
@ -2789,6 +2813,9 @@ packages:
|
||||
resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
protocols@2.0.1:
|
||||
resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==}
|
||||
|
||||
proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
|
||||
@ -4621,6 +4648,8 @@ snapshots:
|
||||
'@types/qs': 6.9.15
|
||||
'@types/serve-static': 1.15.7
|
||||
|
||||
'@types/git-url-parse@9.0.3': {}
|
||||
|
||||
'@types/http-assert@1.5.5': {}
|
||||
|
||||
'@types/http-errors@2.0.4': {}
|
||||
@ -5590,6 +5619,15 @@ snapshots:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
|
||||
git-up@7.0.0:
|
||||
dependencies:
|
||||
is-ssh: 1.4.0
|
||||
parse-url: 8.1.0
|
||||
|
||||
git-url-parse@14.0.0:
|
||||
dependencies:
|
||||
git-up: 7.0.0
|
||||
|
||||
glob-parent@5.1.2:
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
@ -5822,6 +5860,10 @@ snapshots:
|
||||
dependencies:
|
||||
call-bind: 1.0.7
|
||||
|
||||
is-ssh@1.4.0:
|
||||
dependencies:
|
||||
protocols: 2.0.1
|
||||
|
||||
is-string@1.0.7:
|
||||
dependencies:
|
||||
has-tostringtag: 1.0.2
|
||||
@ -6099,6 +6141,14 @@ snapshots:
|
||||
dependencies:
|
||||
callsites: 3.1.0
|
||||
|
||||
parse-path@7.0.0:
|
||||
dependencies:
|
||||
protocols: 2.0.1
|
||||
|
||||
parse-url@8.1.0:
|
||||
dependencies:
|
||||
parse-path: 7.0.0
|
||||
|
||||
path-exists@4.0.0: {}
|
||||
|
||||
path-is-absolute@1.0.1: {}
|
||||
@ -6223,6 +6273,8 @@ snapshots:
|
||||
|
||||
progress@2.0.3: {}
|
||||
|
||||
protocols@2.0.1: {}
|
||||
|
||||
proxy-from-env@1.1.0: {}
|
||||
|
||||
punycode@2.3.0: {}
|
||||
|
Loading…
Reference in New Issue
Block a user