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: 8 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ $ uvx --from 'vcspull' --prerelease allow vcspull

_Upcoming changes will be written here._

### Bug Fixes

#### `vcspull add` keeps tilde workspace labels in path-first mode (#482, #483)

- Running `vcspull add ~/study/python/…` from inside the workspace now logs the
workspace as `~/study/python/` instead of `./`, preserving tilde-shortened
labels for path-first imports.

## vcspull v1.45.0 (2025-11-02)

### Bug Fixes
Expand Down
13 changes: 11 additions & 2 deletions src/vcspull/cli/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,10 @@ def handle_add_command(args: argparse.Namespace) -> None:
repo_path,
)

workspace_root_arg = getattr(args, "workspace_root_path", None)
workspace_root_input = (
args.workspace_root_path
if getattr(args, "workspace_root_path", None)
workspace_root_arg
if workspace_root_arg is not None
else repo_path.parent.as_posix()
)

Expand All @@ -212,6 +213,7 @@ def handle_add_command(args: argparse.Namespace) -> None:
workspace_path,
cwd=cwd,
home=pathlib.Path.home(),
preserve_cwd_label=workspace_root_arg in {".", "./"},
)

summary_url = display_url or config_url
Expand Down Expand Up @@ -479,11 +481,18 @@ def _aggregate_items(items: list[tuple[str, t.Any]]) -> dict[str, t.Any]:
cwd=cwd,
)
workspace_label = workspace_map.get(workspace_path)

if workspace_root_path is None:
preserve_workspace_label = path is None
else:
preserve_workspace_label = workspace_root_path in {".", "./"}

if workspace_label is None:
workspace_label = workspace_root_label(
workspace_path,
cwd=cwd,
home=home,
preserve_cwd_label=preserve_workspace_label,
)
workspace_map[workspace_path] = workspace_label
raw_config.setdefault(workspace_label, {})
Expand Down
3 changes: 2 additions & 1 deletion src/vcspull/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,12 +588,13 @@ def workspace_root_label(
*,
cwd: pathlib.Path | None = None,
home: pathlib.Path | None = None,
preserve_cwd_label: bool = True,
) -> str:
"""Create a normalized label for a workspace root path."""
cwd = cwd or pathlib.Path.cwd()
home = home or pathlib.Path.home()

if workspace_path == cwd:
if preserve_cwd_label and workspace_path == cwd:
return "./"

try:
Expand Down
42 changes: 42 additions & 0 deletions tests/cli/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -890,3 +890,45 @@ def test_add_repo_no_merge_preserves_duplicate_sections(
expected_repos = set(expected_original_repos) | {new_repo_name}
assert combined_repos == expected_repos, f"{test_id}: repositories mismatch"
assert contains_new_repo, f"{test_id}: new repo missing from duplicate sections"


def test_handle_add_command_workspace_label_from_workspace_root(
tmp_path: pathlib.Path,
monkeypatch: MonkeyPatch,
caplog: t.Any,
) -> None:
"""CLI add should label workspace roots with their tilde path even from root cwd."""
caplog.set_level(logging.INFO)

monkeypatch.setenv("HOME", str(tmp_path))

workspace_root = tmp_path / "study/python"
repo_path = workspace_root / "pytest-docker"
init_git_repo(repo_path, remote_url="https://github.com/avast/pytest-docker")

monkeypatch.chdir(workspace_root)

config_file = tmp_path / ".vcspull.yaml"

args = argparse.Namespace(
repo_path=str(repo_path),
url=None,
override_name=None,
config=str(config_file),
workspace_root_path=None,
dry_run=False,
assume_yes=True,
merge_duplicates=True,
)

handle_add_command(args)

expected_label = "~/study/python/"
assert expected_label in caplog.text

import yaml

with config_file.open(encoding="utf-8") as fh:
config_data = yaml.safe_load(fh)

assert expected_label in config_data