@@ -2,6 +2,7 @@ use crate::init::walk::RefsById;
22use crate :: init:: { Entrypoint , Overlay } ;
33use but_core:: { RefMetadata , ref_metadata} ;
44use gix:: prelude:: ReferenceExt ;
5+ use gix:: refs:: Target ;
56use std:: borrow:: Cow ;
67use std:: collections:: BTreeSet ;
78
@@ -16,13 +17,27 @@ impl Overlay {
1617 self
1718 }
1819
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+
1927 /// Override the starting position of the traversal by setting it to `id`,
2028 /// and optionally, by providing the `ref_name` that points to `id`.
2129 pub fn with_entrypoint (
2230 mut self ,
2331 id : gix:: ObjectId ,
2432 ref_name : Option < gix:: refs:: FullName > ,
2533 ) -> 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+ }
2641 self . entrypoint = Some ( ( id, ref_name) ) ;
2742 self
2843 }
@@ -58,14 +73,19 @@ impl Overlay {
5873 T : RefMetadata ,
5974 {
6075 let Overlay {
61- nonoverriding_references,
76+ mut nonoverriding_references,
77+ mut overriding_references,
6278 meta_branches,
6379 workspace,
6480 entrypoint,
6581 } = self ;
82+ // Make sure that duplicates from later determine the value.
83+ nonoverriding_references. reverse ( ) ;
84+ overriding_references. reverse ( ) ;
6685 (
6786 OverlayRepo {
68- nonoverriding_references,
87+ nonoverriding_references : nonoverriding_references. into_iter ( ) . collect ( ) ,
88+ overriding_references : overriding_references. into_iter ( ) . collect ( ) ,
6989 inner : repo,
7090 } ,
7191 OverlayMetadata {
@@ -80,7 +100,8 @@ impl Overlay {
80100
81101pub ( crate ) struct OverlayRepo < ' repo > {
82102 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 > ,
84105}
85106
86107/// 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> {
94115 & self ,
95116 ref_name : & gix:: refs:: FullNameRef ,
96117 ) -> 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) ? {
98125 Ok ( Some ( rn) )
99126 } else if let Some ( r) = self
100127 . nonoverriding_references
@@ -111,6 +138,13 @@ impl<'repo> OverlayRepo<'repo> {
111138 & self ,
112139 ref_name : & gix:: refs:: FullNameRef ,
113140 ) -> 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+ }
114148 Ok ( self
115149 . inner
116150 . find_reference ( ref_name)
@@ -202,6 +236,18 @@ impl<'repo> OverlayRepo<'repo> {
202236 } ;
203237 let mut all_refs_by_id = gix:: hashtable:: HashMap :: < _ , Vec < _ > > :: default ( ) ;
204238 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+ }
205251 for ( commit_id, git_reference) in self
206252 . inner
207253 . references ( ) ?
@@ -214,7 +260,7 @@ impl<'repo> OverlayRepo<'repo> {
214260 . or_default ( )
215261 . push ( git_reference) ;
216262 }
217- // apply overrides
263+ // apply overrides (new only)
218264 for ( commit_id, git_reference) in self
219265 . nonoverriding_references
220266 . iter ( )
0 commit comments