Skip to content

Commit 757406f

Browse files
Byroncodex
andcommitted
Make ChangeIds mandatory for commits in but_workspace::ui::RefInfo
Co-authored-by: GPT 5.4 <codex@openai.com>
1 parent 361e455 commit 757406f

5 files changed

Lines changed: 56 additions & 14 deletions

File tree

crates/but-core/src/commit.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,15 @@ impl CommitOwned {
528528
inner,
529529
}
530530
}
531+
532+
/// Return the stored change-id if present, or derive a deterministic fallback from the commit id.
533+
pub fn change_id(&self) -> ChangeId {
534+
Headers::try_from_commit(&self.inner)
535+
.unwrap_or_default()
536+
.ensure_change_id(self.id)
537+
.change_id
538+
.expect("change-id is ensured")
539+
}
531540
}
532541

533542
/// Mutations
@@ -604,6 +613,15 @@ impl<'repo> Commit<'repo> {
604613
pub fn headers(&self) -> Option<Headers> {
605614
Headers::try_from_commit(&self.inner)
606615
}
616+
617+
/// Return the stored change-id if present, or derive a deterministic fallback from the commit id.
618+
pub fn change_id(&self) -> ChangeId {
619+
self.headers()
620+
.unwrap_or_default()
621+
.ensure_change_id(self.id.detach())
622+
.change_id
623+
.expect("change-id is ensured")
624+
}
607625
}
608626

609627
/// Conflict specific details

crates/but-workspace/src/branch_details.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,7 @@ fn local_commits_gix(
234234
state: CommitState::LocalAndRemote(info.id),
235235
created_at: i128::from(commit.committer.time.seconds) * 1000,
236236
author,
237-
change_id: commit
238-
.headers()
239-
.and_then(|headers| headers.change_id)
240-
.map(|id| id.to_string()),
237+
change_id: commit.change_id().to_string(),
241238
gerrit_review_url: None,
242239
});
243240
}

crates/but-workspace/src/legacy/stacks.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,11 @@ pub fn local_and_remote_commits(
627627
state,
628628
created_at,
629629
author: gix_commit.author()?.into(),
630-
change_id: change_id.map(|id| id.to_string()),
630+
change_id: change_id
631+
.unwrap_or_else(|| {
632+
but_core::commit::Headers::synthetic_change_id_from_commit_id(*commit_id)
633+
})
634+
.to_string(),
631635
gerrit_review_url: None,
632636
};
633637
local_and_remote.push(api_commit);

crates/but-workspace/src/ui/mod.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,10 @@ pub struct Commit {
108108
pub created_at: i128,
109109
/// The author of the commit.
110110
pub author: Author,
111-
/// The GitButler change-id associated with this commit, if available.
112-
pub change_id: Option<String>,
111+
/// The GitButler change-id associated with this commit.
112+
/// It always exists as we either read it from the [headers][but_core::commit::Headers], or we
113+
/// synthesize one from [the commit id][but_core::commit::Headers::synthetic_change_id_from_commit_id()].
114+
pub change_id: String,
113115
/// Optional URL to the Gerrit review for this commit, if applicable.
114116
/// Only populated if Gerrit mode is enabled and the commit has an associated review.
115117
pub gerrit_review_url: Option<String>,
@@ -123,17 +125,22 @@ impl TryFrom<gix::Commit<'_>> for Commit {
123125
let commit_id = commit.id;
124126
let commit = commit.decode()?;
125127
let headers = but_core::commit::Headers::try_from_commit_headers(|| commit.extra_headers());
128+
let has_conflicts = headers.as_ref().is_some_and(|hdr| hdr.is_conflicted());
129+
let change_id = headers
130+
.unwrap_or_default()
131+
.ensure_change_id(commit_id)
132+
.change_id
133+
.expect("change-id is ensured")
134+
.to_string();
126135
Ok(Commit {
127136
id: commit_id,
128137
parent_ids: commit.parents().collect(),
129138
message: commit.message.to_owned(),
130-
has_conflicts: headers.as_ref().is_some_and(|hdr| hdr.is_conflicted()),
139+
has_conflicts,
131140
state: CommitState::LocalAndRemote(commit_id),
132141
created_at: i128::from(commit.time()?.seconds) * 1000,
133142
author: commit.author()?.into(),
134-
change_id: headers
135-
.and_then(|headers| headers.change_id)
136-
.map(|id| id.to_string()),
143+
change_id,
137144
gerrit_review_url: None,
138145
})
139146
}
@@ -144,8 +151,11 @@ impl From<but_core::CommitOwned> for Commit {
144151
let headers = commit::Headers::try_from_commit(&inner);
145152
let has_conflicts = headers.as_ref().is_some_and(|hdr| hdr.is_conflicted());
146153
let change_id = headers
147-
.and_then(|hdr| hdr.change_id)
148-
.map(|id| id.to_string());
154+
.unwrap_or_default()
155+
.ensure_change_id(id)
156+
.change_id
157+
.expect("change-id is ensured")
158+
.to_string();
149159
let gix::objs::Commit {
150160
tree: _,
151161
parents,
@@ -439,7 +449,12 @@ impl From<&LocalCommit> for ui::Commit {
439449
author: author
440450
.to_ref(&mut gix::date::parse::TimeBuf::default())
441451
.into(),
442-
change_id: change_id.as_ref().map(ToString::to_string),
452+
change_id: change_id
453+
.as_ref()
454+
.map(ToString::to_string)
455+
.unwrap_or_else(|| {
456+
but_core::commit::Headers::synthetic_change_id_from_commit_id(*id).to_string()
457+
}),
443458
gerrit_review_url: None,
444459
}
445460
}

packages/but-sdk/src/generated/index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,12 @@ export type Commit = {
581581
createdAt: number;
582582
/** The author of the commit. */
583583
author: Author;
584+
/**
585+
* The GitButler change-id associated with this commit.
586+
* It always exists as we either read it from the [headers][but_core::commit::Headers], or we
587+
* synthesize one from [the commit id][but_core::commit::Headers::synthetic_change_id_from_commit_id()].
588+
*/
589+
changeId: string;
584590
/**
585591
* Optional URL to the Gerrit review for this commit, if applicable.
586592
* Only populated if Gerrit mode is enabled and the commit has an associated review.
@@ -1489,6 +1495,8 @@ export type UpstreamCommit = {
14891495
createdAt: number;
14901496
/** The author of the commit. */
14911497
author: Author;
1498+
/** The GitButler change-id associated with this commit, if available. */
1499+
changeId?: string | null;
14921500
};
14931501

14941502
/** Git files activity. Supplies the head sha */

0 commit comments

Comments
 (0)