Skip to content

Commit

Permalink
op_store: minimal change to load/store tracking state of remote branches
Browse files Browse the repository at this point in the history
We could instead migrate the storage types to (local_branches, remote_views),
but that would be more involved and break forward compatibility with little
benefit. Maybe we can do that later when we introduce remote tags.
  • Loading branch information
yuja committed Oct 15, 2023
1 parent 0b391f9 commit dde4691
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 12 deletions.
7 changes: 7 additions & 0 deletions lib/src/protos/op_store.proto
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,16 @@ message RefTarget {
}
}

enum RemoteRefState {
New = 0;
Tracking = 1;
}

message RemoteBranch {
string remote_name = 1;
RefTarget target = 2;
// Introduced in jj 0.11.
optional RemoteRefState state = 3;
}

message Branch {
Expand Down
29 changes: 29 additions & 0 deletions lib/src/protos/op_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ pub struct RemoteBranch {
pub remote_name: ::prost::alloc::string::String,
#[prost(message, optional, tag = "2")]
pub target: ::core::option::Option<RefTarget>,
/// Introduced in jj 0.11.
#[prost(enumeration = "RemoteRefState", optional, tag = "3")]
pub state: ::core::option::Option<i32>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
Expand Down Expand Up @@ -162,3 +165,29 @@ pub struct OperationMetadata {
::prost::alloc::string::String,
>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum RemoteRefState {
New = 0,
Tracking = 1,
}
impl RemoteRefState {
/// String value of the enum field names used in the ProtoBuf definition.
///
/// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str {
match self {
RemoteRefState::New => "New",
RemoteRefState::Tracking => "Tracking",
}
}
/// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value {
"New" => Some(Self::New),
"Tracking" => Some(Self::Tracking),
_ => None,
}
}
}
54 changes: 42 additions & 12 deletions lib/src/simple_op_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ fn branch_views_to_proto_legacy(
|&(remote_name, remote_ref)| crate::protos::op_store::RemoteBranch {
remote_name: remote_name.to_owned(),
target: ref_target_to_proto(&remote_ref.target),
state: remote_ref_state_to_proto(remote_ref.state),
},
)
.collect();
Expand All @@ -372,17 +373,27 @@ fn branch_views_from_proto_legacy(
for branch_proto in branches_legacy {
let local_target = ref_target_from_proto(branch_proto.local_target);
for remote_branch in branch_proto.remote_branches {
// If local branch doesn't exist, we assume that the remote branch hasn't been
// merged because git.auto-local-branch was off. That's probably more common
// than deleted but yet-to-be-pushed local branch. Alternatively, we could read
// git.auto-local-branch setting here, but that wouldn't always work since the
// setting could be toggled after the branch got merged.
let is_git_tracking = remote_branch.remote_name == git::REMOTE_NAME_FOR_LOCAL_GIT_REPO;
let state = if is_git_tracking || local_target.is_present() {
RemoteRefState::Tracking
} else {
RemoteRefState::New
};
let state = remote_ref_state_from_proto(remote_branch.state).unwrap_or_else(|| {
// If local branch doesn't exist, we assume that the remote branch hasn't been
// merged because git.auto-local-branch was off. That's probably more common
// than deleted but yet-to-be-pushed local branch. Alternatively, we could read
// git.auto-local-branch setting here, but that wouldn't always work since the
// setting could be toggled after the branch got merged.
let is_git_tracking =
remote_branch.remote_name == git::REMOTE_NAME_FOR_LOCAL_GIT_REPO;
let default_state = if is_git_tracking || local_target.is_present() {
RemoteRefState::Tracking
} else {
RemoteRefState::New
};
tracing::trace!(
?branch_proto.name,
?remote_branch.remote_name,
?default_state,
"generated tracking state",
);
default_state
});
let remote_view = remote_views.entry(remote_branch.remote_name).or_default();
let remote_ref = RemoteRef {
target: ref_target_from_proto(remote_branch.target),
Expand Down Expand Up @@ -501,6 +512,23 @@ fn ref_target_from_proto(maybe_proto: Option<crate::protos::op_store::RefTarget>
}
}

fn remote_ref_state_to_proto(state: RemoteRefState) -> Option<i32> {
let proto_state = match state {
RemoteRefState::New => crate::protos::op_store::RemoteRefState::New,
RemoteRefState::Tracking => crate::protos::op_store::RemoteRefState::Tracking,
};
Some(proto_state as i32)
}

fn remote_ref_state_from_proto(proto_value: Option<i32>) -> Option<RemoteRefState> {
let proto_state = proto_value.and_then(crate::protos::op_store::RemoteRefState::from_i32)?;
let state = match proto_state {
crate::protos::op_store::RemoteRefState::New => RemoteRefState::New,
crate::protos::op_store::RemoteRefState::Tracking => RemoteRefState::Tracking,
};
Some(state)
}

#[cfg(test)]
mod tests {
use insta::assert_snapshot;
Expand Down Expand Up @@ -663,8 +691,9 @@ mod tests {
},
"remote2".to_owned() => RemoteView {
branches: btreemap! {
// "branch2" is non-tracking. "branch4" is tracking, but locally deleted.
"branch2".to_owned() => new_remote_ref(&remote2_branch2_target),
"branch4".to_owned() => new_remote_ref(&remote2_branch4_target),
"branch4".to_owned() => tracking_remote_ref(&remote2_branch4_target),
},
},
};
Expand Down Expand Up @@ -706,6 +735,7 @@ mod tests {
|remote_name: &str, ref_target| crate::protos::op_store::RemoteBranch {
remote_name: remote_name.to_owned(),
target: ref_target_to_proto(ref_target),
state: None, // to be generated based on local branch existence
};
let git_ref_to_proto = |name: &str, ref_target| crate::protos::op_store::GitRef {
name: name.to_owned(),
Expand Down

0 comments on commit dde4691

Please sign in to comment.