Skip to content

Commit 298f3b8

Browse files
authored
Streamline / modernize commands (#472)
Modernize CLI with DevOps conventions why: The previous CLI lacked modern DevOps tooling conventions, making it harder to preview changes, introspect configuration, and integrate with CI/CD pipelines. Users had no way to list repos or check status without syncing, and the import command tried to do two unrelated things (add single repo vs scan filesystem). what: - BREAKING: Remove vcspull import command, split into add and discover - BREAKING: Rename -c/--config → -f/--file across all commands - NEW: vcspull list - List configured repositories with --tree, --json, --ndjson - NEW: vcspull status - Check repository health (clean/dirty, ahead/behind) - NEW: vcspull add - Add single repository to configuration - NEW: vcspull discover - Scan filesystem for existing repositories - NEW: --dry-run/-n for sync, add, discover commands - NEW: --json/--ndjson structured output for automation - NEW: -w short flag for --workspace-root (all 3 aliases supported) - NEW: --color {auto,always,never} with NO_COLOR support - NEW: Terraform-style dry-run plans for vcspull sync - NEW: Async progress tracking for sync planning on TTYs - Add comprehensive test coverage: 46 new tests (1,803 lines) - Add complete documentation for all new commands - Add semantic colors infrastructure (_colors.py) - Add output formatting infrastructure (_output.py) - Add workspace filtering helper (_workspaces.py) Migration guide: vcspull import NAME URL → vcspull add NAME URL vcspull import --scan DIR → vcspull discover DIR vcspull sync -c FILE → vcspull sync -f FILE vcspull sync --workspace-root → vcspull sync -w PATH Benefits: - Better DX: Commands are clearer and more intuitive - Safer: Dry-run mode prevents mistakes - More discoverable: List and status commands for introspection - Familiar: Matches patterns from Terraform, Cargo, Ruff, Biome - CI/CD friendly: JSON/NDJSON output for scripting - Type-safe: Full mypy coverage on all new code Stats: 45 files changed, 6412 insertions(+), 1375 deletions(-) Tests: 192/192 passing (146 original + 46 new) refs: Aligns with modern DevOps CLI conventions
2 parents afa61bc + c87805f commit 298f3b8

45 files changed

Lines changed: 6412 additions & 1375 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGES

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,57 @@ $ pipx install --suffix=@next 'vcspull' --pip-args '\--pre' --force
3131

3232
<!-- Maintainers, insert changes / features for the next release here -->
3333

34-
_Notes on upcoming releases will be added here_
34+
### Breaking Changes
35+
36+
This release modernizes the vcspull CLI to align with DevOps tool conventions (Terraform, Cargo, Ruff, Biome). **This is a breaking change release**.
37+
38+
#### Command Changes (#472)
39+
40+
- **REMOVED**: `vcspull import` command
41+
- Replaced by `vcspull add <name> <url>` to add a single repository
42+
- Replaced by `vcspull discover <path>` to scan and add multiple repositories
43+
- **NEW**: `vcspull list` - List configured repositories with optional `--tree`, `--json`, `--ndjson` output
44+
- **NEW**: `vcspull status` - Check repository health (clean/dirty status, ahead/behind tracking with `--detailed`)
45+
46+
#### Flag Changes (#472)
47+
48+
- **RENAMED**: `-c/--config``-f/--file` (all commands)
49+
- **NEW**: `-w/--workspace/--workspace-root` - All three aliases supported for workspace root
50+
- **NEW**: `--dry-run/-n` - Preview changes without making modifications (sync, add, discover)
51+
- **NEW**: `--json/--ndjson` - Machine-readable output for automation (sync, list, status)
52+
- **NEW**: `--color {auto,always,never}` - Control color output
53+
54+
#### Migration Guide (#472)
55+
56+
```bash
57+
# Old → New
58+
vcspull import NAME URL → vcspull add NAME URL
59+
vcspull import --scan DIR → vcspull discover DIR
60+
vcspull sync -c FILE → vcspull sync -f FILE
61+
vcspull sync --workspace-root PATH → vcspull sync -w PATH # (or keep long form)
62+
vcspull fmt -c FILE → vcspull fmt -f FILE
63+
```
64+
65+
### Features
66+
67+
#### Developer Experience Improvements (#472)
68+
69+
- Action commands (`sync`, `add`, `discover`) support `--dry-run` for safe previewing of changes
70+
- Structured output (`--json`, `--ndjson`) enables CI/CD integration and automation
71+
- Semantic colors with `NO_COLOR` environment variable support
72+
- Short `-w` flag for workspace root reduces typing
73+
- Consistent flag naming across all commands
74+
- `vcspull sync --dry-run` renders a Terraform-style plan (with live progress on
75+
TTYs) and exposes the same data via a stable JSON/NDJSON schema for automation
76+
77+
#### New Introspection Commands (#472)
78+
79+
- `vcspull list` - View all configured repositories
80+
- `--tree` mode groups by workspace root
81+
- `--json/--ndjson` for programmatic access
82+
- `vcspull status` - Check repository health
83+
- Shows which repos exist, are clean/dirty, or missing
84+
- `--detailed` mode shows branch, ahead/behind tracking, and full paths
3585

3686
## vcspull v1.38.0 (2025-10-18)
3787

README.md

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ You can test the unpublished version of vcspull before its released.
6868
## Configuration
6969

7070
Add your repos to `~/.vcspull.yaml`. You can edit the file by hand or let
71-
`vcspull import` create entries for you.
71+
`vcspull add` or `vcspull discover` create entries for you.
7272

7373
```yaml
7474
~/code/:
@@ -91,40 +91,68 @@ more [configuration](https://vcspull.git-pull.com/configuration.html))
9191
be used as a declarative manifest to clone your repos consistently across
9292
machines. Subsequent syncs of initialized repos will fetch the latest commits.
9393

94-
### Import repositories from the CLI
94+
### Add repositories from the CLI
9595

96-
Register an existing remote without touching YAML manually:
96+
Register a single repository without touching YAML manually:
9797

9898
```console
99-
$ vcspull import my-lib https://github.com/example/my-lib.git --path ~/code/my-lib
99+
$ vcspull add my-lib https://github.com/example/my-lib.git --path ~/code/my-lib
100100
```
101101

102102
- Omit `--path` to default the entry under `./`.
103-
- Use `--workspace-root` when you want to force a specific workspace root, e.g.
104-
`--workspace-root ~/projects/libs`.
105-
- Pass `-c/--config` to import into an alternate YAML file.
103+
- Use `-w/--workspace` when you want to force a specific workspace root, e.g.
104+
`-w ~/projects/libs`.
105+
- Pass `-f/--file` to add to an alternate YAML file.
106+
- Use `--dry-run` to preview changes before writing.
106107
- Follow with `vcspull sync my-lib` to clone or update the working tree after registration.
107108

108-
### Scan local checkouts and import en masse
109+
### Discover local checkouts and add en masse
109110

110111
Have a directory tree full of cloned Git repositories? Scan and append them to
111112
your configuration:
112113

113114
```console
114-
$ vcspull import --scan ~/code --recursive
115+
$ vcspull discover ~/code --recursive
115116
```
116117

117118
The scan shows each repository before import unless you opt into `--yes`. Add
118-
`--workspace-root ~/code/` to pin the resulting workspace root or `--config` to
119+
`-w ~/code/` to pin the resulting workspace root or `-f` to
119120
write somewhere other than the default `~/.vcspull.yaml`.
120121

122+
### Inspect configured repositories
123+
124+
List what vcspull already knows about without mutating anything:
125+
126+
```console
127+
$ vcspull list
128+
$ vcspull list --tree
129+
$ vcspull list --json | jq '.[].name'
130+
```
131+
132+
`--json` emits a single JSON array, while `--ndjson` streams newline-delimited
133+
objects that are easy to consume from shell pipelines.
134+
135+
### Check repository status
136+
137+
Get a quick health check for all configured workspaces:
138+
139+
```console
140+
$ vcspull status
141+
$ vcspull status --detailed
142+
$ vcspull status --ndjson | jq --slurp 'map(select(.reason == "summary"))'
143+
```
144+
145+
The status command respects `--workspace/-w` filters and the global
146+
`--color {auto,always,never}` flag. JSON and NDJSON output mirrors the list
147+
command for automation workflows.
148+
121149
### Normalize configuration files
122150

123151
After importing or editing by hand, run the formatter to tidy up keys and keep
124152
entries sorted:
125153

126154
```console
127-
$ vcspull fmt --config ~/.vcspull.yaml --write
155+
$ vcspull fmt -f ~/.vcspull.yaml --write
128156
```
129157

130158
Use `vcspull fmt --all --write` to format every YAML file that vcspull can
@@ -136,6 +164,21 @@ discover under the standard config locations.
136164
$ vcspull sync
137165
```
138166

167+
Preview planned work with Terraform-style plan output or emit structured data
168+
for CI/CD:
169+
170+
```console
171+
$ vcspull sync --dry-run "*"
172+
$ vcspull sync --dry-run --show-unchanged "workspace-*"
173+
$ vcspull sync --dry-run --json "*" | jq '.summary'
174+
$ vcspull sync --dry-run --ndjson "*" | jq --slurp 'map(select(.type == "summary"))'
175+
```
176+
177+
Dry runs stream a progress line when stdout is a TTY, then print a concise plan
178+
summary (`+/~/✓/⚠/✗`) grouped by workspace. Use `--summary-only`,
179+
`--relative-paths`, `--long`, or `-v/-vv` for alternate views, and
180+
`--fetch`/`--offline` to control how remote metadata is refreshed.
181+
139182
Keep nested VCS repositories updated too, lets say you have a mercurial
140183
or svn project with a git dependency:
141184

@@ -149,7 +192,7 @@ or svn project with a git dependency:
149192
Clone / update repos via config file:
150193

151194
```console
152-
$ vcspull sync -c external_deps.yaml '*'
195+
$ vcspull sync -f external_deps.yaml '*'
153196
```
154197

155198
See the [Quickstart](https://vcspull.git-pull.com/quickstart.html) for

docs/Makefile

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@ WATCH_FILES= find .. -type f -not -path '*/\.*' | grep -i '.*[.]\(rst\|md\)\$\|.
66

77
# You can set these variables from the command line.
88
SPHINXOPTS =
9-
SPHINXBUILD = sphinx-build
9+
# Keep ANSI color codes out of generated docs (Sphinx + argparse) by forcing
10+
# Python's colour support off for every build command.
11+
SPHINX_ENV = PYTHON_COLORS=0 NO_COLOR=1
12+
SPHINXBUILD = $(SPHINX_ENV) sphinx-build
1013
PAPER =
1114
BUILDDIR = _build
15+
# Apply the same environment when running the live-reload server.
16+
SPHINX_AUTOBUILD = $(SPHINX_ENV) uv run sphinx-autobuild
1217

1318
# Internal variables.
1419
PAPEROPT_a4 = -D latex_paper_size=a4
@@ -182,8 +187,8 @@ dev:
182187
$(MAKE) -j watch serve
183188

184189
start:
185-
uv run sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) --port ${HTTP_PORT} $(O)
190+
$(SPHINX_AUTOBUILD) "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) --port ${HTTP_PORT} $(O)
186191

187192
design:
188193
# This adds additional watch directories (for _static file changes) and disable incremental builds
189-
uv run sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) --port ${HTTP_PORT} --watch "." -a $(O)
194+
$(SPHINX_AUTOBUILD) "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) --port ${HTTP_PORT} --watch "." -a $(O)

docs/api/cli/add.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# vcspull add - `vcspull.cli.add`
2+
3+
```{eval-rst}
4+
.. automodule:: vcspull.cli.add
5+
:members:
6+
:show-inheritance:
7+
:undoc-members:
8+
```

docs/api/cli/discover.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# vcspull discover - `vcspull.cli.discover`
2+
3+
```{eval-rst}
4+
.. automodule:: vcspull.cli.discover
5+
:members:
6+
:show-inheritance:
7+
:undoc-members:
8+
```

docs/api/cli/import.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
# vcspull import - `vcspull.cli._import`
22

3-
```{eval-rst}
4-
.. automodule:: vcspull.cli._import
5-
:members:
6-
:show-inheritance:
7-
:undoc-members:
3+
```{warning}
4+
**This module has been removed** as of vcspull 1.38.0.
5+
6+
The `vcspull.cli._import` module has been split into two separate modules:
7+
- {py:mod}`vcspull.cli.add` - Add single repositories manually
8+
- {py:mod}`vcspull.cli.discover` - Scan directories for existing repositories
9+
10+
See the user-facing documentation at {ref}`cli-add` and {ref}`cli-discover`.
811
```
12+
13+
## Historical API Reference
14+
15+
This module previously provided the `import` command functionality but has been
16+
replaced with more focused commands.

docs/api/cli/index.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
:maxdepth: 1
1010
1111
sync
12-
import
12+
add
13+
discover
14+
list
15+
status
1316
fmt
1417
```
1518

docs/api/cli/list.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# vcspull list - `vcspull.cli.list`
2+
3+
```{eval-rst}
4+
.. automodule:: vcspull.cli.list
5+
:members:
6+
:show-inheritance:
7+
:undoc-members:
8+
```

docs/api/cli/status.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# vcspull status - `vcspull.cli.status`
2+
3+
```{eval-rst}
4+
.. automodule:: vcspull.cli.status
5+
:members:
6+
:show-inheritance:
7+
:undoc-members:
8+
```

0 commit comments

Comments
 (0)