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
5
pub ( crate ) struct Algorithm < ' find > {
21
- graph : gix_revision :: Graph < ' find , Flags > ,
6
+ graph : crate :: Graph < ' find > ,
22
7
revs : gix_revision:: PriorityQueue < CommitterTimestamp , ObjectId > ,
23
8
non_common_revs : usize ,
24
9
}
25
10
26
11
impl < ' a > Algorithm < ' a > {
27
- pub fn new ( graph : gix_revision :: Graph < ' a , Flags > ) -> Self {
12
+ pub fn new ( graph : crate :: Graph < ' a > ) -> Self {
28
13
Self {
29
14
graph,
30
15
revs : gix_revision:: PriorityQueue :: new ( ) ,
@@ -35,15 +20,17 @@ impl<'a> Algorithm<'a> {
35
20
/// Add `id` to our priority queue and *add* `flags` to it.
36
21
fn add_to_queue ( & mut self , id : ObjectId , mark : Flags ) -> 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) = self
25
+ . graph
26
+ . try_lookup_or_insert_commit ( id, |data| {
27
+ has_mark = data. flags . intersects ( mark) ;
28
+ data. flags |= mark;
29
+ is_common = data. flags . contains ( Flags :: COMMON ) ;
30
+ } ) ?
31
+ . filter ( |_| !has_mark)
32
+ {
33
+ self . revs . insert ( commit. commit_time , id) ;
47
34
if !is_common {
48
35
self . non_common_revs += 1 ;
49
36
}
@@ -55,39 +42,39 @@ impl<'a> Algorithm<'a> {
55
42
let mut is_common = false ;
56
43
if let Some ( commit) = self
57
44
. graph
58
- . try_lookup_and_insert ( id, |current | is_common = current . contains ( Flags :: COMMON ) ) ?
45
+ . try_lookup_or_insert_commit ( id, |data | is_common = data . flags . contains ( Flags :: COMMON ) ) ?
59
46
. filter ( |_| !is_common)
60
47
{
61
- let mut queue =
62
- gix_revision:: PriorityQueue :: from_iter ( Some ( ( commit. committer_timestamp ( ) ?, ( id, 0_usize ) ) ) ) ;
48
+ let mut queue = gix_revision:: PriorityQueue :: from_iter ( Some ( ( commit. commit_time , ( id, 0_usize ) ) ) ) ;
63
49
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 ) {
50
+ commit. data . flags |= Flags :: COMMON ;
51
+ if commit. data . flags . contains ( Flags :: SEEN ) && !commit. data . flags . contains ( Flags :: POPPED ) {
67
52
self . non_common_revs -= 1 ;
68
53
}
69
54
}
70
- let mut parents = SmallVec :: new ( ) ;
71
55
while let Some ( ( id, generation) ) = queue. pop ( ) {
72
- if self . graph . get ( & id) . map_or ( true , |d| !d. contains ( Flags :: SEEN ) ) {
56
+ if self
57
+ . graph
58
+ . get ( & id)
59
+ . map_or ( true , |commit| !commit. data . flags . contains ( Flags :: SEEN ) )
60
+ {
73
61
self . add_to_queue ( id, Flags :: SEEN ) ?;
74
62
} 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 ( ..) {
63
+ if let Some ( commit) = self . graph . try_lookup_or_insert_commit ( id, |_| { } ) ? {
64
+ for parent_id in commit. parents . clone ( ) {
78
65
let mut prev_flags = Flags :: default ( ) ;
79
66
if let Some ( parent) = self
80
67
. graph
81
- . try_lookup_and_insert ( parent_id, |d | {
82
- prev_flags = * d ;
83
- * d |= Flags :: COMMON ;
68
+ . try_lookup_or_insert_commit ( parent_id, |data | {
69
+ prev_flags = data . flags ;
70
+ data . flags |= Flags :: COMMON ;
84
71
} ) ?
85
72
. filter ( |_| !prev_flags. contains ( Flags :: COMMON ) )
86
73
{
87
74
if prev_flags. contains ( Flags :: SEEN ) && !prev_flags. contains ( Flags :: POPPED ) {
88
75
self . non_common_revs -= 1 ;
89
76
}
90
- queue. insert ( parent. committer_timestamp ( ) ? , ( parent_id, generation + 1 ) )
77
+ queue. insert ( parent. commit_time , ( parent_id, generation + 1 ) )
91
78
}
92
79
}
93
80
}
@@ -98,23 +85,13 @@ impl<'a> Algorithm<'a> {
98
85
}
99
86
}
100
87
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
88
impl < ' a > Negotiator for Algorithm < ' a > {
116
89
fn known_common ( & mut self , id : ObjectId ) -> Result < ( ) , Error > {
117
- if self . graph . get ( & id) . map_or ( true , |d| !d. contains ( Flags :: SEEN ) ) {
90
+ if self
91
+ . graph
92
+ . get ( & id)
93
+ . map_or ( true , |commit| !commit. data . flags . contains ( Flags :: SEEN ) )
94
+ {
118
95
self . add_to_queue ( id, Flags :: COMMON_REF | Flags :: SEEN ) ?;
119
96
self . mark_common ( id, Mark :: AncestorsOnly , Ancestors :: DirectUnseen ) ?;
120
97
}
@@ -126,10 +103,10 @@ impl<'a> Negotiator for Algorithm<'a> {
126
103
}
127
104
128
105
fn next_have ( & mut self ) -> Option < Result < ObjectId , Error > > {
129
- let mut parents = SmallVec :: new ( ) ;
130
106
loop {
131
107
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" ) ;
108
+ let commit = self . graph . get_mut ( & id) . expect ( "it was added to the graph by now" ) ;
109
+ let flags = & mut commit. data . flags ;
133
110
* flags |= Flags :: POPPED ;
134
111
135
112
if !flags. contains ( Flags :: COMMON ) {
@@ -144,15 +121,12 @@ impl<'a> Negotiator for Algorithm<'a> {
144
121
( Some ( id) , Flags :: SEEN )
145
122
} ;
146
123
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 ) ) {
124
+ for parent_id in commit. parents . clone ( ) {
125
+ if self
126
+ . graph
127
+ . get ( & parent_id)
128
+ . map_or ( true , |commit| !commit. data . flags . contains ( Flags :: SEEN ) )
129
+ {
156
130
if let Err ( err) = self . add_to_queue ( parent_id, mark) {
157
131
return Some ( Err ( err) ) ;
158
132
}
@@ -171,7 +145,10 @@ impl<'a> Negotiator for Algorithm<'a> {
171
145
}
172
146
173
147
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 ) ) ;
148
+ let known_to_be_common = self
149
+ . graph
150
+ . get ( & id)
151
+ . map_or ( false , |commit| commit. data . flags . contains ( Flags :: COMMON ) ) ;
175
152
self . mark_common ( id, Mark :: ThisCommitAndAncestors , Ancestors :: DirectUnseen ) ?;
176
153
Ok ( known_to_be_common)
177
154
}
0 commit comments