Skip to content

Commit 79c7e72

Browse files
committed
fix but restore failing for old snapshots
1 parent 550d2f1 commit 79c7e72

File tree

3 files changed

+46
-20
lines changed

3 files changed

+46
-20
lines changed

crates/but-api/src/commands/oplog.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ pub fn list_snapshots(
6161
Ok(snapshots)
6262
}
6363

64+
/// Gets a specific snapshot by its commit SHA.
65+
///
66+
/// - `project_id`: The ID of the project to get the snapshot for.
67+
/// - `sha`: The SHA of the snapshot to retrieve.
68+
///
69+
/// Returns the `Snapshot` corresponding to the provided SHA.
70+
///
71+
/// # Errors
72+
/// Returns an error if the project cannot be found, if the snapshot SHA is invalid, or if the underlying commit is not a valid snapshot commit
73+
#[api_cmd]
74+
#[cfg_attr(feature = "tauri", tauri::command(async))]
75+
#[instrument(err(Debug))]
76+
pub fn get_snapshot(project_id: ProjectId, sha: String) -> Result<Snapshot, Error> {
77+
let project = gitbutler_project::get(project_id).context("failed to get project")?;
78+
let ctx = CommandContext::open(&project, AppSettings::load_from_default_path_creating()?)?;
79+
let snapshot = ctx.get_snapshot(sha.parse().map_err(anyhow::Error::from)?)?;
80+
Ok(snapshot)
81+
}
82+
6483
/// Creates a new, on-demand snapshot in the oplog.
6584
///
6685
/// - `project_id`: The ID of the project to create a snapshot for.

crates/but/src/oplog.rs

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,27 +128,11 @@ pub(crate) fn restore_to_oplog(
128128
oplog_sha: &str,
129129
force: bool,
130130
) -> anyhow::Result<()> {
131-
let snapshots = but_api::oplog::list_snapshots(project.id, 1000, None, None)?;
131+
let repo = project.open()?;
132+
let commit_id = repo.rev_parse_single(oplog_sha)?.detach();
133+
let target_snapshot = &but_api::oplog::get_snapshot(project.id, commit_id.to_string())?;
132134

133-
// Parse the oplog SHA (support partial SHAs)
134-
let commit_sha_string = if oplog_sha.len() >= 7 {
135-
// Try to find a snapshot that starts with this SHA
136-
137-
let matching_snapshot = snapshots
138-
.iter()
139-
.find(|snapshot| snapshot.commit_id.to_string().starts_with(oplog_sha))
140-
.ok_or_else(|| anyhow::anyhow!("No oplog snapshot found matching '{}'", oplog_sha))?;
141-
142-
matching_snapshot.commit_id.to_string()
143-
} else {
144-
anyhow::bail!("Oplog SHA must be at least 7 characters long");
145-
};
146-
147-
// Get information about the target snapshot
148-
let target_snapshot = snapshots
149-
.iter()
150-
.find(|snapshot| snapshot.commit_id.to_string() == commit_sha_string)
151-
.ok_or_else(|| anyhow::anyhow!("Snapshot {} not found in oplog", commit_sha_string))?;
135+
let commit_sha_string = commit_id.to_string();
152136

153137
let target_operation = target_snapshot
154138
.details

crates/gitbutler-oplog/src/oplog.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ pub trait OplogExt {
141141
/// This is useful to show what has changed in this particular snapshot
142142
fn snapshot_diff(&self, sha: git2::Oid) -> Result<Vec<TreeChange>>;
143143

144+
/// Gets a specific snapshot by its commit sha.
145+
fn get_snapshot(&self, sha: git2::Oid) -> Result<Snapshot>;
146+
144147
/// Gets the sha of the last snapshot commit if present.
145148
fn oplog_head(&self) -> Result<Option<git2::Oid>>;
146149
}
@@ -169,6 +172,26 @@ impl OplogExt for CommandContext {
169172
commit_snapshot(self.project(), tree_id, details, perm)
170173
}
171174

175+
#[instrument(skip(self), err(Debug))]
176+
fn get_snapshot(&self, sha: git2::Oid) -> Result<Snapshot> {
177+
let repo = self.project().open_for_merging()?;
178+
let commit = repo.find_commit(sha.to_gix())?;
179+
let commit_time = gix_time_to_git2(commit.time()?);
180+
let details = commit
181+
.message_raw()?
182+
.to_str()
183+
.ok()
184+
.and_then(|msg| SnapshotDetails::from_str(msg).ok())
185+
.ok_or(anyhow!("Commit is not a snapshot"))?;
186+
187+
let snapshot = Snapshot {
188+
commit_id: sha,
189+
created_at: commit_time,
190+
details: Some(details),
191+
};
192+
Ok(snapshot)
193+
}
194+
172195
#[instrument(skip(self), err(Debug))]
173196
fn list_snapshots(
174197
&self,

0 commit comments

Comments
 (0)