@@ -23,8 +23,39 @@ pub struct ConfigEntry<'cfg> {
23
23
}
24
24
25
25
/// An iterator over the `ConfigEntry` values of a `Config` structure.
26
+ ///
27
+ /// Due to lifetime restrictions, `ConfigEntries` does not implement the
28
+ /// standard [`Iterator`] trait. It provides a [`next`] function which only
29
+ /// allows access to one entry at a time. [`for_each`] is available as a
30
+ /// convenience function.
31
+ ///
32
+ /// [`next`]: ConfigEntries::next
33
+ /// [`for_each`]: ConfigEntries::for_each
34
+ ///
35
+ /// # Example
36
+ ///
37
+ /// ```
38
+ /// // Example of how to collect all entries.
39
+ /// use git2::Config;
40
+ ///
41
+ /// let config = Config::new()?;
42
+ /// let iter = config.entries(None)?;
43
+ /// let mut entries = Vec::new();
44
+ /// iter
45
+ /// .for_each(|entry| {
46
+ /// let name = entry.name().unwrap().to_string();
47
+ /// let value = entry.value().unwrap_or("").to_string();
48
+ /// entries.push((name, value))
49
+ /// })?;
50
+ /// for entry in &entries {
51
+ /// println!("{} = {}", entry.0, entry.1);
52
+ /// }
53
+ /// # Ok::<(), git2::Error>(())
54
+ ///
55
+ /// ```
26
56
pub struct ConfigEntries < ' cfg > {
27
57
raw : * mut raw:: git_config_iterator ,
58
+ current : Option < ConfigEntry < ' cfg > > ,
28
59
_marker : marker:: PhantomData < & ' cfg Config > ,
29
60
}
30
61
@@ -280,15 +311,18 @@ impl Config {
280
311
/// the variable name: the section and variable parts are lower-cased. The
281
312
/// subsection is left unchanged.
282
313
///
314
+ /// Due to lifetime restrictions, the returned value does not implement
315
+ /// the standard [`Iterator`] trait. See [`ConfigEntries`] for more.
316
+ ///
283
317
/// # Example
284
318
///
285
319
/// ```
286
- /// # #![allow(unstable)]
287
320
/// use git2::Config;
288
321
///
289
322
/// let cfg = Config::new().unwrap();
290
323
///
291
- /// for entry in &cfg.entries(None).unwrap() {
324
+ /// let mut entries = cfg.entries(None).unwrap();
325
+ /// while let Some(entry) = entries.next() {
292
326
/// let entry = entry.unwrap();
293
327
/// println!("{} => {}", entry.name().unwrap(), entry.value().unwrap());
294
328
/// }
@@ -317,6 +351,9 @@ impl Config {
317
351
/// The regular expression is applied case-sensitively on the normalized form of
318
352
/// the variable name: the section and variable parts are lower-cased. The
319
353
/// subsection is left unchanged.
354
+ ///
355
+ /// Due to lifetime restrictions, the returned value does not implement
356
+ /// the standard [`Iterator`] trait. See [`ConfigEntries`] for more.
320
357
pub fn multivar ( & self , name : & str , regexp : Option < & str > ) -> Result < ConfigEntries < ' _ > , Error > {
321
358
let mut ret = ptr:: null_mut ( ) ;
322
359
let name = CString :: new ( name) ?;
@@ -550,6 +587,7 @@ impl<'cfg> Binding for ConfigEntries<'cfg> {
550
587
unsafe fn from_raw ( raw : * mut raw:: git_config_iterator ) -> ConfigEntries < ' cfg > {
551
588
ConfigEntries {
552
589
raw,
590
+ current : None ,
553
591
_marker : marker:: PhantomData ,
554
592
}
555
593
}
@@ -558,24 +596,33 @@ impl<'cfg> Binding for ConfigEntries<'cfg> {
558
596
}
559
597
}
560
598
561
- // entries are only valid until the iterator is freed, so this impl is for
562
- // `&'b T` instead of `T` to have a lifetime to tie them to.
563
- //
564
- // It's also not implemented for `&'b mut T` so we can have multiple entries
565
- // (ok).
566
- impl < ' cfg , ' b > Iterator for & ' b ConfigEntries < ' cfg > {
567
- type Item = Result < ConfigEntry < ' b > , Error > ;
568
- fn next ( & mut self ) -> Option < Result < ConfigEntry < ' b > , Error > > {
599
+ impl < ' cfg > ConfigEntries < ' cfg > {
600
+ /// Advances the iterator and returns the next value.
601
+ ///
602
+ /// Returns `None` when iteration is finished.
603
+ pub fn next ( & mut self ) -> Option < Result < & ConfigEntry < ' cfg > , Error > > {
569
604
let mut raw = ptr:: null_mut ( ) ;
605
+ drop ( self . current . take ( ) ) ;
570
606
unsafe {
571
607
try_call_iter ! ( raw:: git_config_next( & mut raw, self . raw) ) ;
572
- Some ( Ok ( ConfigEntry {
608
+ let entry = ConfigEntry {
573
609
owned : false ,
574
610
raw,
575
611
_marker : marker:: PhantomData ,
576
- } ) )
612
+ } ;
613
+ self . current = Some ( entry) ;
614
+ Some ( Ok ( self . current . as_ref ( ) . unwrap ( ) ) )
577
615
}
578
616
}
617
+
618
+ /// Calls the given closure for each remaining entry in the iterator.
619
+ pub fn for_each < F : FnMut ( & ConfigEntry < ' cfg > ) > ( mut self , mut f : F ) -> Result < ( ) , Error > {
620
+ while let Some ( entry) = self . next ( ) {
621
+ let entry = entry?;
622
+ f ( entry) ;
623
+ }
624
+ Ok ( ( ) )
625
+ }
579
626
}
580
627
581
628
impl < ' cfg > Drop for ConfigEntries < ' cfg > {
@@ -628,7 +675,8 @@ mod tests {
628
675
assert_eq ! ( cfg. get_i64( "foo.k3" ) . unwrap( ) , 2 ) ;
629
676
assert_eq ! ( cfg. get_str( "foo.k4" ) . unwrap( ) , "bar" ) ;
630
677
631
- for entry in & cfg. entries ( None ) . unwrap ( ) {
678
+ let mut entries = cfg. entries ( None ) . unwrap ( ) ;
679
+ while let Some ( entry) = entries. next ( ) {
632
680
let entry = entry. unwrap ( ) ;
633
681
entry. name ( ) ;
634
682
entry. value ( ) ;
@@ -649,39 +697,42 @@ mod tests {
649
697
cfg. set_multivar ( "foo.baz" , "^$" , "oki" ) . unwrap ( ) ;
650
698
651
699
// `entries` filters by name
652
- let mut entries: Vec < String > = cfg
653
- . entries ( Some ( "foo.bar" ) )
700
+ let mut entries: Vec < String > = Vec :: new ( ) ;
701
+ cfg . entries ( Some ( "foo.bar" ) )
654
702
. unwrap ( )
655
- . into_iter ( )
656
- . map ( |entry| entry. unwrap ( ) . value ( ) . unwrap ( ) . into ( ) )
657
- . collect ( ) ;
703
+ . for_each ( |entry| entries. push ( entry. value ( ) . unwrap ( ) . to_string ( ) ) )
704
+ . unwrap ( ) ;
658
705
entries. sort ( ) ;
659
706
assert_eq ! ( entries, [ "baz" , "quux" , "qux" ] ) ;
660
707
661
708
// which is the same as `multivar` without a regex
662
- let mut multivals: Vec < String > = cfg
663
- . multivar ( "foo.bar" , None )
709
+ let mut multivals = Vec :: new ( ) ;
710
+ cfg . multivar ( "foo.bar" , None )
664
711
. unwrap ( )
665
- . into_iter ( )
666
- . map ( |entry| entry. unwrap ( ) . value ( ) . unwrap ( ) . into ( ) )
667
- . collect ( ) ;
712
+ . for_each ( |entry| multivals. push ( entry. value ( ) . unwrap ( ) . to_string ( ) ) )
713
+ . unwrap ( ) ;
668
714
multivals. sort ( ) ;
669
715
assert_eq ! ( multivals, entries) ;
670
716
671
717
// yet _with_ a regex, `multivar` filters by value
672
- let mut quxish: Vec < String > = cfg
673
- . multivar ( "foo.bar" , Some ( "qu.*x" ) )
718
+ let mut quxish = Vec :: new ( ) ;
719
+ cfg . multivar ( "foo.bar" , Some ( "qu.*x" ) )
674
720
. unwrap ( )
675
- . into_iter ( )
676
- . map ( |entry| entry. unwrap ( ) . value ( ) . unwrap ( ) . into ( ) )
677
- . collect ( ) ;
721
+ . for_each ( |entry| quxish. push ( entry. value ( ) . unwrap ( ) . to_string ( ) ) )
722
+ . unwrap ( ) ;
678
723
quxish. sort ( ) ;
679
724
assert_eq ! ( quxish, [ "quux" , "qux" ] ) ;
680
725
681
726
cfg. remove_multivar ( "foo.bar" , ".*" ) . unwrap ( ) ;
682
727
683
- assert_eq ! ( cfg. entries( Some ( "foo.bar" ) ) . unwrap( ) . count( ) , 0 ) ;
684
- assert_eq ! ( cfg. multivar( "foo.bar" , None ) . unwrap( ) . count( ) , 0 ) ;
728
+ let count = |entries : super :: ConfigEntries < ' _ > | -> usize {
729
+ let mut c = 0 ;
730
+ entries. for_each ( |_| c += 1 ) . unwrap ( ) ;
731
+ c
732
+ } ;
733
+
734
+ assert_eq ! ( count( cfg. entries( Some ( "foo.bar" ) ) . unwrap( ) ) , 0 ) ;
735
+ assert_eq ! ( count( cfg. multivar( "foo.bar" , None ) . unwrap( ) ) , 0 ) ;
685
736
}
686
737
687
738
#[ test]
0 commit comments