Skip to content

Commit 0cb47b3

Browse files
committed
Replace checkout_tree_ex() with stupid checkout
This affects transaction-time checkout and the various checkouts performed by `stg branch`. This further improves StGit support for sparse checkout worktrees (#195).
1 parent c26867c commit 0cb47b3

File tree

5 files changed

+11
-63
lines changed

5 files changed

+11
-63
lines changed

src/cmd/branch.rs

Lines changed: 8 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
55
use std::io::Write;
66

7-
use anyhow::{anyhow, Context, Result};
7+
use anyhow::{anyhow, Result};
88
use bstr::ByteSlice;
99
use clap::{Arg, ArgMatches};
1010
use termcolor::WriteColor;
1111

1212
use crate::{
1313
argset::{self, get_one_str},
14-
print_info_message, print_warning_message,
14+
print_info_message,
1515
repo::RepositoryExtended,
1616
stack::{get_branch_name, state_refname_from_branch_name, Stack, StackStateAccess},
1717
stupid::Stupid,
@@ -248,12 +248,14 @@ fn run(matches: &ArgMatches) -> Result<()> {
248248
if target_branchname == current_branchname {
249249
Err(anyhow!("{target_branchname} is already the current branch"))
250250
} else {
251+
let stupid = repo.stupid();
252+
let statuses = stupid.statuses(None)?;
251253
if !matches.contains_id("merge") {
252-
let statuses = repo.stupid().statuses(None)?;
253254
statuses.check_worktree_clean()?;
254255
}
256+
statuses.check_conflicts()?;
255257
let target_branch = repo.get_branch(Some(target_branchname))?;
256-
switch_to(matches, &repo, &target_branch)
258+
stupid.checkout(target_branch.name().unwrap().unwrap())
257259
}
258260
} else {
259261
println!("{current_branchname}");
@@ -313,31 +315,6 @@ fn set_stgit_parent(
313315
}
314316
}
315317

316-
fn switch_to(matches: &ArgMatches, repo: &git2::Repository, branch: &git2::Branch) -> Result<()> {
317-
let target_commit = branch.get().peel_to_commit()?;
318-
let branch_refname = branch.get().name().expect("new branch has UTF-8 name");
319-
let mut opts = git2::build::CheckoutBuilder::new();
320-
opts.notify_on(
321-
git2::CheckoutNotificationType::CONFLICT | git2::CheckoutNotificationType::DIRTY,
322-
);
323-
opts.notify(|notification_type, path, _diff0, _diff1, _diff2| {
324-
if let Some(path) = path {
325-
let path_string = path.to_string_lossy();
326-
print_warning_message(matches, &format!("{notification_type:?} {path_string}"));
327-
} else {
328-
print_warning_message(matches, &format!("{notification_type:?}"));
329-
}
330-
true
331-
});
332-
repo.checkout_tree_ex(target_commit.as_object(), Some(&mut opts))?;
333-
repo.set_head(branch_refname)
334-
.with_context(|| format!("switching to `{branch_refname}`"))?;
335-
Ok(())
336-
337-
// let branchname = get_branch_name(branch)?;
338-
// repo.stupid().checkout(&branchname)
339-
}
340-
341318
fn list(repo: git2::Repository, matches: &ArgMatches) -> Result<()> {
342319
let mut branchnames = Vec::new();
343320
for branch_result in repo.branches(Some(git2::BranchType::Local))? {
@@ -503,7 +480,7 @@ fn create(repo: git2::Repository, matches: &ArgMatches) -> Result<()> {
503480
}
504481
}
505482

506-
match switch_to(matches, &repo, &new_branch) {
483+
match stupid.checkout(new_branch.name().unwrap().unwrap()) {
507484
Ok(()) => Ok(()),
508485
Err(e) => {
509486
new_branch.delete()?;
@@ -561,8 +538,7 @@ fn clone(repo: git2::Repository, matches: &ArgMatches) -> Result<()> {
561538
)?;
562539

563540
let new_branch = repo.get_branch(Some(&new_branchname))?;
564-
565-
switch_to(matches, &repo, &new_branch)
541+
stupid.checkout(new_branch.name().unwrap().unwrap())
566542
}
567543

568544
fn rename(repo: git2::Repository, matches: &ArgMatches) -> Result<()> {

src/repo.rs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
55
use anyhow::{anyhow, Context, Result};
66

7-
use crate::stack::Error;
8-
97
/// Extends [`git2::Repository`] with additional methods.
108
pub(crate) trait RepositoryExtended {
119
/// Determine whether the repository is in a clean state.
@@ -18,13 +16,6 @@ pub(crate) trait RepositoryExtended {
1816
///
1917
/// Gets the current branch if the provided `branch_name` is `None`,
2018
fn get_branch(&self, branch_name: Option<&str>) -> Result<git2::Branch<'_>>;
21-
22-
/// [`git2::Repository::checkout_tree()`] with StGit-specfic error mapping.
23-
fn checkout_tree_ex(
24-
&self,
25-
treeish: &git2::Object<'_>,
26-
opts: Option<&mut git2::build::CheckoutBuilder<'_>>,
27-
) -> Result<()>;
2819
}
2920

3021
impl RepositoryExtended for git2::Repository {
@@ -91,20 +82,4 @@ impl RepositoryExtended for git2::Repository {
9182
}
9283
}
9384
}
94-
95-
fn checkout_tree_ex(
96-
&self,
97-
treeish: &git2::Object<'_>,
98-
opts: Option<&mut git2::build::CheckoutBuilder<'_>>,
99-
) -> Result<()> {
100-
self.checkout_tree(treeish, opts)
101-
.map_err(|e| -> anyhow::Error {
102-
if e.class() == git2::ErrorClass::Checkout && e.code() == git2::ErrorCode::Conflict
103-
{
104-
Error::CheckoutConflicts(e.message().to_string()).into()
105-
} else {
106-
e.into()
107-
}
108-
})
109-
}
11085
}

src/stack/transaction.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ use crate::{
3838
commit::{CommitExtended, RepositoryCommitExtended},
3939
index::TemporaryIndex,
4040
patchname::PatchName,
41-
repo::RepositoryExtended,
4241
signature::SignatureExtended,
4342
stack::{PatchState, Stack, StackStateAccess},
4443
stupid::Stupid,
@@ -441,9 +440,7 @@ impl<'repo> StackTransaction<'repo> {
441440
}
442441

443442
if self.options.discard_changes {
444-
let mut checkout_builder = git2::build::CheckoutBuilder::new();
445-
checkout_builder.force();
446-
repo.checkout_tree_ex(commit.as_object(), Some(&mut checkout_builder))?;
443+
stupid.read_tree_checkout_hard(commit.tree_id())?;
447444
} else {
448445
stupid.update_index_refresh()?;
449446
stupid

src/stupid/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ impl<'repo, 'index> StupidContext<'repo, 'index> {
343343
}
344344

345345
/// Checkout a branch.
346-
pub(crate) fn _checkout(&self, branch_name: &str) -> Result<()> {
346+
pub(crate) fn checkout(&self, branch_name: &str) -> Result<()> {
347347
self.git()
348348
.arg("checkout")
349349
.arg(branch_name)

t/t1000-branch-create.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ test_expect_success \
143143

144144
test_expect_success \
145145
'Create branch down the stack, behind the conflict caused by the generated file' '
146-
conflict stg branch --create foo4 master^
146+
command_error stg branch --create foo4 master^
147147
'
148148

149149
test_expect_success \

0 commit comments

Comments
 (0)