@@ -16,7 +16,7 @@ use crate::{
1616 handshake:: Ref ,
1717} ;
1818
19- /// The error returned by [`RefMap::new ()`].
19+ /// The error returned by [`RefMap::fetch ()`].
2020#[ derive( Debug , thiserror:: Error ) ]
2121#[ allow( missing_docs) ]
2222pub enum Error {
@@ -28,89 +28,60 @@ pub enum Error {
2828 ListRefs ( #[ from] crate :: ls_refs:: Error ) ,
2929}
3030
31- /// For use in [`RefMap::new ()`].
31+ /// For use in [`RefMap::fetch ()`].
3232#[ derive( Debug , Clone ) ]
33- pub struct Options {
33+ pub struct Context {
3434 /// All explicit refspecs to identify references on the remote that you are interested in.
3535 /// Note that these are copied to [`RefMap::refspecs`] for convenience, as `RefMap::mappings` refer to them by index.
36- fetch_refspecs : Vec < gix_refspec:: RefSpec > ,
37- /// Use a two-component prefix derived from the ref-spec's source, like `refs/heads/` to let the server pre-filter refs
38- /// with great potential for savings in traffic and local CPU time. Defaults to `true`.
39- prefix_from_spec_as_filter_on_remote : bool ,
36+ pub fetch_refspecs : Vec < gix_refspec:: RefSpec > ,
4037 /// A list of refspecs to use as implicit refspecs which won't be saved or otherwise be part of the remote in question.
4138 ///
4239 /// This is useful for handling `remote.<name>.tagOpt` for example.
43- extra_refspecs : Vec < gix_refspec:: RefSpec > ,
44- all_refspecs : Vec < gix_refspec:: RefSpec > ,
40+ pub extra_refspecs : Vec < gix_refspec:: RefSpec > ,
4541}
4642
47- impl Options {
48- /// Create options to fetch the given `fetch_refspecs`.
49- pub fn fetch ( fetch_refspecs : Vec < gix_refspec:: RefSpec > ) -> Self {
50- Self :: new ( fetch_refspecs, true , Vec :: new ( ) )
51- }
52-
53- /// Specify all options for fetching.
54- pub fn new (
55- fetch_refspecs : Vec < gix_refspec:: RefSpec > ,
56- prefix_from_spec_as_filter_on_remote : bool ,
57- extra_refspecs : Vec < gix_refspec:: RefSpec > ,
58- ) -> Self {
59- let mut all_refspecs = fetch_refspecs. clone ( ) ;
60- all_refspecs. extend ( extra_refspecs. iter ( ) . cloned ( ) ) ;
61-
62- Self {
63- all_refspecs,
64- fetch_refspecs : fetch_refspecs. clone ( ) ,
65- prefix_from_spec_as_filter_on_remote,
66- extra_refspecs,
67- }
68- }
69-
70- fn push_prefix_arguments ( & self , arguments : & mut Vec < BString > ) {
71- if !self . prefix_from_spec_as_filter_on_remote {
72- return ;
73- }
74-
75- let mut seen = HashSet :: new ( ) ;
76- for spec in & self . all_refspecs {
77- let spec = spec. to_ref ( ) ;
78- if seen. insert ( spec. instruction ( ) ) {
79- let mut prefixes = Vec :: with_capacity ( 1 ) ;
80- spec. expand_prefixes ( & mut prefixes) ;
81- for mut prefix in prefixes {
82- prefix. insert_str ( 0 , "ref-prefix " ) ;
83- arguments. push ( prefix) ;
84- }
85- }
86- }
43+ impl Context {
44+ fn aggregate_refspecs ( & self ) -> Vec < gix_refspec:: RefSpec > {
45+ let mut all_refspecs = self . fetch_refspecs . clone ( ) ;
46+ all_refspecs. extend ( self . extra_refspecs . iter ( ) . cloned ( ) ) ;
47+ all_refspecs
8748 }
8849}
8950
9051impl RefMap {
91- /// Create a new instance by obtaining all references on the remote that have been filtered through our remote's
52+ /// Create a new instance by obtaining all references on the remote that have been filtered through our remote's specs
9253 /// for _fetching_.
9354 ///
9455 /// * `progress` is used if `ls-refs` is invoked on the remote. Always the case when V2 is used.
56+ /// * `capabilities` are the capabilities of the server, obtained by a [handshake](crate::handshake()).
57+ /// * `transport` is a way to communicate with the server to obtain the reference listing.
58+ /// * `user_agent` is passed to the server.
59+ /// * `trace_packetlines` traces all packet lines if `true`, for debugging primarily.
60+ /// * `prefix_from_spec_as_filter_on_remote`
61+ /// - Use a two-component prefix derived from the ref-spec's source, like `refs/heads/` to let the server pre-filter refs
62+ /// with great potential for savings in traffic and local CPU time.
63+ /// * `context` to provide more [configuration](Context).
9564 #[ allow( clippy:: result_large_err) ]
9665 #[ maybe_async:: maybe_async]
97- pub async fn new < T > (
66+ pub async fn fetch < T > (
9867 mut progress : impl Progress ,
9968 capabilities : & Capabilities ,
10069 transport : & mut T ,
10170 user_agent : ( & ' static str , Option < Cow < ' static , str > > ) ,
10271 trace_packetlines : bool ,
103- options : Options ,
72+ prefix_from_spec_as_filter_on_remote : bool ,
73+ context : Context ,
10474 ) -> Result < Self , Error >
10575 where
10676 T : Transport ,
10777 {
10878 let _span = gix_trace:: coarse!( "gix_protocol::fetch::RefMap::new()" ) ;
79+ let all_refspecs = context. aggregate_refspecs ( ) ;
10980 let remote_refs = crate :: ls_refs (
11081 transport,
11182 capabilities,
11283 |_capabilities, arguments| {
113- options . push_prefix_arguments ( arguments) ;
84+ push_prefix_arguments ( prefix_from_spec_as_filter_on_remote , arguments, & all_refspecs ) ;
11485 Ok ( crate :: ls_refs:: Action :: Continue )
11586 } ,
11687 & mut progress,
@@ -119,18 +90,16 @@ impl RefMap {
11990 )
12091 . await ?;
12192
122- Self :: from_refs ( remote_refs, capabilities, options )
93+ Self :: from_refs ( remote_refs, capabilities, context )
12394 }
12495
125- /// Create a ref-map from already obtained `remote_refs`.
126- pub fn from_refs ( remote_refs : Vec < Ref > , capabilities : & Capabilities , options : Options ) -> Result < RefMap , Error > {
127- let Options {
96+ /// Create a ref-map from already obtained `remote_refs`. Use `context` to pass in refspecs.
97+ pub fn from_refs ( remote_refs : Vec < Ref > , capabilities : & Capabilities , context : Context ) -> Result < RefMap , Error > {
98+ let all_refspecs = context. aggregate_refspecs ( ) ;
99+ let Context {
128100 fetch_refspecs,
129101 extra_refspecs,
130- all_refspecs,
131- ..
132- } = options;
133-
102+ } = context;
134103 let num_explicit_specs = fetch_refspecs. len ( ) ;
135104 let group = gix_refspec:: MatchGroup :: from_fetch_specs ( all_refspecs. iter ( ) . map ( gix_refspec:: RefSpec :: to_ref) ) ;
136105 let null = gix_hash:: ObjectId :: null ( gix_hash:: Kind :: Sha1 ) ; // OK to hardcode Sha1, it's not supposed to match, ever.
@@ -191,3 +160,26 @@ impl RefMap {
191160 } )
192161 }
193162}
163+
164+ fn push_prefix_arguments (
165+ prefix_from_spec_as_filter_on_remote : bool ,
166+ arguments : & mut Vec < BString > ,
167+ all_refspecs : & [ gix_refspec:: RefSpec ] ,
168+ ) {
169+ if !prefix_from_spec_as_filter_on_remote {
170+ return ;
171+ }
172+
173+ let mut seen = HashSet :: new ( ) ;
174+ for spec in all_refspecs {
175+ let spec = spec. to_ref ( ) ;
176+ if seen. insert ( spec. instruction ( ) ) {
177+ let mut prefixes = Vec :: with_capacity ( 1 ) ;
178+ spec. expand_prefixes ( & mut prefixes) ;
179+ for mut prefix in prefixes {
180+ prefix. insert_str ( 0 , "ref-prefix " ) ;
181+ arguments. push ( prefix) ;
182+ }
183+ }
184+ }
185+ }
0 commit comments