1
- use crate :: { Error , Negotiator } ;
1
+ use crate :: { Error , Flags , Negotiator } ;
2
2
use gix_hash:: ObjectId ;
3
3
use gix_revision:: graph:: CommitterTimestamp ;
4
- use smallvec:: SmallVec ;
5
- bitflags:: bitflags! {
6
- /// Whether something can be read or written.
7
- #[ derive( Debug , Default , Copy , Clone ) ]
8
- pub struct Flags : u8 {
9
- /// The revision is known to be in common with the remote.
10
- const COMMON = 1 << 0 ;
11
- /// The revision is common and was set by merit of a remote tracking ref (e.g. `refs/heads/origin/main`).
12
- const COMMON_REF = 1 << 1 ;
13
- /// The revision has entered the priority queue.
14
- const SEEN = 1 << 2 ;
15
- /// The revision was popped off our primary priority queue, used to avoid double-counting of `non_common_revs`
16
- const POPPED = 1 << 3 ;
17
- }
18
- }
19
4
20
- pub ( crate ) struct Algorithm < ' find > {
21
- graph : gix_revision:: Graph < ' find , Flags > ,
5
+ pub ( crate ) struct Algorithm {
22
6
revs : gix_revision:: PriorityQueue < CommitterTimestamp , ObjectId > ,
23
7
non_common_revs : usize ,
24
8
}
25
9
26
- impl < ' a > Algorithm < ' a > {
27
- pub fn new ( graph : gix_revision :: Graph < ' a , Flags > ) -> Self {
10
+ impl Default for Algorithm {
11
+ fn default ( ) -> Self {
28
12
Self {
29
- graph,
30
13
revs : gix_revision:: PriorityQueue :: new ( ) ,
31
14
non_common_revs : 0 ,
32
15
}
33
16
}
17
+ }
34
18
19
+ impl Algorithm {
35
20
/// Add `id` to our priority queue and *add* `flags` to it.
36
- fn add_to_queue ( & mut self , id : ObjectId , mark : Flags ) -> Result < ( ) , Error > {
21
+ fn add_to_queue ( & mut self , id : ObjectId , mark : Flags , graph : & mut crate :: Graph < ' _ > ) -> Result < ( ) , Error > {
37
22
let mut is_common = false ;
38
- if self . graph . get ( & id) . map_or ( false , |flags| flags. intersects ( mark) ) {
39
- return Ok ( ( ) ) ;
40
- }
41
- let commit = self . graph . try_lookup_and_insert ( id, |current| {
42
- * current |= mark;
43
- is_common = current. contains ( Flags :: COMMON ) ;
44
- } ) ?;
45
- if let Some ( timestamp) = commit. map ( |c| c. committer_timestamp ( ) ) . transpose ( ) ? {
46
- self . revs . insert ( timestamp, id) ;
23
+ let mut has_mark = false ;
24
+ if let Some ( commit) = graph
25
+ . try_lookup_or_insert_commit ( id, |data| {
26
+ has_mark = data. flags . intersects ( mark) ;
27
+ data. flags |= mark;
28
+ is_common = data. flags . contains ( Flags :: COMMON ) ;
29
+ } ) ?
30
+ . filter ( |_| !has_mark)
31
+ {
32
+ self . revs . insert ( commit. commit_time , id) ;
47
33
if !is_common {
48
34
self . non_common_revs += 1 ;
49
35
}
50
36
}
51
37
Ok ( ( ) )
52
38
}
53
39
54
- fn mark_common ( & mut self , id : ObjectId , mode : Mark , ancestors : Ancestors ) -> Result < ( ) , Error > {
40
+ fn mark_common (
41
+ & mut self ,
42
+ id : ObjectId ,
43
+ mode : Mark ,
44
+ ancestors : Ancestors ,
45
+ graph : & mut crate :: Graph < ' _ > ,
46
+ ) -> Result < ( ) , Error > {
55
47
let mut is_common = false ;
56
- if let Some ( commit) = self
57
- . graph
58
- . try_lookup_and_insert ( id, |current| is_common = current. contains ( Flags :: COMMON ) ) ?
48
+ if let Some ( commit) = graph
49
+ . try_lookup_or_insert_commit ( id, |data| is_common = data. flags . contains ( Flags :: COMMON ) ) ?
59
50
. filter ( |_| !is_common)
60
51
{
61
- let mut queue =
62
- gix_revision:: PriorityQueue :: from_iter ( Some ( ( commit. committer_timestamp ( ) ?, ( id, 0_usize ) ) ) ) ;
52
+ let mut queue = gix_revision:: PriorityQueue :: from_iter ( Some ( ( commit. commit_time , ( id, 0_usize ) ) ) ) ;
63
53
if let Mark :: ThisCommitAndAncestors = mode {
64
- let current = self . graph . get_mut ( & id) . expect ( "just inserted" ) ;
65
- * current |= Flags :: COMMON ;
66
- if current. contains ( Flags :: SEEN ) && !current. contains ( Flags :: POPPED ) {
54
+ commit. data . flags |= Flags :: COMMON ;
55
+ if commit. data . flags . contains ( Flags :: SEEN ) && !commit. data . flags . contains ( Flags :: POPPED ) {
67
56
self . non_common_revs -= 1 ;
68
57
}
69
58
}
70
- let mut parents = SmallVec :: new ( ) ;
71
59
while let Some ( ( id, generation) ) = queue. pop ( ) {
72
- if self . graph . get ( & id) . map_or ( true , |d| !d. contains ( Flags :: SEEN ) ) {
73
- self . add_to_queue ( id, Flags :: SEEN ) ?;
60
+ if graph
61
+ . get ( & id)
62
+ . map_or ( true , |commit| !commit. data . flags . contains ( Flags :: SEEN ) )
63
+ {
64
+ self . add_to_queue ( id, Flags :: SEEN , graph) ?;
74
65
} else if matches ! ( ancestors, Ancestors :: AllUnseen ) || generation < 2 {
75
- if let Some ( commit) = self . graph . try_lookup_and_insert ( id, |_| { } ) ? {
76
- collect_parents ( commit. iter_parents ( ) , & mut parents) ?;
77
- for parent_id in parents. drain ( ..) {
66
+ if let Some ( commit) = graph. try_lookup_or_insert_commit ( id, |_| { } ) ? {
67
+ for parent_id in commit. parents . clone ( ) {
78
68
let mut prev_flags = Flags :: default ( ) ;
79
- if let Some ( parent) = self
80
- . graph
81
- . try_lookup_and_insert ( parent_id, |d| {
82
- prev_flags = * d;
83
- * d |= Flags :: COMMON ;
69
+ if let Some ( parent) = graph
70
+ . try_lookup_or_insert_commit ( parent_id, |data| {
71
+ prev_flags = data. flags ;
72
+ data. flags |= Flags :: COMMON ;
84
73
} ) ?
85
74
. filter ( |_| !prev_flags. contains ( Flags :: COMMON ) )
86
75
{
87
76
if prev_flags. contains ( Flags :: SEEN ) && !prev_flags. contains ( Flags :: POPPED ) {
88
77
self . non_common_revs -= 1 ;
89
78
}
90
- queue. insert ( parent. committer_timestamp ( ) ? , ( parent_id, generation + 1 ) )
79
+ queue. insert ( parent. commit_time , ( parent_id, generation + 1 ) )
91
80
}
92
81
}
93
82
}
@@ -98,38 +87,27 @@ impl<'a> Algorithm<'a> {
98
87
}
99
88
}
100
89
101
- pub ( crate ) fn collect_parents (
102
- parents : gix_revision:: graph:: commit:: Parents < ' _ > ,
103
- out : & mut SmallVec < [ ObjectId ; 2 ] > ,
104
- ) -> Result < ( ) , Error > {
105
- out. clear ( ) ;
106
- for parent in parents {
107
- out. push ( parent. map_err ( |err| match err {
108
- gix_revision:: graph:: commit:: iter_parents:: Error :: DecodeCommit ( err) => Error :: DecodeCommit ( err) ,
109
- gix_revision:: graph:: commit:: iter_parents:: Error :: DecodeCommitGraph ( err) => Error :: DecodeCommitInGraph ( err) ,
110
- } ) ?) ;
111
- }
112
- Ok ( ( ) )
113
- }
114
-
115
- impl < ' a > Negotiator for Algorithm < ' a > {
116
- fn known_common ( & mut self , id : ObjectId ) -> Result < ( ) , Error > {
117
- if self . graph . get ( & id) . map_or ( true , |d| !d. contains ( Flags :: SEEN ) ) {
118
- self . add_to_queue ( id, Flags :: COMMON_REF | Flags :: SEEN ) ?;
119
- self . mark_common ( id, Mark :: AncestorsOnly , Ancestors :: DirectUnseen ) ?;
90
+ impl Negotiator for Algorithm {
91
+ fn known_common ( & mut self , id : ObjectId , graph : & mut crate :: Graph < ' _ > ) -> Result < ( ) , Error > {
92
+ if graph
93
+ . get ( & id)
94
+ . map_or ( true , |commit| !commit. data . flags . contains ( Flags :: SEEN ) )
95
+ {
96
+ self . add_to_queue ( id, Flags :: COMMON_REF | Flags :: SEEN , graph) ?;
97
+ self . mark_common ( id, Mark :: AncestorsOnly , Ancestors :: DirectUnseen , graph) ?;
120
98
}
121
99
Ok ( ( ) )
122
100
}
123
101
124
- fn add_tip ( & mut self , id : ObjectId ) -> Result < ( ) , Error > {
125
- self . add_to_queue ( id, Flags :: SEEN )
102
+ fn add_tip ( & mut self , id : ObjectId , graph : & mut crate :: Graph < ' _ > ) -> Result < ( ) , Error > {
103
+ self . add_to_queue ( id, Flags :: SEEN , graph )
126
104
}
127
105
128
- fn next_have ( & mut self ) -> Option < Result < ObjectId , Error > > {
129
- let mut parents = SmallVec :: new ( ) ;
106
+ fn next_have ( & mut self , graph : & mut crate :: Graph < ' _ > ) -> Option < Result < ObjectId , Error > > {
130
107
loop {
131
108
let id = self . revs . pop ( ) . filter ( |_| self . non_common_revs != 0 ) ?;
132
- let flags = self . graph . get_mut ( & id) . expect ( "it was added to the graph by now" ) ;
109
+ let commit = graph. get_mut ( & id) . expect ( "it was added to the graph by now" ) ;
110
+ let flags = & mut commit. data . flags ;
133
111
* flags |= Flags :: POPPED ;
134
112
135
113
if !flags. contains ( Flags :: COMMON ) {
@@ -144,21 +122,17 @@ impl<'a> Negotiator for Algorithm<'a> {
144
122
( Some ( id) , Flags :: SEEN )
145
123
} ;
146
124
147
- let commit = match self . graph . try_lookup ( & id) {
148
- Ok ( c) => c. expect ( "it was found before, must still be there" ) ,
149
- Err ( err) => return Some ( Err ( err. into ( ) ) ) ,
150
- } ;
151
- if let Err ( err) = collect_parents ( commit. iter_parents ( ) , & mut parents) {
152
- return Some ( Err ( err) ) ;
153
- }
154
- for parent_id in parents. drain ( ..) {
155
- if self . graph . get ( & parent_id) . map_or ( true , |d| !d. contains ( Flags :: SEEN ) ) {
156
- if let Err ( err) = self . add_to_queue ( parent_id, mark) {
125
+ for parent_id in commit. parents . clone ( ) {
126
+ if graph
127
+ . get ( & parent_id)
128
+ . map_or ( true , |commit| !commit. data . flags . contains ( Flags :: SEEN ) )
129
+ {
130
+ if let Err ( err) = self . add_to_queue ( parent_id, mark, graph) {
157
131
return Some ( Err ( err) ) ;
158
132
}
159
133
}
160
134
if mark. contains ( Flags :: COMMON ) {
161
- if let Err ( err) = self . mark_common ( parent_id, Mark :: AncestorsOnly , Ancestors :: AllUnseen ) {
135
+ if let Err ( err) = self . mark_common ( parent_id, Mark :: AncestorsOnly , Ancestors :: AllUnseen , graph ) {
162
136
return Some ( Err ( err) ) ;
163
137
}
164
138
}
@@ -170,9 +144,11 @@ impl<'a> Negotiator for Algorithm<'a> {
170
144
}
171
145
}
172
146
173
- fn in_common_with_remote ( & mut self , id : ObjectId ) -> Result < bool , Error > {
174
- let known_to_be_common = self . graph . get ( & id) . map_or ( false , |d| d. contains ( Flags :: COMMON ) ) ;
175
- self . mark_common ( id, Mark :: ThisCommitAndAncestors , Ancestors :: DirectUnseen ) ?;
147
+ fn in_common_with_remote ( & mut self , id : ObjectId , graph : & mut crate :: Graph < ' _ > ) -> Result < bool , Error > {
148
+ let known_to_be_common = graph
149
+ . get ( & id)
150
+ . map_or ( false , |commit| commit. data . flags . contains ( Flags :: COMMON ) ) ;
151
+ self . mark_common ( id, Mark :: ThisCommitAndAncestors , Ancestors :: DirectUnseen , graph) ?;
176
152
Ok ( known_to_be_common)
177
153
}
178
154
}
0 commit comments