diff --git a/httpd-client/lib/project/commit.ts b/httpd-client/lib/project/commit.ts index 13f5c7bfa..14bd1b774 100644 --- a/httpd-client/lib/project/commit.ts +++ b/httpd-client/lib/project/commit.ts @@ -106,7 +106,7 @@ const diffAddedDeletedModifiedChangesetSchema = object({ }), }) satisfies ZodSchema; -interface DiffCopiedMovedChangeset { +export interface DiffCopiedMovedChangeset { newPath: string; oldPath: string; } diff --git a/src/views/projects/SourceBrowser/Changeset.svelte b/src/views/projects/SourceBrowser/Changeset.svelte index a4ef8cd14..01e043c5a 100644 --- a/src/views/projects/SourceBrowser/Changeset.svelte +++ b/src/views/projects/SourceBrowser/Changeset.svelte @@ -4,11 +4,18 @@ import { pluralize } from "@app/lib/pluralize"; import FileDiff from "@app/views/projects/SourceBrowser/FileDiff.svelte"; + import FileLocationChange from "@app/views/projects/SourceBrowser/FileLocationChange.svelte"; export let diff: Diff; export let revision: string; - const diffDescription = ({ modified, added, deleted }: Diff): string => { + const diffDescription = ({ + modified, + added, + deleted, + moved, + copied, + }: Diff): string => { const s = []; if (modified.length) { @@ -22,6 +29,12 @@ if (deleted.length) { s.push(`${deleted.length} ${pluralize("file", deleted.length)} deleted`); } + if (copied.length) { + s.push(`${copied.length} ${pluralize("file", copied.length)} copied`); + } + if (moved.length) { + s.push(`${moved.length} ${pluralize("file", moved.length)} moved`); + } return s.join(", "); }; @@ -54,12 +67,18 @@
{#each diff.added as file} - + {/each} {#each diff.deleted as file} - + {/each} {#each diff.modified as file} - + + {/each} + {#each diff.moved as file} + + {/each} + {#each diff.copied as file} + {/each}
diff --git a/src/views/projects/SourceBrowser/FileDiff.svelte b/src/views/projects/SourceBrowser/FileDiff.svelte index 0bf9f103a..cefbcd7be 100644 --- a/src/views/projects/SourceBrowser/FileDiff.svelte +++ b/src/views/projects/SourceBrowser/FileDiff.svelte @@ -10,7 +10,7 @@ export let file: DiffAddedDeletedModifiedChangeset; export let revision: string; - export let mode: string | null = null; + export let headerBadgeCaption: "added" | "deleted" | undefined = undefined; let collapsed = false; @@ -163,9 +163,9 @@

{file.path}

- {#if mode === "added"} + {#if headerBadgeCaption === "added"} added - {:else if mode === "deleted"} + {:else if headerBadgeCaption === "deleted"} deleted {/if}
diff --git a/src/views/projects/SourceBrowser/FileLocationChange.svelte b/src/views/projects/SourceBrowser/FileLocationChange.svelte new file mode 100644 index 000000000..849404035 --- /dev/null +++ b/src/views/projects/SourceBrowser/FileLocationChange.svelte @@ -0,0 +1,63 @@ + + + + +
+
+
+

{file.oldPath} → {file.newPath}

+ {#if mode === "moved"} + moved + {:else if mode === "copied"} + copied + {/if} +
+
+ + + +
+
+
diff --git a/tests/e2e/project/commit.spec.ts b/tests/e2e/project/commit.spec.ts index 5049e367f..c769559bc 100644 --- a/tests/e2e/project/commit.spec.ts +++ b/tests/e2e/project/commit.spec.ts @@ -81,6 +81,17 @@ test("deleted file", async ({ page }) => { await expect(page.locator("text=.hidden deleted")).toBeVisible(); }); +test("moved file", async ({ page }) => { + await page.goto( + `${sourceBrowsingUrl}/remotes/${aliceRemote}/commits/835d9a52066c46d86cdee88f2863e9a804c7fa50/commits/`, + ); + await expect( + page.locator("header").filter({ hasText: "moves/111.txt → moves/222.txt" }), + ).toBeVisible(); +}); + +// TODO: Add copy operation detection spec. + test("navigation to source tree at specific revision", async ({ page }) => { await page.goto( `${sourceBrowsingUrl}/commits/0801aceeab500033f8d608778218657bd626ef73`, diff --git a/tests/fixtures/repos/source-browsing.tar.bz2 b/tests/fixtures/repos/source-browsing.tar.bz2 index 2ba24452c..8d3f565bb 100644 Binary files a/tests/fixtures/repos/source-browsing.tar.bz2 and b/tests/fixtures/repos/source-browsing.tar.bz2 differ diff --git a/tests/support/fixtures.ts b/tests/support/fixtures.ts index 6c112175a..9f55b4186 100644 --- a/tests/support/fixtures.ts +++ b/tests/support/fixtures.ts @@ -251,6 +251,9 @@ export async function createSourceBrowsingFixture( await alice.git(["clone", sourceBrowsingDir], { cwd: alice.checkoutPath }); await alice.git(["checkout", "feature/branch"], { cwd: aliceProjectPath }); + await alice.git(["checkout", "feature/move-copy-files"], { + cwd: aliceProjectPath, + }); await alice.git(["checkout", "orphaned-branch"], { cwd: aliceProjectPath }); await alice.git(["checkout", "main"], { cwd: aliceProjectPath }); await alice.rad(