@@ -2,6 +2,7 @@ use crate::init::walk::RefsById;
2
2
use crate :: init:: { Entrypoint , Overlay } ;
3
3
use but_core:: { RefMetadata , ref_metadata} ;
4
4
use gix:: prelude:: ReferenceExt ;
5
+ use gix:: refs:: Target ;
5
6
use std:: borrow:: Cow ;
6
7
use std:: collections:: BTreeSet ;
7
8
@@ -16,13 +17,27 @@ impl Overlay {
16
17
self
17
18
}
18
19
20
+ /// Serve the given `refs` from memory, which is like creating the reference or as if its value was set,
21
+ /// completely overriding the value in the repository.
22
+ pub fn with_references ( mut self , refs : impl IntoIterator < Item = gix:: refs:: Reference > ) -> Self {
23
+ self . overriding_references . extend ( refs) ;
24
+ self
25
+ }
26
+
19
27
/// Override the starting position of the traversal by setting it to `id`,
20
28
/// and optionally, by providing the `ref_name` that points to `id`.
21
29
pub fn with_entrypoint (
22
30
mut self ,
23
31
id : gix:: ObjectId ,
24
32
ref_name : Option < gix:: refs:: FullName > ,
25
33
) -> Self {
34
+ if let Some ( ref_name) = & ref_name {
35
+ self . overriding_references . push ( gix:: refs:: Reference {
36
+ name : ref_name. to_owned ( ) ,
37
+ target : Target :: Object ( id) ,
38
+ peeled : Some ( id) ,
39
+ } )
40
+ }
26
41
self . entrypoint = Some ( ( id, ref_name) ) ;
27
42
self
28
43
}
@@ -58,14 +73,19 @@ impl Overlay {
58
73
T : RefMetadata ,
59
74
{
60
75
let Overlay {
61
- nonoverriding_references,
76
+ mut nonoverriding_references,
77
+ mut overriding_references,
62
78
meta_branches,
63
79
workspace,
64
80
entrypoint,
65
81
} = self ;
82
+ // Make sure that duplicates from later determine the value.
83
+ nonoverriding_references. reverse ( ) ;
84
+ overriding_references. reverse ( ) ;
66
85
(
67
86
OverlayRepo {
68
- nonoverriding_references,
87
+ nonoverriding_references : nonoverriding_references. into_iter ( ) . collect ( ) ,
88
+ overriding_references : overriding_references. into_iter ( ) . collect ( ) ,
69
89
inner : repo,
70
90
} ,
71
91
OverlayMetadata {
@@ -80,7 +100,8 @@ impl Overlay {
80
100
81
101
pub ( crate ) struct OverlayRepo < ' repo > {
82
102
inner : & ' repo gix:: Repository ,
83
- nonoverriding_references : Vec < gix:: refs:: Reference > ,
103
+ nonoverriding_references : BTreeSet < gix:: refs:: Reference > ,
104
+ overriding_references : BTreeSet < gix:: refs:: Reference > ,
84
105
}
85
106
86
107
/// Note that functions with `'repo` in their return value technically leak the bare repo, and it's
@@ -94,7 +115,13 @@ impl<'repo> OverlayRepo<'repo> {
94
115
& self ,
95
116
ref_name : & gix:: refs:: FullNameRef ,
96
117
) -> anyhow:: Result < Option < gix:: Reference < ' repo > > > {
97
- if let Some ( rn) = self . inner . try_find_reference ( ref_name) ? {
118
+ if let Some ( r) = self
119
+ . overriding_references
120
+ . iter ( )
121
+ . find ( |r| r. name . as_ref ( ) == ref_name)
122
+ {
123
+ Ok ( Some ( r. clone ( ) . attach ( self . inner ) ) )
124
+ } else if let Some ( rn) = self . inner . try_find_reference ( ref_name) ? {
98
125
Ok ( Some ( rn) )
99
126
} else if let Some ( r) = self
100
127
. nonoverriding_references
@@ -111,6 +138,13 @@ impl<'repo> OverlayRepo<'repo> {
111
138
& self ,
112
139
ref_name : & gix:: refs:: FullNameRef ,
113
140
) -> anyhow:: Result < gix:: Reference < ' repo > > {
141
+ if let Some ( r) = self
142
+ . overriding_references
143
+ . iter ( )
144
+ . find ( |r| r. name . as_ref ( ) == ref_name)
145
+ {
146
+ return Ok ( r. clone ( ) . attach ( self . inner ) ) ;
147
+ }
114
148
Ok ( self
115
149
. inner
116
150
. find_reference ( ref_name)
@@ -202,6 +236,18 @@ impl<'repo> OverlayRepo<'repo> {
202
236
} ;
203
237
let mut all_refs_by_id = gix:: hashtable:: HashMap :: < _ , Vec < _ > > :: default ( ) ;
204
238
for prefix in prefixes {
239
+ // apply overrides - they are seen first and take the spot of everything.
240
+ for ( commit_id, git_reference) in self
241
+ . overriding_references
242
+ . iter ( )
243
+ . filter ( |rn| rn. name . as_bstr ( ) . starts_with ( prefix. as_bytes ( ) ) )
244
+ . filter_map ( |rn| ref_filter ( rn. clone ( ) . attach ( self . inner ) ) )
245
+ {
246
+ all_refs_by_id
247
+ . entry ( commit_id)
248
+ . or_default ( )
249
+ . push ( git_reference) ;
250
+ }
205
251
for ( commit_id, git_reference) in self
206
252
. inner
207
253
. references ( ) ?
@@ -214,7 +260,7 @@ impl<'repo> OverlayRepo<'repo> {
214
260
. or_default ( )
215
261
. push ( git_reference) ;
216
262
}
217
- // apply overrides
263
+ // apply overrides (new only)
218
264
for ( commit_id, git_reference) in self
219
265
. nonoverriding_references
220
266
. iter ( )
0 commit comments