From 8f6cd1692954548864bc09a319f8c328705a7d3f Mon Sep 17 00:00:00 2001 From: rayaq Date: Wed, 5 Aug 2026 20:43:53 +0000 Subject: [PATCH] working_copy: Add LockedWorkingCopy::set_workspace_annotations hook Custom working-copy backends (such as those used at Google) often maintain separate metadata stores alongside the repository. These backends need to record the checked-out commit ID (`@`) in synchronization with the working copy's operation ID. Maintaining this explicit mapping allows external tools, including developer environments and build systems, to accurately determine workspace state and verify code provenance. Currently, when commands trigger automatic snapshotting of dirty working-copy files (e.g., during `jj status`), a new working-copy commit is created, but `LockedWorkingCopy` is not informed of the updated commit ID. To address this, introduce a hook on `LockedWorkingCopy` that allows backends to be notified when checkout annotations or metadata are updated: - Add `WorkspaceAnnotations` to encapsulate working-copy checkout metadata (currently holding the associated `CommitId`). - Add `LockedWorkingCopy::set_workspace_annotations` with a default no-op implementation for backends that do not track this state (such as `LocalWorkingCopy`). - Invoke `set_workspace_annotations` in `cli_util::snapshot_working_copy()` after updating the snapshot working-copy commit. --- cli/src/cli_util.rs | 9 +++++++++ lib/src/working_copy.rs | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/cli/src/cli_util.rs b/cli/src/cli_util.rs index 26f6c6292e9..11ca0f84a83 100644 --- a/cli/src/cli_util.rs +++ b/cli/src/cli_util.rs @@ -141,6 +141,7 @@ use jj_lib::working_copy::SnapshotStats; use jj_lib::working_copy::UntrackedReason; use jj_lib::working_copy::WorkingCopy; use jj_lib::working_copy::WorkingCopyFactory; +use jj_lib::working_copy::WorkspaceAnnotations; use jj_lib::working_copy::WorkingCopyFreshness; use jj_lib::workspace::DefaultWorkspaceLoaderFactory; use jj_lib::workspace::LockedWorkspace; @@ -2137,6 +2138,14 @@ to the current parents may contain changes from multiple commits. mut_repo .set_wc_commit(workspace_name, new_wc_commit.id().clone()) .map_err(snapshot_command_error)?; + let annotations = WorkspaceAnnotations { + commit_id: Some(new_wc_commit.id()), + }; + locked_ws + .locked_wc() + .set_workspace_annotations(annotations) + .await + .map_err(snapshot_command_error)?; // Rebase descendants let num_rebased = mut_repo diff --git a/lib/src/working_copy.rs b/lib/src/working_copy.rs index 0d4317c19d2..3b3b84e0598 100644 --- a/lib/src/working_copy.rs +++ b/lib/src/working_copy.rs @@ -27,6 +27,7 @@ use thiserror::Error; use tracing::instrument; use crate::backend::BackendError; +use crate::backend::CommitId; use crate::commit::Commit; use crate::gitignore::GitIgnoreError; use crate::gitignore::GitIgnoreFile; @@ -105,6 +106,14 @@ pub trait WorkingCopyFactory { ) -> Result, WorkingCopyStateError>; } +/// Annotations and metadata associated with a working-copy checkout. +#[derive(Debug, Clone, Default)] +pub struct WorkspaceAnnotations<'a> { + /// The working-copy commit ID associated with this checkout, if one was + /// created or updated. + pub commit_id: Option<&'a CommitId>, +} + /// A working copy that's being modified. #[async_trait] pub trait LockedWorkingCopy: Any + Send { @@ -129,6 +138,16 @@ pub trait LockedWorkingCopy: Any + Send { /// Update to another commit without touching the files in the working copy. async fn reset(&mut self, commit: &Commit) -> Result<(), ResetError>; + /// Notify the locked working copy of updated workspace annotations. + async fn set_workspace_annotations( + &mut self, + _annotations: WorkspaceAnnotations<'_>, + ) -> Result<(), ResetError> { + // Default no-op for backends that don't track annotations in their checkout + // state. + Ok(()) + } + /// Update to another commit without touching the files in the working copy, /// without assuming that the previous tree exists. async fn recover(&mut self, commit: &Commit) -> Result<(), ResetError>;