From 91865e21f38523555a5a7ffab310cfccaf4d5de2 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Sun, 31 May 2026 03:25:45 -0700 Subject: [PATCH] fix: build bitbucket line anchors (#4074) --- src/main/git/hosted-remote-url.test.ts | 8 +++++++- src/main/git/hosted-remote-url.ts | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/git/hosted-remote-url.test.ts b/src/main/git/hosted-remote-url.test.ts index 977ea3607..60a30e0dc 100644 --- a/src/main/git/hosted-remote-url.test.ts +++ b/src/main/git/hosted-remote-url.test.ts @@ -54,7 +54,7 @@ describe('hosted remote URLs', () => { expect( buildHostedRemoteFileUrl('git@bitbucket.org:team/repo.git', 'src/a.ts', 'feature/x', 7) - ).toBe('https://bitbucket.org/team/repo/src/feature%2Fx/src/a.ts#L7') + ).toBe('https://bitbucket.org/team/repo/src/feature%2Fx/src/a.ts#a.ts-7') expect( buildHostedRemoteFileUrl( @@ -66,6 +66,12 @@ describe('hosted remote URLs', () => { ).toBe('https://github.com/Org/Repo/blob/feature%2Fx/src/a.ts#L5') }) + it('builds Bitbucket line fragments from the target file name', () => { + expect( + buildHostedRemoteFileUrl('https://bitbucket.org/team/repo.git', 'src/a file.ts', 'main', 29) + ).toBe('https://bitbucket.org/team/repo/src/main/src/a%20file.ts#a%20file.ts-29') + }) + it('rejects unsupported hosts and incomplete repo paths', () => { expect(parseHostedRemote('git@example.com:team/repo.git')).toBeNull() expect(parseHostedRemote('git@github.com:repo.git')).toBeNull() diff --git a/src/main/git/hosted-remote-url.ts b/src/main/git/hosted-remote-url.ts index 84882cc71..0af711b1f 100644 --- a/src/main/git/hosted-remote-url.ts +++ b/src/main/git/hosted-remote-url.ts @@ -96,6 +96,11 @@ function encodeRelativePath(path: string): string { return path.replaceAll('\\', '/').split('/').filter(Boolean).map(encodeURIComponent).join('/') } +function encodeBitbucketFileLineFragment(path: string, line: number): string { + const fileName = path.replaceAll('\\', '/').split('/').filter(Boolean).at(-1) + return fileName ? `#${encodeURIComponent(`${fileName}-${line}`)}` : '' +} + export function buildHostedRemoteFileUrl( remoteUrl: string, relativePath: string, @@ -119,5 +124,5 @@ export function buildHostedRemoteFileUrl( if (remote.provider === 'gitlab') { return `${baseUrl}/-/blob/${encodedBranch}${filePathSuffix}#L${line}` } - return `${baseUrl}/src/${encodedBranch}${filePathSuffix}#L${line}` + return `${baseUrl}/src/${encodedBranch}${filePathSuffix}${encodeBitbucketFileLineFragment(relativePath, line)}` }