1
- use crate :: CommitIndex ;
1
+ use crate :: { CommitIndex , SegmentIndex } ;
2
2
use bitflags:: bitflags;
3
3
use gix:: bstr:: BString ;
4
- use std:: ops:: { Deref , DerefMut } ;
5
4
6
5
/// A commit with must useful information extracted from the Git commit itself.
7
6
///
@@ -21,12 +20,21 @@ pub struct Commit {
21
20
pub refs : Vec < gix:: refs:: FullName > ,
22
21
/// Additional properties to help classify this commit.
23
22
pub flags : CommitFlags ,
24
- // TODO: bring has_conflict: bool here, then remove `RemoteCommit` type.
23
+ /// Whether the commit is in a conflicted state, a GitButler concept.
24
+ /// GitButler will perform rebasing/reordering etc. without interruptions and flag commits as conflicted if needed.
25
+ /// Conflicts are resolved via the Edit Mode mechanism.
26
+ ///
27
+ /// Note that even though GitButler won't push branches with conflicts, the user can still push such branches at will.
28
+ pub has_conflicts : bool ,
25
29
}
26
30
27
31
impl Commit {
28
32
/// Read the object of the `commit_id` and extract relevant values, while setting `flags` as well.
29
- pub fn new_from_id ( commit_id : gix:: Id < ' _ > , flags : CommitFlags ) -> anyhow:: Result < Self > {
33
+ pub fn new_from_id (
34
+ commit_id : gix:: Id < ' _ > ,
35
+ flags : CommitFlags ,
36
+ has_conflicts : bool ,
37
+ ) -> anyhow:: Result < Self > {
30
38
let commit = commit_id. object ( ) ?. into_commit ( ) ;
31
39
// Decode efficiently, no need to own this.
32
40
let commit = commit. decode ( ) ?;
@@ -37,6 +45,7 @@ impl Commit {
37
45
author : commit. author . to_owned ( ) ?,
38
46
refs : Vec :: new ( ) ,
39
47
flags,
48
+ has_conflicts,
40
49
} )
41
50
}
42
51
}
@@ -66,6 +75,7 @@ impl From<but_core::Commit<'_>> for Commit {
66
75
author : value. inner . author ,
67
76
refs : Vec :: new ( ) ,
68
77
flags : CommitFlags :: empty ( ) ,
78
+ has_conflicts : false ,
69
79
}
70
80
}
71
81
}
@@ -109,152 +119,6 @@ impl CommitFlags {
109
119
}
110
120
}
111
121
112
- /// A commit that is reachable through the *local tracking branch*, with additional, computed information.
113
- #[ derive( Clone , Eq , PartialEq ) ]
114
- pub struct LocalCommit {
115
- /// The simple commit.
116
- pub inner : Commit ,
117
- /// Provide additional information on how this commit relates to other points of reference, like its remote branch,
118
- /// or the target branch to integrate with.
119
- pub relation : LocalCommitRelation ,
120
- /// Whether the commit is in a conflicted state, a GitButler concept.
121
- /// GitButler will perform rebasing/reordering etc. without interruptions and flag commits as conflicted if needed.
122
- /// Conflicts are resolved via the Edit Mode mechanism.
123
- ///
124
- /// Note that even though GitButler won't push branches with conflicts, the user can still push such branches at will.
125
- pub has_conflicts : bool ,
126
- }
127
-
128
- impl std:: fmt:: Debug for LocalCommit {
129
- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
130
- let refs = self
131
- . refs
132
- . iter ( )
133
- . map ( |rn| format ! ( "►{}" , rn. shorten( ) ) )
134
- . collect :: < Vec < _ > > ( )
135
- . join ( ", " ) ;
136
- write ! (
137
- f,
138
- "LocalCommit({conflict}{hash}, {msg:?}, {relation}{refs})" ,
139
- conflict = if self . has_conflicts { "💥" } else { "" } ,
140
- hash = self . id. to_hex_with_len( 7 ) ,
141
- msg = self . message,
142
- relation = self . relation. display( self . id) ,
143
- refs = if refs. is_empty( ) {
144
- "" . to_string( )
145
- } else {
146
- format!( ", {refs}" )
147
- }
148
- )
149
- }
150
- }
151
-
152
- impl LocalCommit {
153
- /// Create a new branch-commit, along with default values for the non-commit fields.
154
- // TODO: remove this function once ref_info code doesn't need it anymore (i.e. mapping is implemented).
155
- pub fn new_from_id ( value : gix:: Id < ' _ > , flags : CommitFlags ) -> anyhow:: Result < Self > {
156
- Ok ( LocalCommit {
157
- inner : Commit :: new_from_id ( value, flags) ?,
158
- relation : LocalCommitRelation :: LocalOnly ,
159
- has_conflicts : false ,
160
- } )
161
- }
162
- }
163
-
164
- /// The state of the [local commit](LocalCommit) in relation to its remote tracking branch or its integration branch.
165
- #[ derive( Default , Debug , Eq , PartialEq , Clone , Copy ) ]
166
- pub enum LocalCommitRelation {
167
- /// The commit is only local
168
- #[ default]
169
- LocalOnly ,
170
- /// The commit is also present in the remote tracking branch.
171
- ///
172
- /// This is the case if:
173
- /// - The commit has been pushed to the remote
174
- /// - The commit has been copied from a remote commit (when applying a remote branch)
175
- ///
176
- /// This variant carries the remote commit id.
177
- /// The `remote_commit_id` may be the same as the `id` or it may be different if the local commit has been rebased
178
- /// or updated in another way.
179
- LocalAndRemote ( gix:: ObjectId ) ,
180
- /// The commit is considered integrated.
181
- /// This should happen when the commit or the contents of this commit is already part of the base.
182
- Integrated ,
183
- }
184
-
185
- impl LocalCommitRelation {
186
- /// Convert this relation into something displaying, mainly for debugging.
187
- pub fn display ( & self , id : gix:: ObjectId ) -> & ' static str {
188
- match self {
189
- LocalCommitRelation :: LocalOnly => "local" ,
190
- LocalCommitRelation :: LocalAndRemote ( remote_id) => {
191
- if * remote_id == id {
192
- "local/remote(identity)"
193
- } else {
194
- "local/remote(similarity)"
195
- }
196
- }
197
- LocalCommitRelation :: Integrated => "integrated" ,
198
- }
199
- }
200
- }
201
-
202
- impl Deref for LocalCommit {
203
- type Target = Commit ;
204
-
205
- fn deref ( & self ) -> & Self :: Target {
206
- & self . inner
207
- }
208
- }
209
-
210
- impl DerefMut for LocalCommit {
211
- fn deref_mut ( & mut self ) -> & mut Self :: Target {
212
- & mut self . inner
213
- }
214
- }
215
-
216
- /// A commit that is reachable only through the *remote tracking branch*, with additional, computed information.
217
- ///
218
- /// TODO: Remote commits can also be integrated, without the local branch being all caught up. Currently we can't represent that.
219
- #[ derive( Clone , Eq , PartialEq ) ]
220
- pub struct RemoteCommit {
221
- /// The simple commit.
222
- pub inner : Commit ,
223
- /// Whether the commit is in a conflicted state, a GitButler concept.
224
- /// GitButler will perform rebasing/reordering etc. without interruptions and flag commits as conflicted if needed.
225
- /// Conflicts are resolved via the Edit Mode mechanism.
226
- ///
227
- /// Note that even though GitButler won't push branches with conflicts, the user can still push such branches at will.
228
- /// For remote commits, this only happens if someone manually pushed them.
229
- pub has_conflicts : bool ,
230
- }
231
-
232
- impl std:: fmt:: Debug for RemoteCommit {
233
- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
234
- write ! (
235
- f,
236
- "RemoteCommit({conflict}{hash}, {msg:?}" ,
237
- conflict = if self . has_conflicts { "💥" } else { "" } ,
238
- hash = self . id. to_hex_with_len( 7 ) ,
239
- msg = self . message,
240
- )
241
- }
242
- }
243
-
244
- impl Deref for RemoteCommit {
245
- type Target = Commit ;
246
-
247
- fn deref ( & self ) -> & Self :: Target {
248
- & self . inner
249
- }
250
- }
251
-
252
- impl DerefMut for RemoteCommit {
253
- fn deref_mut ( & mut self ) -> & mut Self :: Target {
254
- & mut self . inner
255
- }
256
- }
257
-
258
122
/// A segment of a commit graph, representing a set of commits exclusively.
259
123
#[ derive( Default , Clone , Eq , PartialEq ) ]
260
124
pub struct Segment {
@@ -269,24 +133,15 @@ pub struct Segment {
269
133
pub ref_name : Option < gix:: refs:: FullName > ,
270
134
/// An ID which can uniquely identify this segment among all segments within the graph that owned it.
271
135
/// Note that it's not suitable to permanently identify the segment, so should not be persisted.
272
- pub id : usize ,
136
+ pub id : SegmentIndex ,
273
137
/// The name of the remote tracking branch of this segment, if present, i.e. `refs/remotes/origin/main`.
274
138
/// Its presence means that a remote is configured and that the stack content
275
139
pub remote_tracking_ref_name : Option < gix:: refs:: FullName > ,
276
140
/// The portion of commits that can be reached from the tip of the *branch* downwards, so that they are unique
277
141
/// for that stack segment and not included in any other stack or stack segment.
278
142
///
279
143
/// The list could be empty for when this is a dedicated empty segment as insertion position of commits.
280
- pub commits : Vec < LocalCommit > ,
281
- /// Commits that are reachable from the remote-tracking branch associated with this branch,
282
- /// but are not reachable from this branch or duplicated by a commit in it.
283
- /// Note that commits that are also similar to commits in `commits` are pruned, and not present here.
284
- ///
285
- /// Note that remote commits along with their remote tracking branch should always retain a shared history
286
- /// with the local tracking branch. If these diverge, we can represent this in data, but currently there is
287
- /// no derived value to make this visible explicitly.
288
- // TODO: remove this in favor of having a UI-only variant of the segment that contains these.
289
- pub commits_unique_in_remote_tracking_branch : Vec < RemoteCommit > ,
144
+ pub commits : Vec < Commit > ,
290
145
/// Read-only metadata with additional information, or `None` if nothing was present.
291
146
pub metadata : Option < SegmentMetadata > ,
292
147
}
@@ -347,7 +202,6 @@ impl std::fmt::Debug for Segment {
347
202
ref_name,
348
203
id,
349
204
commits,
350
- commits_unique_in_remote_tracking_branch,
351
205
remote_tracking_ref_name,
352
206
metadata,
353
207
} = self ;
@@ -368,10 +222,6 @@ impl std::fmt::Debug for Segment {
368
222
} ,
369
223
)
370
224
. field ( "commits" , & commits)
371
- . field (
372
- "commits_unique_in_remote_tracking_branch" ,
373
- & commits_unique_in_remote_tracking_branch,
374
- )
375
225
. field (
376
226
"metadata" ,
377
227
match metadata {
0 commit comments