mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
* feat: expandable commits and actions in the git history panel Expand a commit row in the Commits panel to see its changed files inline; click a file to open that file's commit diff. Author and date surface on expand, so the dense row itself stays subject-only. Right-click a commit for: open in the in-app browser, copy hash, copy message, and explain changes (spawns the default agent seeded with the commit context). Open-in-browser resolves the provider commit URL in the main process via a new remoteCommitUrl resolver (GitHub/GitLab/Bitbucket), mirroring the existing remoteFileUrl chain end-to-end (repo, IPC, SSH provider, runtime RPC, preload) so it works for local and SSH/remote workspaces. Layout: subject-first single-line rows with a tighter graph, refs moved inline, and local/remote ref pills deduped when they point at the same commit. * fix: address git history review feedback * fix: address PR review feedback on the git history panel - Trim commit SHA before building the remote URL so whitespace input returns null instead of an invalid %20 URL. - Gate commit-row expansion on the file loader (onLoadCommitFiles) so a row can't expand into a perpetual loading state. - Harden the explain prompt: treat the commit subject and diff as untrusted data and run git show --no-ext-diff. - Keep ambiguous multi-segment remote refs instead of mis-deduping them against a local branch. - Use standard 10-char i18n keys for the new commit-history strings and translate them into es/ja/ko/zh. * refactor: extract commit-history actions into useGitHistoryCommitActions hook Moves the commit load/open/context-menu action callbacks (and the per-commit compare cache) out of SourceControl.tsx — which already carries a max-lines disable — into a focused hook, addressing the PR review nitpick. Behavior is unchanged. * Refine git history row rendering, ref deduplication, and OID validation - Prevent deduplication of remote branch badges in the history view when multiple remotes exist or when a ref is explicitly preserved. - Render GitHistoryRow as an accessible button with dynamic ARIA labels for expansion states. - Add double-click handler on commit files to open them permanently. - Validate commit SHAs as full 40-character Git object IDs before requesting remote commit URLs. --------- Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
108 lines
3.7 KiB
TypeScript
108 lines
3.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
buildHostedRemoteCommitUrl,
|
|
buildHostedRemoteFileUrl,
|
|
parseHostedRemote
|
|
} from './hosted-remote-url'
|
|
|
|
describe('hosted remote URLs', () => {
|
|
it('parses common GitHub remote formats', () => {
|
|
expect(parseHostedRemote('https://github.com/Org/Repo.git')).toEqual({
|
|
host: 'github.com',
|
|
path: 'Org/Repo',
|
|
provider: 'github'
|
|
})
|
|
expect(parseHostedRemote('git@github.com:Org/Repo.git')).toEqual({
|
|
host: 'github.com',
|
|
path: 'Org/Repo',
|
|
provider: 'github'
|
|
})
|
|
expect(parseHostedRemote('ssh://git@github.com/Org/Repo.git')).toEqual({
|
|
host: 'github.com',
|
|
path: 'Org/Repo',
|
|
provider: 'github'
|
|
})
|
|
expect(parseHostedRemote('ssh://git@ssh.github.com:443/Org/Repo.git')).toEqual({
|
|
host: 'github.com',
|
|
path: 'Org/Repo',
|
|
provider: 'github'
|
|
})
|
|
expect(parseHostedRemote('github:Org/Repo')).toEqual({
|
|
host: 'github.com',
|
|
path: 'Org/Repo',
|
|
provider: 'github'
|
|
})
|
|
})
|
|
|
|
it('parses nested GitLab and Bitbucket remotes', () => {
|
|
expect(parseHostedRemote('git@gitlab.com:group/sub/repo.git')).toEqual({
|
|
host: 'gitlab.com',
|
|
path: 'group/sub/repo',
|
|
provider: 'gitlab'
|
|
})
|
|
expect(parseHostedRemote('https://bitbucket.org/team/repo.git')).toEqual({
|
|
host: 'bitbucket.org',
|
|
path: 'team/repo',
|
|
provider: 'bitbucket'
|
|
})
|
|
})
|
|
|
|
it('builds file URLs with encoded branches and paths', () => {
|
|
expect(
|
|
buildHostedRemoteFileUrl('git@github.com:Org/Repo.git', 'src/a file.ts', 'feature/x', 42)
|
|
).toBe('https://github.com/Org/Repo/blob/feature%2Fx/src/a%20file.ts#L42')
|
|
|
|
expect(
|
|
buildHostedRemoteFileUrl('git@gitlab.com:group/sub/repo.git', 'src/a.ts', 'feature/x', 9)
|
|
).toBe('https://gitlab.com/group/sub/repo/-/blob/feature%2Fx/src/a.ts#L9')
|
|
|
|
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#a.ts-7')
|
|
|
|
expect(
|
|
buildHostedRemoteFileUrl(
|
|
'ssh://git@ssh.github.com:443/Org/Repo.git',
|
|
'src/a.ts',
|
|
'feature/x',
|
|
5
|
|
)
|
|
).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('builds commit URLs per provider from ssh and https remotes', () => {
|
|
const sha = '0123456789abcdef0123456789abcdef01234567'
|
|
expect(buildHostedRemoteCommitUrl('git@github.com:Org/Repo.git', sha)).toBe(
|
|
`https://github.com/Org/Repo/commit/${sha}`
|
|
)
|
|
expect(buildHostedRemoteCommitUrl('https://gitlab.com/group/sub/repo.git', sha)).toBe(
|
|
`https://gitlab.com/group/sub/repo/-/commit/${sha}`
|
|
)
|
|
expect(buildHostedRemoteCommitUrl('git@bitbucket.org:team/repo.git', sha)).toBe(
|
|
`https://bitbucket.org/team/repo/commits/${sha}`
|
|
)
|
|
})
|
|
|
|
it('returns null for unsupported commit remotes or missing sha', () => {
|
|
expect(
|
|
buildHostedRemoteCommitUrl(
|
|
'git@example.com:team/repo.git',
|
|
'0123456789abcdef0123456789abcdef01234567'
|
|
)
|
|
).toBeNull()
|
|
expect(buildHostedRemoteCommitUrl('git@github.com:Org/Repo.git', '')).toBeNull()
|
|
})
|
|
|
|
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()
|
|
expect(parseHostedRemote('ftp://github.com/Org/Repo.git')).toBeNull()
|
|
})
|
|
})
|