workdir: report current selector and ref
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import type { WorkingDirectorySummary } from "../sidebar/types.ts";
|
||||
import { formatCurrentWorkdirRevision } from "./workdir-revision.ts";
|
||||
|
||||
declare const Deno: {
|
||||
test(name: string, fn: () => Promise<void> | void): void;
|
||||
};
|
||||
|
||||
function assertEquals<T>(actual: T, expected: T): void {
|
||||
if (actual !== expected) {
|
||||
throw new Error(`Expected ${String(expected)}, got ${String(actual)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function workdir(
|
||||
current_selector: string | null,
|
||||
current_ref: string | null,
|
||||
): WorkingDirectorySummary {
|
||||
return {
|
||||
working_directory_id: "workdir-1",
|
||||
repository_id: "repository-1",
|
||||
current_selector,
|
||||
current_ref,
|
||||
materializer_kind: "local_git_worktree",
|
||||
status: "active",
|
||||
cleanup_target: {
|
||||
kind: "local_git_worktree",
|
||||
working_directory_id: "workdir-1",
|
||||
repository_id: "repository-1",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Deno.test("Git detached Workdir shows only its current ref", () => {
|
||||
assertEquals(
|
||||
formatCurrentWorkdirRevision(
|
||||
workdir(null, "0123456789abcdef0123456789abcdef01234567"),
|
||||
"git",
|
||||
),
|
||||
"0123456789ab",
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("Git Workdir with a selector shows selector at current ref", () => {
|
||||
assertEquals(
|
||||
formatCurrentWorkdirRevision(
|
||||
workdir("feature/current", "fedcba9876543210fedcba9876543210fedcba98"),
|
||||
"git",
|
||||
),
|
||||
"feature/current@fedcba987654",
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("non-Git Workdir does not receive Git hash formatting", () => {
|
||||
assertEquals(
|
||||
formatCurrentWorkdirRevision(
|
||||
workdir("snapshot", "revision-value"),
|
||||
"archive",
|
||||
),
|
||||
"snapshot · revision-value",
|
||||
);
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import type { WorkingDirectorySummary } from "../sidebar/types.ts";
|
||||
|
||||
export function formatCurrentWorkdirRevision(
|
||||
workdir: WorkingDirectorySummary,
|
||||
repositoryProvider: string | null | undefined,
|
||||
): string {
|
||||
const selector = workdir.current_selector?.trim() || null;
|
||||
const reference = workdir.current_ref?.trim() || null;
|
||||
|
||||
if (repositoryProvider?.toLowerCase() === "git") {
|
||||
const hash = reference ? shortGitHash(reference) : null;
|
||||
if (selector && hash) return `${selector}@${hash}`;
|
||||
return selector ?? hash ?? "—";
|
||||
}
|
||||
|
||||
if (selector && reference) return `${selector} · ${reference}`;
|
||||
return selector ?? reference ?? "—";
|
||||
}
|
||||
|
||||
function shortGitHash(reference: string): string {
|
||||
return reference.length > 12 ? reference.slice(0, 12) : reference;
|
||||
}
|
||||
@@ -110,7 +110,7 @@
|
||||
</span>
|
||||
<span class="item-meta">
|
||||
worker {worker.worker_id} · {worker.profile ? `${worker.profile} · ` : ''}{worker.state} · 🖥 {worker.host_id}
|
||||
{worker.working_directory ? ` · wd:${worker.working_directory.repository_id}@${worker.working_directory.resolved_commit.slice(0, 8)}` : ''}
|
||||
{worker.working_directory?.current_ref ? ` · wd:${worker.working_directory.repository_id}@${worker.working_directory.current_ref.slice(0, 8)}` : ''}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -128,10 +128,11 @@ export type WorkingDirectoryOccupancy = {
|
||||
export type WorkingDirectorySummary = {
|
||||
working_directory_id: string;
|
||||
repository_id: string;
|
||||
requested_selector?: string | null;
|
||||
creation_selector?: string | null;
|
||||
creation_ref?: string | null;
|
||||
current_selector?: string | null;
|
||||
current_ref?: string | null;
|
||||
materializer_kind: string;
|
||||
resolved_commit: string;
|
||||
resolved_tree?: string | null;
|
||||
status: string;
|
||||
cleanliness?: string | null;
|
||||
primary_worker_id?: number | null;
|
||||
|
||||
@@ -50,9 +50,11 @@ const options: WorkerLaunchOptionsResponse = {
|
||||
{
|
||||
working_directory_id: "wd-1-repo",
|
||||
repository_id: "repo",
|
||||
requested_selector: "HEAD",
|
||||
creation_selector: "HEAD",
|
||||
creation_ref: "0123456789abcdef",
|
||||
current_selector: null,
|
||||
current_ref: "0123456789abcdef",
|
||||
materializer_kind: "local_git_worktree",
|
||||
resolved_commit: "0123456789abcdef",
|
||||
status: "active",
|
||||
cleanliness: "clean",
|
||||
primary_worker_id: null,
|
||||
@@ -159,7 +161,7 @@ Deno.test("defaultWorkerLaunchForm preserves a Ticket repository target", () =>
|
||||
...options.working_directories[0],
|
||||
working_directory_id: "ticket-workdir",
|
||||
repository_id: "ticket-repo",
|
||||
requested_selector: "work/ticket",
|
||||
creation_selector: "work/ticket",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -55,7 +55,8 @@ export function defaultWorkerLaunchForm(
|
||||
Boolean(current.working_directory_repository_id) &&
|
||||
directory.repository_id === current.working_directory_repository_id &&
|
||||
(!current.working_directory_selector ||
|
||||
directory.requested_selector === current.working_directory_selector)
|
||||
(directory.current_selector ?? directory.creation_selector) ===
|
||||
current.working_directory_selector)
|
||||
) ?? availableWorkingDirectories.find((directory) =>
|
||||
Boolean(current.working_directory_repository_id) &&
|
||||
directory.repository_id === current.working_directory_repository_id
|
||||
|
||||
+8
-8
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { pushWorkspaceAlert } from '$lib/workspace/alerts/store';
|
||||
import { workspaceApiPath } from '$lib/workspace/api/http';
|
||||
import { formatCurrentWorkdirRevision } from '$lib/workspace/settings/workdir-revision';
|
||||
import type {
|
||||
CleanupWorkdirCandidate,
|
||||
RuntimeCleanupExecutionResponse,
|
||||
@@ -23,12 +24,13 @@
|
||||
workdirs = data.workdirs?.items ?? [];
|
||||
});
|
||||
|
||||
function commitLabel(workdir: WorkingDirectorySummary): string {
|
||||
return workdir.resolved_commit ? workdir.resolved_commit.slice(0, 12) : '—';
|
||||
function repositoryProvider(workdir: WorkingDirectorySummary): string | null {
|
||||
return data.repositories?.items.find((repository) => repository.id === workdir.repository_id)
|
||||
?.provider ?? null;
|
||||
}
|
||||
|
||||
function selectorLabel(workdir: WorkingDirectorySummary): string {
|
||||
return workdir.requested_selector ?? 'HEAD';
|
||||
function currentRevision(workdir: WorkingDirectorySummary): string {
|
||||
return formatCurrentWorkdirRevision(workdir, repositoryProvider(workdir));
|
||||
}
|
||||
|
||||
function cleanupCandidate(workdir: WorkingDirectorySummary): CleanupWorkdirCandidate | undefined {
|
||||
@@ -125,8 +127,7 @@
|
||||
<tr>
|
||||
<th>Workdir</th>
|
||||
<th>Repository</th>
|
||||
<th>Selector</th>
|
||||
<th>Commit</th>
|
||||
<th>Revision</th>
|
||||
<th>Status</th>
|
||||
<th>Cleanliness</th>
|
||||
<th>Occupied by</th>
|
||||
@@ -139,8 +140,7 @@
|
||||
<tr>
|
||||
<td><code>{workdir.working_directory_id}</code></td>
|
||||
<td>{workdir.repository_id}</td>
|
||||
<td>{selectorLabel(workdir)}</td>
|
||||
<td><code>{commitLabel(workdir)}</code></td>
|
||||
<td><code>{currentRevision(workdir)}</code></td>
|
||||
<td>{workdir.status}</td>
|
||||
<td>{workdir.cleanliness ?? 'unknown'}</td>
|
||||
<td>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { pushWorkspaceAlert } from '$lib/workspace/alerts/store';
|
||||
import { workspaceApiPath } from '$lib/workspace/api/http';
|
||||
import { workerConsoleHref } from '$lib/workspace/console/model';
|
||||
import { formatCurrentWorkdirRevision } from '$lib/workspace/settings/workdir-revision';
|
||||
import { canOpenWorkerConsole } from '$lib/workspace/sidebar/workers';
|
||||
import type { CleanupWorkerCandidate, RuntimeCleanupExecutionResponse, RuntimeCleanupPlanResponse, Worker } from '$lib/workspace/sidebar/types';
|
||||
import type { PageProps } from './$types';
|
||||
@@ -145,9 +146,9 @@
|
||||
function workerDirectory(worker: Worker): string {
|
||||
const directory = worker.working_directory;
|
||||
if (!directory) return '—';
|
||||
const selector = directory.requested_selector ?? 'HEAD';
|
||||
const commit = directory.resolved_commit ? directory.resolved_commit.slice(0, 12) : null;
|
||||
return commit ? `${directory.repository_id} · ${selector} · ${commit}` : `${directory.repository_id} · ${selector}`;
|
||||
const provider = data.repositories?.items.find((repository) => repository.id === directory.repository_id)
|
||||
?.provider;
|
||||
return `${directory.repository_id} · ${formatCurrentWorkdirRevision(directory, provider)}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
import { goto } from '$app/navigation';
|
||||
import { untrack } from 'svelte';
|
||||
import { workspaceApiPath } from '$lib/workspace/api/http';
|
||||
import { formatCurrentWorkdirRevision } from '$lib/workspace/settings/workdir-revision';
|
||||
import { buildBrowserCreateWorkerRequest, defaultWorkerLaunchForm } from '$lib/workspace/sidebar/worker-launch';
|
||||
import type {
|
||||
BrowserCreateWorkerResponse,
|
||||
BrowserWorkingDirectoryCreateResponse,
|
||||
Diagnostic,
|
||||
WorkerLaunchOptionsResponse,
|
||||
WorkingDirectorySummary,
|
||||
} from '$lib/workspace/sidebar/types';
|
||||
import type { PageProps } from './$types';
|
||||
|
||||
@@ -22,6 +24,12 @@
|
||||
diagnostics?: Diagnostic[];
|
||||
};
|
||||
|
||||
function workdirOptionLabel(directory: WorkingDirectorySummary): string {
|
||||
const provider = data.repositories?.items.find((repository) => repository.id === directory.repository_id)
|
||||
?.provider;
|
||||
return `${directory.repository_id} · ${formatCurrentWorkdirRevision(directory, provider)}`;
|
||||
}
|
||||
|
||||
let { data }: PageProps = $props();
|
||||
let workspaceId = $derived(data.workspaceId);
|
||||
const ticketContext = untrack(() => data.ticketContext);
|
||||
@@ -296,7 +304,7 @@
|
||||
<option value="" disabled>Select workdir</option>
|
||||
{#each availableWorkingDirectories as directory}
|
||||
<option value={directory.working_directory_id}>
|
||||
{directory.repository_id} · {directory.requested_selector ?? 'HEAD'}
|
||||
{workdirOptionLabel(directory)}
|
||||
</option>
|
||||
{/each}
|
||||
<option value={NEW_WORKING_DIRECTORY_VALUE}>New workdir…</option>
|
||||
|
||||
Reference in New Issue
Block a user