Skip to content

Commit 11f4357

Browse files
committed
feat: Add support for git worktrees
1 parent 72f0458 commit 11f4357

6 files changed

Lines changed: 140 additions & 20 deletions

File tree

src/lib.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -115,32 +115,40 @@ pub fn run(config: Arc<Config>, args: &cli::Args, term: &mut Term) -> Res<()> {
115115

116116
fn open_repo(dir: &Path) -> Res<Repository> {
117117
log::debug!("Opening repo");
118-
let repo = open_repo_from_env()?;
118+
let mut repo = Repository::open(dir).map_err(Error::OpenRepo)?;
119+
120+
if repo.is_worktree() {
121+
repo = Repository::open(repo.commondir()).map_err(Error::OpenRepo)?;
122+
}
123+
119124
repo.set_workdir(dir, false).map_err(Error::OpenRepo)?;
120125
Ok(repo)
121126
}
122127

123128
fn find_git_dir() -> Res<PathBuf> {
124129
log::debug!("Finding git dir");
130+
131+
let output = Command::new("git")
132+
.args(["rev-parse", "--show-toplevel"])
133+
.output()
134+
.map_err(Error::FindGitDir)?;
135+
136+
let status = output.status;
137+
138+
if !status.success() {
139+
return Err(Error::CmdBadExit(
140+
String::from_utf8(output.stderr).unwrap(),
141+
status.code(),
142+
));
143+
};
144+
125145
let dir = PathBuf::from(
126-
String::from_utf8(
127-
Command::new("git")
128-
.args(["rev-parse", "--show-toplevel"])
129-
.output()
130-
.map_err(Error::FindGitDir)?
131-
.stdout,
132-
)
133-
.map_err(Error::GitDirUtf8)?
134-
.trim_end(),
146+
String::from_utf8(output.stdout)
147+
.map_err(Error::GitDirUtf8)?
148+
.trim_end(),
135149
);
136-
Ok(dir)
137-
}
138150

139-
fn open_repo_from_env() -> Res<Repository> {
140-
match Repository::open_from_env() {
141-
Ok(repo) => Ok(repo),
142-
Err(err) => Err(Error::OpenRepo(err)),
143-
}
151+
Ok(dir)
144152
}
145153

146154
fn keys_to_events(keys: &[(KeyModifiers, KeyCode)]) -> Vec<Event> {

src/tests/helpers/ui.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ use crate::{
44
config::{self, Config},
55
error::Error,
66
key_parser::parse_test_keys,
7+
open_repo,
78
term::{Term, TermBackend},
89
tests::helpers::RepoTestContext,
910
};
1011
use crossterm::event::{Event, KeyEvent, KeyModifiers, MouseButton, MouseEventKind};
11-
use git2::Repository;
1212
use ratatui::{Terminal, backend::TestBackend, layout::Size};
1313
use regex::Regex;
14-
use std::{path::PathBuf, rc::Rc, sync::Arc, time::Duration};
14+
use std::path::PathBuf;
15+
use std::{rc::Rc, sync::Arc, time::Duration};
1516

1617
use self::buffer::TestBuffer;
1718

@@ -69,7 +70,7 @@ impl TestContext {
6970

7071
pub fn init_app_at_path(&mut self, path: PathBuf) -> App {
7172
let mut app = App::create(
72-
Rc::new(Repository::open(path).unwrap()),
73+
Rc::new(open_repo(&path).unwrap()),
7374
self.size,
7475
&Args::default(),
7576
Arc::clone(&self.config),

src/tests/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,42 @@ fn inside_submodule() {
412412
insta::assert_snapshot!(ctx.redact_buffer());
413413
}
414414

415+
#[test]
416+
fn inside_shallow() {
417+
let mut ctx = setup_clone!();
418+
let url = Url::from_file_path(&ctx.remote_dir).unwrap().to_string();
419+
run(&ctx.dir, &["git", "clone", "--depth=1", &url, "shallow"]);
420+
421+
let _app = ctx.init_app_at_path(ctx.dir.join("shallow"));
422+
insta::assert_snapshot!(ctx.redact_buffer());
423+
}
424+
425+
#[test]
426+
fn inside_worktree() {
427+
let mut ctx = setup_clone!();
428+
run(&ctx.dir, &["git", "checkout", "-b", "new-branch"]);
429+
run(&ctx.dir, &["git", "worktree", "add", "main"]);
430+
431+
let _app = ctx.init_app_at_path(ctx.dir.join("main"));
432+
insta::assert_snapshot!(ctx.redact_buffer());
433+
}
434+
435+
#[test]
436+
fn inside_shallow_worktree() {
437+
let mut ctx = setup_clone!();
438+
clone_and_commit(&ctx.remote_dir, "new-file", "hello");
439+
440+
let url = Url::from_file_path(&ctx.remote_dir).unwrap().to_string();
441+
run(&ctx.dir, &["git", "clone", "--depth=1", &url, "shallow"]);
442+
443+
let shallow_dir = ctx.dir.join("shallow");
444+
run(&shallow_dir, &["git", "checkout", "-b", "new-branch"]);
445+
run(&shallow_dir, &["git", "worktree", "add", "main"]);
446+
447+
let _app = ctx.init_app_at_path(shallow_dir.join("main"));
448+
insta::assert_snapshot!(ctx.redact_buffer());
449+
}
450+
415451
#[test]
416452
fn syntax_highlighted() {
417453
let ctx = setup_clone!();
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
source: src/tests/mod.rs
3+
expression: ctx.redact_buffer()
4+
---
5+
On branch main |
6+
Your branch is up to date with 'origin/main'. |
7+
|
8+
Recent commits |
9+
b66a0bf main origin/main add initial-file |
10+
|
11+
|
12+
|
13+
|
14+
|
15+
|
16+
|
17+
|
18+
|
19+
|
20+
|
21+
|
22+
|
23+
|
24+
|
25+
styles_hash: f47a6512af0aca26
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
source: src/tests/mod.rs
3+
expression: ctx.redact_buffer()
4+
---
5+
On branch main |
6+
Your branch is up to date with 'origin/main'. |
7+
|
8+
Recent commits |
9+
46c81ca main new-branch origin/main add new-file |
10+
|
11+
|
12+
|
13+
|
14+
|
15+
|
16+
|
17+
|
18+
|
19+
|
20+
|
21+
|
22+
|
23+
|
24+
|
25+
styles_hash: 4d5a9a1a08dc1d60
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
source: src/tests/mod.rs
3+
expression: ctx.redact_buffer()
4+
---
5+
On branch main |
6+
Your branch is up to date with 'origin/main'. |
7+
|
8+
Recent commits |
9+
b66a0bf main new-branch origin/main add initial-file |
10+
|
11+
|
12+
|
13+
|
14+
|
15+
|
16+
|
17+
|
18+
|
19+
|
20+
|
21+
|
22+
|
23+
|
24+
|
25+
styles_hash: 4d5a9a1a08dc1d60

0 commit comments

Comments
 (0)