Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/commands/worktree/switch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,11 @@ use crate::output::{

/// Result of resolving the switch target.
struct ResolvedTarget {
/// The branch to switch to, carrying whether anything rewrote the token
/// the user typed — `pr:`/`mr:` dispatch and the remote-prefix strip both
/// do, and a rewritten token is no longer a path worth trying.
/// The branch to switch to, carrying whether the token may still be tried
/// as a path. Two things take that off: a rewrite, since `pr:`/`mr:`
/// dispatch and the remote-prefix strip leave the user's literal argument
/// naming nothing; and `--create`, where the argument names a branch that
/// does not exist yet.
selector: Selector,
/// How to create the worktree
method: CreationMethod,
Expand Down
19 changes: 12 additions & 7 deletions src/git/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,13 +605,18 @@ pub fn resolve_input_path(path: impl AsRef<Path>) -> PathBuf {
/// one sits beside the branch, yielding `docs/`, and the branch lookup then
/// misses a branch that is right there.
///
/// Applied where a raw token enters resolution — [`Repository::resolve_worktree`],
/// [`Repository::resolve_target_branch`], and `plan_switch` — rather than
/// inside the shortcut expander they each call first. Both halves of "try the
/// branch, then try the path" have to see one token: each gates its path
/// attempt on the resolved name still equalling the input, which is how it
/// tells a shortcut rewrite from a literal, and a name stripped underneath
/// that test would read as a rewrite.
/// Applied in [`Repository::expand_selector`] — which every token the user
/// typed reaches before resolution — and again in
/// [`Repository::resolve_worktree`], so its `@` fast path tests the normalized
/// token. A [`Selector`] built straight from [`Selector::rewritten_to`] skips
/// it, correctly: a PR's head branch or a cached default branch was never a
/// spelling anyone chose, so there is nothing to strip.
///
/// That normalization has one home at all is what [`Selector`] buys. While
/// "may this token name a path?" was inferred by comparing an expansion's
/// output against its input, stripping a separator underneath that comparison
/// read as a rewrite and silently disabled the path arm — so each assembly of
/// the ladder had to normalize for itself, or not normalize at all.
///
/// A selector of nothing but separators is returned unchanged — `/` is the
/// root directory, and the empty string names nothing at all.
Expand Down
7 changes: 5 additions & 2 deletions src/git/repository/worktrees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,11 @@ impl Repository {
///
/// The `prunable` half costs a lookup rather than a fork:
/// [`list_worktrees`](Self::list_worktrees) has already parsed and cached
/// the listing. `false` for a path git has no registration for — absence of
/// a registration is not breakage of one.
/// the listing, and a path absent from it contributes nothing — no
/// registration is not a broken one. The existence half still applies to
/// such a path, so an unregistered directory that is gone answers `true`.
/// No caller reaches that combination: all three take their path out of the
/// listing.
pub fn worktree_is_unusable(&self, path: &Path) -> anyhow::Result<bool> {
if !path.exists() {
return Ok(true);
Expand Down
Loading