|
1 | 1 | use std::{path::PathBuf, vec};
|
2 | 2 |
|
3 | 3 | use anyhow::{anyhow, Context, Result};
|
4 |
| -use bstr::ByteSlice; |
5 |
| -use gitbutler_branch::BranchCreateRequest; |
6 | 4 | use gitbutler_branch::{self, GITBUTLER_WORKSPACE_REFERENCE};
|
7 | 5 | use gitbutler_cherry_pick::RepositoryExt as _;
|
8 | 6 | use gitbutler_command_context::CommandContext;
|
9 |
| -use gitbutler_commit::commit_ext::CommitExt; |
10 | 7 | use gitbutler_error::error::Marker;
|
11 | 8 | use gitbutler_operating_modes::OPEN_WORKSPACE_REFS;
|
12 |
| -use gitbutler_oxidize::{git2_to_gix_object_id, gix_to_git2_oid, GixRepositoryExt, RepoExt}; |
| 9 | +use gitbutler_oxidize::{git2_to_gix_object_id, gix_to_git2_oid, GixRepositoryExt, RepoExt as _}; |
13 | 10 | use gitbutler_project::access::WorktreeWritePermission;
|
14 |
| -use gitbutler_repo::logging::{LogUntil, RepositoryExt as _}; |
15 |
| -use gitbutler_repo::RepositoryExt; |
16 | 11 | use gitbutler_repo::SignaturePurpose;
|
17 | 12 | use gitbutler_stack::{Stack, VirtualBranchesHandle};
|
18 | 13 | use tracing::instrument;
|
19 | 14 |
|
20 |
| -use crate::{branch_manager::BranchManagerExt, VirtualBranchesExt}; |
| 15 | +use crate::{workspace_commit::resolve_commits_above, VirtualBranchesExt}; |
21 | 16 |
|
22 | 17 | const WORKSPACE_HEAD: &str = "Workspace Head";
|
23 |
| -const GITBUTLER_INTEGRATION_COMMIT_TITLE: &str = "GitButler Integration Commit"; |
| 18 | +pub const GITBUTLER_INTEGRATION_COMMIT_TITLE: &str = "GitButler Integration Commit"; |
24 | 19 | pub const GITBUTLER_WORKSPACE_COMMIT_TITLE: &str = "GitButler Workspace Commit";
|
25 | 20 |
|
26 | 21 | /// Creates and returns a merge commit of all active branch heads.
|
@@ -287,7 +282,7 @@ pub fn update_workspace_commit(
|
287 | 282 | pub fn verify_branch(ctx: &CommandContext, perm: &mut WorktreeWritePermission) -> Result<()> {
|
288 | 283 | verify_current_branch_name(ctx)
|
289 | 284 | .and_then(verify_head_is_set)
|
290 |
| - .and_then(|()| verify_head_is_clean(ctx, perm)) |
| 285 | + .and_then(|()| resolve_commits_above(ctx, perm)) |
291 | 286 | .context(Marker::VerificationFailure)?;
|
292 | 287 | Ok(())
|
293 | 288 | }
|
@@ -317,106 +312,6 @@ fn verify_current_branch_name(ctx: &CommandContext) -> Result<&CommandContext> {
|
317 | 312 | }
|
318 | 313 | }
|
319 | 314 |
|
320 |
| -// TODO(ST): Probably there should not be an implicit vbranch creation here. |
321 |
| -fn verify_head_is_clean(ctx: &CommandContext, perm: &mut WorktreeWritePermission) -> Result<()> { |
322 |
| - let head_commit = ctx |
323 |
| - .repo() |
324 |
| - .head() |
325 |
| - .context("failed to get head")? |
326 |
| - .peel_to_commit() |
327 |
| - .context("failed to peel to commit")?; |
328 |
| - |
329 |
| - let vb_handle = VirtualBranchesHandle::new(ctx.project().gb_dir()); |
330 |
| - let default_target = vb_handle |
331 |
| - .get_default_target() |
332 |
| - .context("failed to get default target")?; |
333 |
| - |
334 |
| - let commits = ctx |
335 |
| - .repo() |
336 |
| - .log( |
337 |
| - head_commit.id(), |
338 |
| - LogUntil::Commit(default_target.sha), |
339 |
| - false, |
340 |
| - ) |
341 |
| - .context("failed to get log")?; |
342 |
| - |
343 |
| - let workspace_index = commits |
344 |
| - .iter() |
345 |
| - .position(|commit| { |
346 |
| - commit.message().is_some_and(|message| { |
347 |
| - message.starts_with(GITBUTLER_WORKSPACE_COMMIT_TITLE) |
348 |
| - || message.starts_with(GITBUTLER_INTEGRATION_COMMIT_TITLE) |
349 |
| - }) |
350 |
| - }) |
351 |
| - .context("GitButler workspace commit not found")?; |
352 |
| - let workspace_commit = &commits[workspace_index]; |
353 |
| - let mut extra_commits = commits[..workspace_index].to_vec(); |
354 |
| - extra_commits.reverse(); |
355 |
| - |
356 |
| - if extra_commits.is_empty() { |
357 |
| - // no extra commits found, so we're good |
358 |
| - return Ok(()); |
359 |
| - } |
360 |
| - |
361 |
| - ctx.repo() |
362 |
| - .reset(workspace_commit.as_object(), git2::ResetType::Soft, None) |
363 |
| - .context("failed to reset to workspace commit")?; |
364 |
| - |
365 |
| - let branch_manager = ctx.branch_manager(); |
366 |
| - let mut new_branch = branch_manager |
367 |
| - .create_virtual_branch( |
368 |
| - &BranchCreateRequest { |
369 |
| - name: extra_commits |
370 |
| - .last() |
371 |
| - .map(|commit| commit.message_bstr().to_string()), |
372 |
| - ..Default::default() |
373 |
| - }, |
374 |
| - perm, |
375 |
| - ) |
376 |
| - .context("failed to create virtual branch")?; |
377 |
| - |
378 |
| - // rebasing the extra commits onto the new branch |
379 |
| - let gix_repo = ctx.repo().to_gix()?; |
380 |
| - let mut head = new_branch.head(&gix_repo)?; |
381 |
| - for commit in extra_commits { |
382 |
| - let new_branch_head = ctx |
383 |
| - .repo() |
384 |
| - .find_commit(head) |
385 |
| - .context("failed to find new branch head")?; |
386 |
| - |
387 |
| - let rebased_commit_oid = ctx |
388 |
| - .repo() |
389 |
| - .commit_with_signature( |
390 |
| - None, |
391 |
| - &commit.author(), |
392 |
| - &commit.committer(), |
393 |
| - &commit.message_bstr().to_str_lossy(), |
394 |
| - &commit.tree().unwrap(), |
395 |
| - &[&new_branch_head], |
396 |
| - None, |
397 |
| - ) |
398 |
| - .context(format!( |
399 |
| - "failed to rebase commit {} onto new branch", |
400 |
| - commit.id() |
401 |
| - ))?; |
402 |
| - |
403 |
| - let rebased_commit = ctx.repo().find_commit(rebased_commit_oid).context(format!( |
404 |
| - "failed to find rebased commit {}", |
405 |
| - rebased_commit_oid |
406 |
| - ))?; |
407 |
| - |
408 |
| - new_branch.set_stack_head( |
409 |
| - &vb_handle, |
410 |
| - &gix_repo, |
411 |
| - rebased_commit.id(), |
412 |
| - Some(rebased_commit.tree_id()), |
413 |
| - )?; |
414 |
| - |
415 |
| - head = rebased_commit.id(); |
416 |
| - } |
417 |
| - Ok(()) |
418 |
| -} |
419 |
| - |
420 | 315 | fn invalid_head_err(head_name: &str) -> anyhow::Error {
|
421 | 316 | anyhow!(
|
422 | 317 | "project is on {head_name}. Please checkout {} to continue",
|
|
0 commit comments