gitui-org / gitui-org/gitui

Log tab panics and aborts the process when the cwd has been deleted (gix discovery reads the process cwd)

オープン
#3,017 コメント 1 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Rust
スター
22.5k
フォーク
774
PR マージ指標
30日以内にマージされた PR はありません

説明

## Summary

Any operation that leaves the process cwd deleted makes the unfiltered Log tab panic, and the panic aborts the whole process rather than just the log thread. The most reachable way in is stashing untracked files from inside a subdirectory, since libgit2 removes that directory as part of the stash.

```
thread panicked at asyncgit/src/revlog.rs:186:14:
failed to fetch: Gix(Discover(Discover(CurrentDir(Os { code: 2, kind: NotFound, message: "No such file or directory" }))))
Rayon: detected unexpected panic; aborting
```

## Why the repo path cannot fix it

`gix` discovery reads the process cwd unconditionally, before it looks at the path it was given:

- `gix/src/discover.rs:45` in `discover_opts`: `options.current_dir = Some(gix_fs::current_dir(false).map_err(upwards::Error::CurrentDir)?);`
- `gix-fs/src/lib.rs:56`: `let cwd = std::env::current_dir()?;`

So passing an absolute repository root does not help. I reproduced it with an explicit absolute path, and again with `RepoPath::resolve_root()` applied exactly as `src/main.rs` does at startup. Identical panic both times.

The entry point is `gix_repo()` at `asyncgit/src/sync/repository.rs:89`, reached from `AsyncLog::fetch_helper_without_filter` at `asyncgit/src/revlog.rs:266`, whose error is `.expect("failed to fetch")` at `revlog.rs:186`.

## Why git2 paths survive

`repo()` at `asyncgit/src/sync/repository.rs:82` uses `git2::Repository::open_ext`, which does not consult the cwd for an absolute path. That is why `get_stashes` and the filtered log keep working while the unfiltered log dies. In other words this only fires when no commit filter is active.

## Reproduction

A scratch crate linking `asyncgit`: create a repo, add an untracked subdirectory, set the process cwd inside it, `stash_save(..., untracked=true)`, then call `AsyncLog::fetch`.

```
[after stash] cwd=Err(Os { code: 2, kind: NotFound })
[git2 get_stashes] OK, 1 stashes
[gix discover] ERR on "/tmp/.../scratch": Discover(CurrentDir(Os { code: 2, kind: NotFound }))
panicked at asyncgit/src/revlog.rs:186: failed to fetch: Gix(Discover(...))
```

## Possible directions

Either set the process cwd to the repository root at startup, or build `discover_opts` with `upwards::Options::current_dir` set explicitly rather than letting gix read the environment. Separately, `revlog.rs:186` turning a fetch error into `.expect` is what escalates this from a broken tab to an aborted process, so that is worth handling regardless of the cwd question.

Filed at the request of a reviewer on #3015, which fixes the git2 half of the same scenario. This one is independent of that change.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

asyncgit/src/revlog.rs の 186 行目と 266 行目付近を読み、次に asyncgit/src/sync/repository.rs の 82 行目と 89 行目付近を読んでください。issue に記載された cwd が削除されたシナリオを再現し、gix の discovery failure を追跡してください。それを存続する git2 のパスと比較してください。cwd が削除されてもフィルタリングされていない Log タブがプロセスを中断せず、fetch failure が panic なしで処理されれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
git, rust
領域
cli
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
活発
明瞭さ
おおむね明確
初心者へのやさしさ
58/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。