Skip to content

Commit 0b2bf7b

Browse files
Merge pull request #124 from triblespace/codex/improve-user-friendly-selectors-for-git-set
Return PATCH from commit selectors
2 parents 5ed768e + 40991cd commit 0b2bf7b

3 files changed

Lines changed: 47 additions & 29 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
147147
starting point.
148148
- Scalar commit selectors once again return only the specified commit.
149149
- Introduced an `ancestors` selector to retrieve a commit and its history.
150+
- Commit selectors now return a `CommitSet` patch of commit handles instead of a `Vec`.
151+
- Renamed the `CommitPatch` type alias to `CommitSet`.
150152

151153
## [0.5.2] - 2025-06-30
152154
### Added

book/src/commit-selectors.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ Instead of passing ranges, callers would construct *commit sets* derived from
1010
reachability. Primitive functions like `ancestors(<commit>)` and
1111
`descendants(<commit>)` would produce sets. Higher level combinators such as
1212
`union`, `intersection` and `difference` would then let users express queries
13-
like "A minus B" or "ancestors of A intersect B". The result of a selector
14-
would still be an ordered list of commits for `checkout` to load.
13+
like "A minus B" or "ancestors of A intersect B". Each selector would return
14+
a `CommitSet` patch of commit handles for `checkout` to load.
1515

1616
This approach aligns with Git's mental model and keeps selection logic separate
1717
from workspace mutation. It also opens the door for additional operations on

src/repo.rs

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,9 @@ use crate::{
124124
find,
125125
id::Id,
126126
metadata::metadata,
127+
patch::{Entry, IdentityOrder, SingleSegmentation, PATCH},
127128
trible::TribleSet,
129+
value::VALUE_LEN,
128130
value::{
129131
schemas::hash::{Handle, HashProtocol},
130132
Value, ValueSchema,
@@ -799,6 +801,7 @@ where
799801
}
800802

801803
type CommitHandle = Value<Handle<Blake3, SimpleArchive>>;
804+
type CommitSet = PATCH<VALUE_LEN, IdentityOrder, SingleSegmentation>;
802805
type BranchMetaHandle = Value<Handle<Blake3, SimpleArchive>>;
803806

804807
/// The Workspace represents the mutable working area or "staging" state.
@@ -841,7 +844,7 @@ pub trait CommitSelector<Blobs: BlobStore<Blake3>> {
841844
self,
842845
ws: &mut Workspace<Blobs>,
843846
) -> Result<
844-
Vec<CommitHandle>,
847+
CommitSet,
845848
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
846849
>;
847850
}
@@ -862,10 +865,12 @@ where
862865
self,
863866
_ws: &mut Workspace<Blobs>,
864867
) -> Result<
865-
Vec<CommitHandle>,
868+
CommitSet,
866869
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
867870
> {
868-
Ok(vec![self])
871+
let mut patch = CommitSet::new();
872+
patch.insert(&Entry::new(&self.raw));
873+
Ok(patch)
869874
}
870875
}
871876

@@ -877,10 +882,14 @@ where
877882
self,
878883
_ws: &mut Workspace<Blobs>,
879884
) -> Result<
880-
Vec<CommitHandle>,
885+
CommitSet,
881886
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
882887
> {
883-
Ok(self)
888+
let mut patch = CommitSet::new();
889+
for handle in self {
890+
patch.insert(&Entry::new(&handle.raw));
891+
}
892+
Ok(patch)
884893
}
885894
}
886895

@@ -892,10 +901,14 @@ where
892901
self,
893902
_ws: &mut Workspace<Blobs>,
894903
) -> Result<
895-
Vec<CommitHandle>,
904+
CommitSet,
896905
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
897906
> {
898-
Ok(self.to_vec())
907+
let mut patch = CommitSet::new();
908+
for handle in self {
909+
patch.insert(&Entry::new(&handle.raw));
910+
}
911+
Ok(patch)
899912
}
900913
}
901914

@@ -907,7 +920,7 @@ where
907920
self,
908921
ws: &mut Workspace<Blobs>,
909922
) -> Result<
910-
Vec<CommitHandle>,
923+
CommitSet,
911924
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
912925
> {
913926
collect_reachable(ws, self.0)
@@ -922,14 +935,13 @@ where
922935
self,
923936
ws: &mut Workspace<Blobs>,
924937
) -> Result<
925-
Vec<CommitHandle>,
938+
CommitSet,
926939
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
927940
> {
928-
let mut commits = collect_range(ws, Some(self.start), Some(self.end), true)?;
929-
if !commits.is_empty() {
930-
commits.remove(0);
931-
}
932-
Ok(commits)
941+
let mut patch = collect_range(ws, Some(self.start), Some(self.end), true)?;
942+
// Exclude the starting commit to mirror git semantics
943+
patch.remove(&self.start.raw);
944+
Ok(patch)
933945
}
934946
}
935947

@@ -941,7 +953,7 @@ where
941953
self,
942954
ws: &mut Workspace<Blobs>,
943955
) -> Result<
944-
Vec<CommitHandle>,
956+
CommitSet,
945957
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
946958
> {
947959
collect_range(ws, Some(self.start), None, true)
@@ -956,7 +968,7 @@ where
956968
self,
957969
ws: &mut Workspace<Blobs>,
958970
) -> Result<
959-
Vec<CommitHandle>,
971+
CommitSet,
960972
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
961973
> {
962974
collect_range(ws, None, Some(self.end), false)
@@ -971,7 +983,7 @@ where
971983
self,
972984
ws: &mut Workspace<Blobs>,
973985
) -> Result<
974-
Vec<CommitHandle>,
986+
CommitSet,
975987
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
976988
> {
977989
collect_range(ws, None, None, true)
@@ -1138,7 +1150,8 @@ impl<Blobs: BlobStore<Blake3>> Workspace<Blobs> {
11381150
where
11391151
R: CommitSelector<Blobs>,
11401152
{
1141-
let commits = spec.select(self)?;
1153+
let patch = spec.select(self)?;
1154+
let commits = patch.iter().map(|raw| Value::new(*raw));
11421155
self.checkout_commits(commits)
11431156
}
11441157
}
@@ -1192,18 +1205,18 @@ fn collect_reachable<Blobs: BlobStore<Blake3>>(
11921205
ws: &mut Workspace<Blobs>,
11931206
from: CommitHandle,
11941207
) -> Result<
1195-
Vec<CommitHandle>,
1208+
CommitSet,
11961209
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
11971210
> {
11981211
let mut visited = HashSet::new();
11991212
let mut stack = vec![from];
1200-
let mut result = Vec::new();
1213+
let mut result = CommitSet::new();
12011214

12021215
while let Some(commit) = stack.pop() {
12031216
if !visited.insert(commit) {
12041217
continue;
12051218
}
1206-
result.push(commit);
1219+
result.insert(&Entry::new(&commit.raw));
12071220

12081221
let meta: TribleSet = ws
12091222
.local_blobs
@@ -1217,7 +1230,6 @@ fn collect_reachable<Blobs: BlobStore<Blake3>>(
12171230
}
12181231
}
12191232

1220-
result.reverse();
12211233
Ok(result)
12221234
}
12231235

@@ -1227,17 +1239,17 @@ fn collect_range<Blobs: BlobStore<Blake3>>(
12271239
end: Option<CommitHandle>,
12281240
inclusive_end: bool,
12291241
) -> Result<
1230-
Vec<CommitHandle>,
1242+
CommitSet,
12311243
WorkspaceCheckoutError<<Blobs::Reader as BlobStoreGet<Blake3>>::GetError<UnarchiveError>>,
12321244
> {
1233-
let mut result = Vec::new();
1245+
let mut tmp = Vec::new();
12341246
let mut current = match end.or(ws.head) {
12351247
Some(c) => c,
12361248
None => return Err(WorkspaceCheckoutError::NoHead),
12371249
};
12381250

12391251
loop {
1240-
result.push(current);
1252+
tmp.push(current);
12411253
if Some(current) == start {
12421254
break;
12431255
}
@@ -1246,9 +1258,13 @@ fn collect_range<Blobs: BlobStore<Blake3>>(
12461258
None => break,
12471259
}
12481260
}
1249-
result.reverse();
1261+
tmp.reverse();
12501262
if !inclusive_end {
1251-
result.pop();
1263+
tmp.pop();
1264+
}
1265+
let mut result = CommitSet::new();
1266+
for h in tmp {
1267+
result.insert(&Entry::new(&h.raw));
12521268
}
12531269
Ok(result)
12541270
}

0 commit comments

Comments
 (0)