mirror of
https://github.com/garrytan/gstack.git
synced 2026-07-18 13:37:23 +02:00
fix(gbrain): canonicalize remotes with trailing slashes
This commit is contained in:
@@ -106,9 +106,15 @@ export function canonicalizeRemote(url: string | null | undefined): string {
|
||||
// strip user@ prefix on URL-style remotes
|
||||
s = s.replace(/^[^@\/]+@/, "");
|
||||
}
|
||||
// strip trailing slash(es) first, so a URL written with a trailing slash
|
||||
// still matches the `.git$` suffix below (e.g. ".../repo.git/" must
|
||||
// canonicalize to ".../repo", not ".../repo.git").
|
||||
s = s.replace(/\/+$/, "");
|
||||
// strip trailing .git
|
||||
s = s.replace(/\.git$/i, "");
|
||||
// strip trailing slash
|
||||
// re-strip trailing slash(es): a path remote ending in a `.git` directory
|
||||
// component ("/repo/.git") exposes a new trailing slash once `.git` is
|
||||
// stripped, which would split the repo into a second identity.
|
||||
s = s.replace(/\/+$/, "");
|
||||
// collapse multiple slashes (after path normalization)
|
||||
s = s.replace(/\/{2,}/g, "/");
|
||||
|
||||
@@ -67,6 +67,30 @@ describe("canonicalizeRemote", () => {
|
||||
it("collapses redundant slashes", () => {
|
||||
expect(canonicalizeRemote("https://github.com//foo//bar")).toBe("github.com/foo/bar");
|
||||
});
|
||||
|
||||
it("strips .git even when the URL has a trailing slash", () => {
|
||||
// A remote configured with both a .git suffix and a trailing slash must
|
||||
// canonicalize to the same key as one without — otherwise the same repo
|
||||
// gets two dedup/source-id keys across machines.
|
||||
expect(canonicalizeRemote("https://github.com/garrytan/gstack.git/")).toBe("github.com/garrytan/gstack");
|
||||
expect(canonicalizeRemote("git@github.com:garrytan/gstack.git/")).toBe("github.com/garrytan/gstack");
|
||||
expect(canonicalizeRemote("https://github.com/foo/bar.git///")).toBe("github.com/foo/bar");
|
||||
});
|
||||
|
||||
it("produces the same key with or without a trailing slash", () => {
|
||||
expect(canonicalizeRemote("https://github.com/garrytan/gstack.git/")).toBe(
|
||||
canonicalizeRemote("https://github.com/garrytan/gstack.git")
|
||||
);
|
||||
});
|
||||
|
||||
it("canonicalizes a path remote ending in a .git directory component", () => {
|
||||
// Stripping the `.git` suffix exposes a new trailing slash
|
||||
// ("/repo/.git" → "/repo/") which must also be stripped, or the same
|
||||
// repo splits into two identities.
|
||||
expect(canonicalizeRemote("file:///Users/x/repo/.git")).toBe(
|
||||
canonicalizeRemote("file:///Users/x/repo")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// ── secretScanFile ─────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user