Skip to content

Commit 7803660

Browse files
committed
cli/add(feat[config-format]): Use verbose repo format for new configs
why: Simple string format doesn't allow for future extensions like multiple remotes or other repo-specific settings. what: - Change add and add-from-fs to write verbose format with repo: key - Use {"repo": "url"} instead of plain string format - Add comprehensive tests for add command - Update all test assertions to expect verbose format This matches vcspull's existing test patterns and README examples, and allows users to easily extend configs with remotes later.
1 parent 7fd2cbb commit 7803660

File tree

4 files changed

+168
-5
lines changed

4 files changed

+168
-5
lines changed

src/vcspull/cli/add.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,10 @@ def add_repo(
149149
)
150150
return
151151

152-
# Add the repository
153-
raw_config[base_dir_key][name] = url
152+
# Add the repository in verbose format
153+
raw_config[base_dir_key][name] = {
154+
"repo": url
155+
}
154156

155157
# Save config
156158
try:

src/vcspull/cli/add_from_fs.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,9 @@ def add_from_filesystem(
300300
continue
301301

302302
if repo_name not in raw_config[determined_base_key]:
303-
raw_config[determined_base_key][repo_name] = repo_url
303+
raw_config[determined_base_key][repo_name] = {
304+
"repo": repo_url
305+
}
304306
log.info(
305307
f"{Fore.GREEN}+{Style.RESET_ALL} Adding "
306308
f"{Fore.CYAN}'{repo_name}'{Style.RESET_ALL} "

tests/cli/test_add.py

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
"""Tests for vcspull.cli.add functionality."""
2+
3+
from __future__ import annotations
4+
5+
import pathlib
6+
import typing as t
7+
8+
import pytest
9+
import yaml
10+
11+
from vcspull.cli.add import add_repo
12+
13+
if t.TYPE_CHECKING:
14+
from _pytest.logging import LogCaptureFixture
15+
16+
17+
class TestAddRepo:
18+
"""Test add_repo function."""
19+
20+
def test_add_simple_repo(
21+
self,
22+
tmp_path: pathlib.Path,
23+
caplog: LogCaptureFixture,
24+
) -> None:
25+
"""Test adding a simple repository."""
26+
caplog.set_level("INFO")
27+
28+
config_file = tmp_path / ".vcspull.yaml"
29+
30+
# Add a repository
31+
add_repo(
32+
name="myproject",
33+
url="git@github.com:user/myproject.git",
34+
config_file_path_str=str(config_file),
35+
path=None,
36+
base_dir=None,
37+
)
38+
39+
# Verify config file was created with verbose format
40+
assert config_file.exists()
41+
with config_file.open() as f:
42+
config_data = yaml.safe_load(f)
43+
44+
# Check verbose format
45+
assert "./" in config_data
46+
assert "myproject" in config_data["./"]
47+
assert config_data["./"]["myproject"] == {
48+
"repo": "git@github.com:user/myproject.git"
49+
}
50+
51+
# Check success message
52+
assert "Successfully added 'myproject'" in caplog.text
53+
54+
def test_add_with_custom_base_dir(
55+
self,
56+
tmp_path: pathlib.Path,
57+
caplog: LogCaptureFixture,
58+
) -> None:
59+
"""Test adding a repository with custom base directory."""
60+
caplog.set_level("INFO")
61+
62+
config_file = tmp_path / ".vcspull.yaml"
63+
64+
# Add a repository with custom base dir
65+
add_repo(
66+
name="mylib",
67+
url="https://github.com/org/mylib",
68+
config_file_path_str=str(config_file),
69+
path=None,
70+
base_dir="~/projects/libs",
71+
)
72+
73+
# Verify config
74+
with config_file.open() as f:
75+
config_data = yaml.safe_load(f)
76+
77+
assert "~/projects/libs/" in config_data
78+
assert config_data["~/projects/libs/"]["mylib"] == {
79+
"repo": "https://github.com/org/mylib"
80+
}
81+
82+
def test_add_duplicate_repo(
83+
self,
84+
tmp_path: pathlib.Path,
85+
caplog: LogCaptureFixture,
86+
) -> None:
87+
"""Test adding a duplicate repository shows warning."""
88+
caplog.set_level("WARNING")
89+
90+
config_file = tmp_path / ".vcspull.yaml"
91+
92+
# Pre-create config with existing repo
93+
existing_config = {
94+
"~/code/": {
95+
"existing": {
96+
"repo": "git@github.com:user/existing.git"
97+
}
98+
}
99+
}
100+
with config_file.open("w") as f:
101+
yaml.dump(existing_config, f)
102+
103+
# Try to add duplicate
104+
add_repo(
105+
name="existing",
106+
url="git@github.com:other/existing.git",
107+
config_file_path_str=str(config_file),
108+
path=None,
109+
base_dir="~/code",
110+
)
111+
112+
# Should show warning
113+
assert "Repository 'existing' already exists" in caplog.text
114+
assert "Current URL: git@github.com:user/existing.git" in caplog.text
115+
116+
# Config should not be changed
117+
with config_file.open() as f:
118+
config_data = yaml.safe_load(f)
119+
assert config_data["~/code/"]["existing"]["repo"] == "git@github.com:user/existing.git"
120+
121+
def test_add_to_existing_config(
122+
self,
123+
tmp_path: pathlib.Path,
124+
caplog: LogCaptureFixture,
125+
) -> None:
126+
"""Test adding to an existing config file."""
127+
caplog.set_level("INFO")
128+
129+
config_file = tmp_path / ".vcspull.yaml"
130+
131+
# Pre-create config with some repos
132+
existing_config = {
133+
"~/work/": {
134+
"project1": {
135+
"repo": "git@github.com:user/project1.git"
136+
}
137+
}
138+
}
139+
with config_file.open("w") as f:
140+
yaml.dump(existing_config, f)
141+
142+
# Add new repo to same base dir
143+
add_repo(
144+
name="project2",
145+
url="git@github.com:user/project2.git",
146+
config_file_path_str=str(config_file),
147+
path=None,
148+
base_dir="~/work",
149+
)
150+
151+
# Verify both repos exist
152+
with config_file.open() as f:
153+
config_data = yaml.safe_load(f)
154+
155+
assert "project1" in config_data["~/work/"]
156+
assert "project2" in config_data["~/work/"]
157+
assert config_data["~/work/"]["project2"] == {
158+
"repo": "git@github.com:user/project2.git"
159+
}

tests/cli/test_add_from_fs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def test_single_repo(
136136
expected_key = str(scan_dir) + "/"
137137
assert expected_key in config_data
138138
assert repo_name in config_data[expected_key]
139-
assert config_data[expected_key][repo_name] == remote_url
139+
assert config_data[expected_key][repo_name] == {"repo": remote_url}
140140

141141
# Check log messages
142142
assert f"Adding '{repo_name}' ({remote_url})" in caplog.text
@@ -200,7 +200,7 @@ def test_multiple_repos_recursive(
200200

201201
for name, url in repos:
202202
assert name in config_data[expected_key]
203-
assert config_data[expected_key][name] == url
203+
assert config_data[expected_key][name] == {"repo": url}
204204

205205
def test_non_recursive(
206206
self,

0 commit comments

Comments
 (0)