Skip to content

Commit

Permalink
Replace uses of content_hash! with an equivalent proc macro and #[der…
Browse files Browse the repository at this point in the history
…ive(ContentHash)]

This is a pure refactor with no behavior changes.
  • Loading branch information
emesterhazy committed Feb 14, 2024
1 parent 3c44d84 commit 04a83da
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 177 deletions.
98 changes: 41 additions & 57 deletions lib/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,14 @@ id_type!(pub FileId);
id_type!(pub SymlinkId);
id_type!(pub ConflictId);

content_hash! {
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct MillisSinceEpoch(pub i64);
}

content_hash! {
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct Timestamp {
pub timestamp: MillisSinceEpoch,
// time zone offset in minutes
pub tz_offset: i32,
}
#[derive(ContentHash, Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct MillisSinceEpoch(pub i64);

#[derive(ContentHash, Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct Timestamp {
pub timestamp: MillisSinceEpoch,
// time zone offset in minutes
pub tz_offset: i32,
}

impl Timestamp {
Expand All @@ -68,21 +64,17 @@ impl Timestamp {
}
}

content_hash! {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Signature {
pub name: String,
pub email: String,
pub timestamp: Timestamp,
}
#[derive(ContentHash, Debug, PartialEq, Eq, Clone)]
pub struct Signature {
pub name: String,
pub email: String,
pub timestamp: Timestamp,
}

content_hash! {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct SecureSig {
pub data: Vec<u8>,
pub sig: Vec<u8>,
}
#[derive(ContentHash, Debug, PartialEq, Eq, Clone)]
pub struct SecureSig {
pub data: Vec<u8>,
pub sig: Vec<u8>,
}

pub type SigningFn<'a> = dyn FnMut(&[u8]) -> SignResult<Vec<u8>> + 'a;
Expand Down Expand Up @@ -140,37 +132,31 @@ impl MergedTreeId {
}
}

content_hash! {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Commit {
pub parents: Vec<CommitId>,
pub predecessors: Vec<CommitId>,
pub root_tree: MergedTreeId,
pub change_id: ChangeId,
pub description: String,
pub author: Signature,
pub committer: Signature,
pub secure_sig: Option<SecureSig>,
}
#[derive(ContentHash, Debug, PartialEq, Eq, Clone)]
pub struct Commit {
pub parents: Vec<CommitId>,
pub predecessors: Vec<CommitId>,
pub root_tree: MergedTreeId,
pub change_id: ChangeId,
pub description: String,
pub author: Signature,
pub committer: Signature,
pub secure_sig: Option<SecureSig>,
}

content_hash! {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ConflictTerm {
pub value: TreeValue,
}
#[derive(ContentHash, Debug, PartialEq, Eq, Clone)]
pub struct ConflictTerm {
pub value: TreeValue,
}

content_hash! {
#[derive(Default, Debug, PartialEq, Eq, Clone)]
pub struct Conflict {
// A conflict is represented by a list of positive and negative states that need to be applied.
// In a simple 3-way merge of B and C with merge base A, the conflict will be { add: [B, C],
// remove: [A] }. Also note that a conflict of the form { add: [A], remove: [] } is the
// same as non-conflict A.
pub removes: Vec<ConflictTerm>,
pub adds: Vec<ConflictTerm>,
}
#[derive(ContentHash, Default, Debug, PartialEq, Eq, Clone)]
pub struct Conflict {
// A conflict is represented by a list of positive and negative states that need to be applied.
// In a simple 3-way merge of B and C with merge base A, the conflict will be { add: [B, C],
// remove: [A] }. Also note that a conflict of the form { add: [A], remove: [] } is the
// same as non-conflict A.
pub removes: Vec<ConflictTerm>,
pub adds: Vec<ConflictTerm>,
}

/// Error that may occur during backend initialization.
Expand Down Expand Up @@ -309,11 +295,9 @@ impl<'a> Iterator for TreeEntriesNonRecursiveIterator<'a> {
}
}

content_hash! {
#[derive(Default, PartialEq, Eq, Debug, Clone)]
pub struct Tree {
entries: BTreeMap<RepoPathComponentBuf, TreeValue>,
}
#[derive(ContentHash, Default, PartialEq, Eq, Debug, Clone)]
pub struct Tree {
entries: BTreeMap<RepoPathComponentBuf, TreeValue>,
}

impl Tree {
Expand Down
38 changes: 7 additions & 31 deletions lib/src/content_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,33 +129,6 @@ where
}
}

macro_rules! content_hash {
($(#[$meta:meta])* $vis:vis struct $name:ident {
$($(#[$field_meta:meta])* $field_vis:vis $field:ident : $ty:ty),* $(,)?
}) => {
$(#[$meta])*
$vis struct $name {
$($(#[$field_meta])* $field_vis $field : $ty),*
}

impl crate::content_hash::ContentHash for $name {
fn hash(&self, state: &mut impl digest::Update) {
$(<$ty as crate::content_hash::ContentHash>::hash(&self.$field, state);)*
}
}
};
($(#[$meta:meta])* $vis:vis struct $name:ident($field_vis:vis $ty:ty);) => {
$(#[$meta])*
$vis struct $name($field_vis $ty);

impl crate::content_hash::ContentHash for $name {
fn hash(&self, state: &mut impl digest::Update) {
<$ty as crate::content_hash::ContentHash>::hash(&self.0, state);
}
}
};
}

#[cfg(test)]
mod tests {
use std::collections::{BTreeMap, HashMap};
Expand Down Expand Up @@ -199,8 +172,9 @@ mod tests {

#[test]
fn test_struct_sanity() {
content_hash! {
struct Foo { x: i32 }
#[derive(ContentHash)]
struct Foo {
x: i32,
}
assert_ne!(hash(&Foo { x: 42 }), hash(&Foo { x: 12 }));
}
Expand All @@ -221,8 +195,10 @@ mod tests {

#[test]
fn test_consistent_hashing() {
content_hash! {
struct Foo { x: Vec<Option<i32>>, y: i64 }
#[derive(ContentHash)]
struct Foo {
x: Vec<Option<i32>>,
y: i64,
}
insta::assert_snapshot!(
hex::encode(hash(&Foo {
Expand Down
6 changes: 2 additions & 4 deletions lib/src/object_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ pub trait ObjectId {

macro_rules! id_type {
($vis:vis $name:ident) => {
content_hash! {
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
$vis struct $name(Vec<u8>);
}
#[derive(ContentHash, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
$vis struct $name(Vec<u8>);
$crate::object_id::impl_id_type!($name);
};
}
Expand Down
140 changes: 63 additions & 77 deletions lib/src/op_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ use crate::content_hash::ContentHash;
use crate::merge::Merge;
use crate::object_id::{id_type, HexPrefix, ObjectId, PrefixResolution};

content_hash! {
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct WorkspaceId(String);
}
#[derive(ContentHash, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct WorkspaceId(String);

impl Debug for WorkspaceId {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
Expand All @@ -59,11 +57,9 @@ impl WorkspaceId {
id_type!(pub ViewId);
id_type!(pub OperationId);

content_hash! {
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub struct RefTarget {
merge: Merge<Option<CommitId>>,
}
#[derive(ContentHash, PartialEq, Eq, Hash, Clone, Debug)]
pub struct RefTarget {
merge: Merge<Option<CommitId>>,
}

impl Default for RefTarget {
Expand Down Expand Up @@ -147,13 +143,11 @@ impl RefTarget {
}
}

content_hash! {
/// Remote branch or tag.
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct RemoteRef {
pub target: RefTarget,
pub state: RemoteRefState,
}
/// Remote branch or tag.
#[derive(ContentHash, Clone, Debug, Eq, Hash, PartialEq)]
pub struct RemoteRef {
pub target: RefTarget,
pub state: RemoteRefState,
}

impl RemoteRef {
Expand Down Expand Up @@ -266,39 +260,35 @@ pub struct BranchTarget<'a> {
pub remote_refs: Vec<(&'a str, &'a RemoteRef)>,
}

content_hash! {
/// Represents the way the repo looks at a given time, just like how a Tree
/// object represents how the file system looks at a given time.
#[derive(PartialEq, Eq, Clone, Debug, Default)]
pub struct View {
/// All head commits
pub head_ids: HashSet<CommitId>,
pub local_branches: BTreeMap<String, RefTarget>,
pub tags: BTreeMap<String, RefTarget>,
pub remote_views: BTreeMap<String, RemoteView>,
pub git_refs: BTreeMap<String, RefTarget>,
/// The commit the Git HEAD points to.
// TODO: Support multiple Git worktrees?
// TODO: Do we want to store the current branch name too?
pub git_head: RefTarget,
// The commit that *should be* checked out in the workspace. Note that the working copy
// (.jj/working_copy/) has the source of truth about which commit *is* checked out (to be
// precise: the commit to which we most recently completed an update to).
pub wc_commit_ids: HashMap<WorkspaceId, CommitId>,
}
/// Represents the way the repo looks at a given time, just like how a Tree
/// object represents how the file system looks at a given time.
#[derive(ContentHash, PartialEq, Eq, Clone, Debug, Default)]
pub struct View {
/// All head commits
pub head_ids: HashSet<CommitId>,
pub local_branches: BTreeMap<String, RefTarget>,
pub tags: BTreeMap<String, RefTarget>,
pub remote_views: BTreeMap<String, RemoteView>,
pub git_refs: BTreeMap<String, RefTarget>,
/// The commit the Git HEAD points to.
// TODO: Support multiple Git worktrees?
// TODO: Do we want to store the current branch name too?
pub git_head: RefTarget,
// The commit that *should be* checked out in the workspace. Note that the working copy
// (.jj/working_copy/) has the source of truth about which commit *is* checked out (to be
// precise: the commit to which we most recently completed an update to).
pub wc_commit_ids: HashMap<WorkspaceId, CommitId>,
}

content_hash! {
/// Represents the state of the remote repo.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RemoteView {
// TODO: Do we need to support tombstones for remote branches? For example, if the branch
// has been deleted locally and you pull from a remote, maybe it should make a difference
// whether the branch is known to have existed on the remote. We may not want to resurrect
// the branch if the branch's state on the remote was just not known.
pub branches: BTreeMap<String, RemoteRef>,
// TODO: pub tags: BTreeMap<String, RemoteRef>,
}
/// Represents the state of the remote repo.
#[derive(ContentHash, Clone, Debug, Default, Eq, PartialEq)]
pub struct RemoteView {
// TODO: Do we need to support tombstones for remote branches? For example, if the branch
// has been deleted locally and you pull from a remote, maybe it should make a difference
// whether the branch is known to have existed on the remote. We may not want to resurrect
// the branch if the branch's state on the remote was just not known.
pub branches: BTreeMap<String, RemoteRef>,
// TODO: pub tags: BTreeMap<String, RemoteRef>,
}

/// Iterates pair of local and remote branches by branch name.
Expand Down Expand Up @@ -353,25 +343,23 @@ pub(crate) fn flatten_remote_branches(
.kmerge_by(|(full_name1, _), (full_name2, _)| full_name1 < full_name2)
}

content_hash! {
/// Represents an operation (transaction) on the repo view, just like how a
/// Commit object represents an operation on the tree.
///
/// Operations and views are not meant to be exchanged between repos or users;
/// they represent local state and history.
///
/// The operation history will almost always be linear. It will only have
/// forks when parallel operations occurred. The parent is determined when
/// the transaction starts. When the transaction commits, a lock will be
/// taken and it will be checked that the current head of the operation
/// graph is unchanged. If the current head has changed, there has been
/// concurrent operation.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Operation {
pub view_id: ViewId,
pub parents: Vec<OperationId>,
pub metadata: OperationMetadata,
}
/// Represents an operation (transaction) on the repo view, just like how a
/// Commit object represents an operation on the tree.
///
/// Operations and views are not meant to be exchanged between repos or users;
/// they represent local state and history.
///
/// The operation history will almost always be linear. It will only have
/// forks when parallel operations occurred. The parent is determined when
/// the transaction starts. When the transaction commits, a lock will be
/// taken and it will be checked that the current head of the operation
/// graph is unchanged. If the current head has changed, there has been
/// concurrent operation.
#[derive(ContentHash, PartialEq, Eq, Clone, Debug)]
pub struct Operation {
pub view_id: ViewId,
pub parents: Vec<OperationId>,
pub metadata: OperationMetadata,
}

impl Operation {
Expand All @@ -396,17 +384,15 @@ impl Operation {
}
}

content_hash! {
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct OperationMetadata {
pub start_time: Timestamp,
pub end_time: Timestamp,
// Whatever is useful to the user, such as exact command line call
pub description: String,
pub hostname: String,
pub username: String,
pub tags: HashMap<String, String>,
}
#[derive(ContentHash, PartialEq, Eq, Clone, Debug)]
pub struct OperationMetadata {
pub start_time: Timestamp,
pub end_time: Timestamp,
// Whatever is useful to the user, such as exact command line call
pub description: String,
pub hostname: String,
pub username: String,
pub tags: HashMap<String, String>,
}

#[derive(Debug, Error)]
Expand Down
Loading

0 comments on commit 04a83da

Please sign in to comment.