Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Add missing moved and copied file operations to Changeset
Sebastian Martinez committed 3 years ago
commit f971d777f2d0385f35b0cdb8ca423b76584a5501
parent becfd5d8c57386b7fddd5aa04627e81b91918bb5
7 files changed +104 -8
modified httpd-client/lib/project/commit.ts
@@ -106,7 +106,7 @@ const diffAddedDeletedModifiedChangesetSchema = object({
  }),
}) satisfies ZodSchema<DiffAddedDeletedModifiedChangeset>;

-
interface DiffCopiedMovedChangeset {
+
export interface DiffCopiedMovedChangeset {
  newPath: string;
  oldPath: string;
}
modified 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(", ");
  };
</script>
@@ -54,12 +67,18 @@
</div>
<div class="diff-listing">
  {#each diff.added as file}
-
    <FileDiff on:browse {file} {revision} mode="added" />
+
    <FileDiff {file} {revision} headerBadgeCaption="added" />
  {/each}
  {#each diff.deleted as file}
-
    <FileDiff on:browse {file} {revision} mode="deleted" />
+
    <FileDiff {file} {revision} headerBadgeCaption="deleted" />
  {/each}
  {#each diff.modified as file}
-
    <FileDiff on:browse {file} {revision} />
+
    <FileDiff {file} {revision} />
+
  {/each}
+
  {#each diff.moved as file}
+
    <FileLocationChange {file} {revision} mode="moved" />
+
  {/each}
+
  {#each diff.copied as file}
+
    <FileLocationChange {file} {revision} mode="copied" />
  {/each}
</div>
modified 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 @@
    </div>
    <div class="actions">
      <p class="txt-regular">{file.path}</p>
-
      {#if mode === "added"}
+
      {#if headerBadgeCaption === "added"}
        <Badge variant="positive">added</Badge>
-
      {:else if mode === "deleted"}
+
      {:else if headerBadgeCaption === "deleted"}
        <Badge variant="negative">deleted</Badge>
      {/if}
    </div>
added src/views/projects/SourceBrowser/FileLocationChange.svelte
@@ -0,0 +1,63 @@
+
<script lang="ts">
+
  import type { DiffCopiedMovedChangeset } from "@httpd-client/lib/project/commit";
+

+
  import Badge from "@app/components/Badge.svelte";
+
  import Icon from "@app/components/Icon.svelte";
+
  import ProjectLink from "@app/components/ProjectLink.svelte";
+

+
  export let file: DiffCopiedMovedChangeset;
+
  export let revision: string;
+
  export let mode: "moved" | "copied";
+
</script>
+

+
<style>
+
  .wrapper {
+
    border: 1px solid var(--color-foreground-4);
+
    border-radius: var(--border-radius-small);
+
    margin-bottom: 2rem;
+
    line-height: 1.5rem;
+
  }
+
  .header {
+
    align-items: center;
+
    background: none;
+
    border-radius: 0;
+
    display: flex;
+
    flex-direction: row;
+
    height: 3rem;
+
    padding: 1rem;
+
  }
+
  .actions {
+
    display: flex;
+
    flex-direction: row;
+
    align-items: center;
+
    gap: 1rem;
+
  }
+
  .browse {
+
    margin-left: auto;
+
    cursor: pointer;
+
  }
+
</style>
+

+
<div id={file.newPath} class="wrapper">
+
  <header class="header">
+
    <div class="actions">
+
      <p class="txt-regular">{file.oldPath} → {file.newPath}</p>
+
      {#if mode === "moved"}
+
        <Badge variant="foreground">moved</Badge>
+
      {:else if mode === "copied"}
+
        <Badge variant="foreground">copied</Badge>
+
      {/if}
+
    </div>
+
    <div class="browse" title="View file">
+
      <ProjectLink
+
        projectParams={{
+
          view: { resource: "tree" },
+
          path: file.newPath,
+
          revision,
+
          search: undefined,
+
        }}>
+
        <Icon name="browse" />
+
      </ProjectLink>
+
    </div>
+
  </header>
+
</div>
modified 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`,
modified tests/fixtures/repos/source-browsing.tar.bz2
modified 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(