dotx 2.1.0__tar.gz → 2.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {dotx-2.1.0/src/dotx.egg-info → dotx-2.2.1}/PKG-INFO +120 -57
  2. {dotx-2.1.0 → dotx-2.2.1}/README.md +119 -56
  3. {dotx-2.1.0 → dotx-2.2.1}/pyproject.toml +1 -1
  4. dotx-2.2.1/src/dotx/cli.py +119 -0
  5. dotx-2.2.1/src/dotx/commands/__init__.py +1 -0
  6. dotx-2.2.1/src/dotx/commands/database.py +430 -0
  7. dotx-2.2.1/src/dotx/commands/install_cmd.py +117 -0
  8. dotx-2.2.1/src/dotx/commands/uninstall_cmd.py +90 -0
  9. {dotx-2.1.0 → dotx-2.2.1}/src/dotx/ignore.py +10 -4
  10. {dotx-2.1.0 → dotx-2.2.1/src/dotx.egg-info}/PKG-INFO +120 -57
  11. {dotx-2.1.0 → dotx-2.2.1}/src/dotx.egg-info/SOURCES.txt +4 -0
  12. dotx-2.2.1/tests/test_cli.py +248 -0
  13. {dotx-2.1.0 → dotx-2.2.1}/tests/test_cli_database.py +126 -0
  14. dotx-2.1.0/src/dotx/cli.py +0 -622
  15. dotx-2.1.0/tests/test_cli.py +0 -30
  16. {dotx-2.1.0 → dotx-2.2.1}/LICENSE +0 -0
  17. {dotx-2.1.0 → dotx-2.2.1}/MANIFEST.in +0 -0
  18. {dotx-2.1.0 → dotx-2.2.1}/setup.cfg +0 -0
  19. {dotx-2.1.0 → dotx-2.2.1}/src/dotx/__init__.py +0 -0
  20. {dotx-2.1.0 → dotx-2.2.1}/src/dotx/database.py +0 -0
  21. {dotx-2.1.0 → dotx-2.2.1}/src/dotx/install.py +0 -0
  22. {dotx-2.1.0 → dotx-2.2.1}/src/dotx/installed-schema.sql +0 -0
  23. {dotx-2.1.0 → dotx-2.2.1}/src/dotx/options.py +0 -0
  24. {dotx-2.1.0 → dotx-2.2.1}/src/dotx/plan.py +0 -0
  25. {dotx-2.1.0 → dotx-2.2.1}/src/dotx/uninstall.py +0 -0
  26. {dotx-2.1.0 → dotx-2.2.1}/src/dotx.egg-info/dependency_links.txt +0 -0
  27. {dotx-2.1.0 → dotx-2.2.1}/src/dotx.egg-info/entry_points.txt +0 -0
  28. {dotx-2.1.0 → dotx-2.2.1}/src/dotx.egg-info/requires.txt +0 -0
  29. {dotx-2.1.0 → dotx-2.2.1}/src/dotx.egg-info/top_level.txt +0 -0
  30. {dotx-2.1.0 → dotx-2.2.1}/tests/test_ignore.py +0 -0
  31. {dotx-2.1.0 → dotx-2.2.1}/tests/test_ignore_rules.py +0 -0
  32. {dotx-2.1.0 → dotx-2.2.1}/tests/test_install.py +0 -0
  33. {dotx-2.1.0 → dotx-2.2.1}/tests/test_options.py +0 -0
  34. {dotx-2.1.0 → dotx-2.2.1}/tests/test_plan.py +0 -0
  35. {dotx-2.1.0 → dotx-2.2.1}/tests/test_uninstall.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dotx
3
- Version: 2.1.0
3
+ Version: 2.2.1
4
4
  Summary: A command-line tool to install a link-farm to your dotfiles
5
5
  Author-email: Wolf <Wolf@zv.cx>
6
6
  License-Expression: MIT
@@ -28,6 +28,8 @@ Dynamic: license-file
28
28
 
29
29
  ## The Basic Idea
30
30
 
31
+ > **Comparing dotfile managers?** See [ALTERNATIVES.md](ALTERNATIVES.md) for a detailed comparison of dotx vs GNU Stow, chezmoi, YADM, dotbot, and others.
32
+
31
33
  ### What `dotx` does; what it's _for_
32
34
  #### The problem
33
35
 
@@ -241,15 +243,78 @@ Installations:
241
243
 
242
244
  #### Rebuild database from filesystem
243
245
 
244
- If you have existing dotfile installations and an empty or missing database, use `sync` to rebuild it:
246
+ If you have existing dotfile installations and an empty or missing database, use `sync` to rebuild it.
247
+
248
+ ##### The Problem: Unwanted Symlinks
245
249
 
250
+ By default, `sync` scans your home directory and `~/.config` for **all** symlinks. This can discover symlinks you don't want to track as dotfiles packages, such as:
251
+ - System symlinks in `~/Library/` (macOS)
252
+ - Application symlinks in `/Applications/`
253
+ - IDE or tool-generated symlinks
254
+ - Homebrew-managed symlinks
255
+
256
+ For example, without filtering you might see:
246
257
  ```bash
247
- # Preview what would be added to database
248
258
  +$ dotx sync --dry-run
259
+ ✓ Found 44 symlink(s)
260
+
261
+ Discovered 25 potential package(s):
262
+ /Users/wolf/dotfiles/bash # ✓ Want this
263
+ 5 symlink(s)
264
+ /Users/wolf/dotfiles/vim # ✓ Want this
265
+ 8 symlink(s)
266
+ /Users/wolf/Library # ✗ Don't want this!
267
+ 1 symlink(s)
268
+ /Applications/Raycast.app/... # ✗ Don't want this!
269
+ 1 symlink(s)
270
+ ```
271
+
272
+ ##### The Solution: `--package-root`
249
273
 
250
- # Interactively rebuild database from filesystem
251
- +$ dotx sync
252
- Found 15 symlink(s) in /Users/wolf
274
+ Use `--package-root` to filter packages to **only** those under specific directories. This is **strongly recommended** to avoid tracking unwanted symlinks:
275
+
276
+ ```bash
277
+ # Filter to only your dotfiles directory
278
+ +$ dotx sync --dry-run --package-root ~/dotfiles
279
+ ✓ Found 44 symlink(s)
280
+ Filtered out 6 symlink(s) not under --package-root
281
+
282
+ Discovered 3 potential package(s):
283
+ /Users/wolf/dotfiles/bash
284
+ 5 symlink(s)
285
+ /Users/wolf/dotfiles/vim
286
+ 8 symlink(s)
287
+ /Users/wolf/dotfiles/git
288
+ 2 symlink(s)
289
+ ```
290
+
291
+ You can specify multiple roots if your packages are in different locations:
292
+
293
+ ```bash
294
+ +$ dotx sync --package-root ~/dotfiles --package-root ~/work/configs
295
+ ```
296
+
297
+ ##### Safety Warning
298
+
299
+ If you run `sync` without `--package-root` and have an empty database, you'll see a warning:
300
+
301
+ ```bash
302
+ +$ dotx sync --dry-run
303
+ ✓ Found 44 symlink(s)
304
+ ⚠ Warning: No --package-root specified and database is empty.
305
+ Consider using --package-root to filter packages (e.g., --package-root ~/dotfiles)
306
+ ```
307
+
308
+ ##### Complete Example
309
+
310
+ ```bash
311
+ # Preview what will be synced (recommended first step)
312
+ +$ dotx sync --dry-run --package-root ~/dotfiles
313
+
314
+ # After reviewing, sync for real
315
+ +$ dotx sync --package-root ~/dotfiles
316
+ ✓ Found 15 symlink(s)
317
+ Filtered out 0 symlink(s) not under --package-root
253
318
 
254
319
  Discovered 3 potential package(s):
255
320
  /Users/wolf/dotfiles/bash
@@ -265,66 +330,58 @@ Continue? [y/N]: y
265
330
  ✓ Recorded 15 installation(s) in database.
266
331
  ```
267
332
 
268
- The `sync` command scans your home directory for symlinks and attempts to determine which package they belong to, then rebuilds the database accordingly.
333
+ **Note:** The `sync` command is **additive** - it updates existing entries and adds new ones, but doesn't delete entries for packages not found. This means running sync with `--package-root` won't remove other packages from your database.
269
334
 
270
- ### How it works
335
+ ##### Cleaning Orphaned Entries with `--clean`
271
336
 
272
- *Documentation to be expanded*
337
+ Over time, your database may accumulate **orphaned entries** - records for symlinks that no longer exist on the filesystem. Use `--clean` to remove these automatically, similar to `git fetch --prune`:
273
338
 
274
- ### What's New in v1.1.0
339
+ ```bash
340
+ # Preview what would be cleaned
341
+ +$ dotx sync --dry-run --clean --package-root ~/dotfiles
342
+ ✓ Found 15 symlink(s)
275
343
 
276
- #### Testing and Quality
277
- - **Comprehensive test coverage**: 77.64% overall (up from 53%)
278
- - **21 new database command tests**: Full integration testing for `list`, `verify`, `show`, `sync`
279
- - **Automated coverage tracking**: pytest-cov integration with HTML reports
280
- - **Bug fix**: Database now correctly stores symlink paths instead of resolved paths
344
+ Would clean orphaned entries:
345
+ bash: 2 orphaned entry(ies)
346
+ vim: 1 orphaned entry(ies)
347
+ Would remove 3 orphaned entry(ies).
281
348
 
282
- #### Documentation
283
- - Added Development section with testing, pre-commit hooks, and integration testing docs
284
- - Added clean-up instructions for development artifacts
285
- - Coverage reports available via `open htmlcov/index.html`
349
+ Dry run - no database changes made.
286
350
 
287
- ### What's New in v1.0.0
351
+ # Clean for real
352
+ +$ dotx sync --clean --package-root ~/dotfiles
353
+ ✓ Found 15 symlink(s)
354
+ Filtered out 0 symlink(s) not under --package-root
288
355
 
289
- #### Installation Database
290
- - **SQLite database** tracks which packages installed which files
291
- - **New commands**: `list`, `verify`, `show`, `sync` for package management
292
- - Database location respects `XDG_DATA_HOME` environment variable
293
- - Export reinstall commands with `dotx list --as-commands` for easy migration
356
+ Discovered 3 potential package(s):
357
+ /Users/wolf/dotfiles/bash
358
+ 5 symlink(s)
359
+ ...
294
360
 
295
- #### Improved Ignore System
296
- - **`.dotxignore` files** replace CLI `-i/--ignore` option (breaking change)
297
- - Full gitignore-style pattern syntax support
298
- - Nested `.dotxignore` files in subdirectories
299
- - Global ignore file at `~/.config/dotx/ignore`
300
- - Negation patterns (`!important.conf`)
361
+ This will rebuild the database with the discovered installations.
362
+ Continue? [y/N]: y
301
363
 
302
- #### Quality Improvements
303
- - Pre-commit hooks with ruff, pyrefly, pytest
304
- - Modern Python type annotations throughout
305
- - Better logging with loguru
306
- - Comprehensive code documentation and comments
364
+ Recorded 15 installation(s) in database.
307
365
 
308
- ### Migration from older versions
366
+ Cleaning orphaned entries...
367
+ ✓ Removed 3 orphaned entry(ies).
368
+ ```
309
369
 
310
- **Breaking change in v1.0.0:** The `-i/--ignore` command-line option has been removed in favor of `.dotxignore` files.
370
+ **When to use `--clean`:**
371
+ - After manually removing symlinks
372
+ - After uninstalling packages without using `dotx uninstall`
373
+ - During regular maintenance to keep database accurate
374
+ - When migrating or reorganizing dotfiles
311
375
 
312
- If you were using:
313
- ```bash
314
- dotx --ignore=README.* --ignore=.mypy_cache install bash
315
- ```
376
+ **Important:** `--clean` removes database entries for files that don't exist. Always preview with `--dry-run` first to ensure you're not removing entries you want to keep.
316
377
 
317
- Now create a `.dotxignore` file in your package:
318
- ```bash
319
- +$ cat > bash/.dotxignore <<EOF
320
- README.*
321
- .mypy_cache
322
- EOF
378
+ ### How it works
323
379
 
324
- +$ dotx install bash
325
- ```
380
+ *Documentation to be expanded*
381
+
382
+ ### Changelog
326
383
 
327
- Or use the global ignore file at `~/.config/dotx/ignore` for patterns that apply to all packages.
384
+ See [CHANGELOG.md](CHANGELOG.md) for version history and release notes.
328
385
 
329
386
  ## Development
330
387
 
@@ -395,10 +452,16 @@ This removes:
395
452
 
396
453
  **Note:** Add `.` at the end (`git clean -fdx .`) to limit cleanup to the current directory only.
397
454
 
398
- ### What's next
455
+ ### Shell Completions
456
+
457
+ dotx includes automatic shell completion via Typer:
458
+
459
+ ```bash
460
+ # Install completion for your shell
461
+ dotx --install-completion
462
+
463
+ # Or show the completion script to customize it
464
+ dotx --show-completion
465
+ ```
399
466
 
400
- Potential future enhancements:
401
- * Support for templates and variable substitution in dotfiles
402
- * Hooks system for running commands before/after installation
403
- * Conflict resolution strategies for overlapping packages
404
- * Shell completions for bash/zsh/fish
467
+ Supports Bash, Zsh, Fish, and PowerShell automatically.
@@ -1,5 +1,7 @@
1
1
  ## The Basic Idea
2
2
 
3
+ > **Comparing dotfile managers?** See [ALTERNATIVES.md](ALTERNATIVES.md) for a detailed comparison of dotx vs GNU Stow, chezmoi, YADM, dotbot, and others.
4
+
3
5
  ### What `dotx` does; what it's _for_
4
6
  #### The problem
5
7
 
@@ -213,15 +215,78 @@ Installations:
213
215
 
214
216
  #### Rebuild database from filesystem
215
217
 
216
- If you have existing dotfile installations and an empty or missing database, use `sync` to rebuild it:
218
+ If you have existing dotfile installations and an empty or missing database, use `sync` to rebuild it.
219
+
220
+ ##### The Problem: Unwanted Symlinks
217
221
 
222
+ By default, `sync` scans your home directory and `~/.config` for **all** symlinks. This can discover symlinks you don't want to track as dotfiles packages, such as:
223
+ - System symlinks in `~/Library/` (macOS)
224
+ - Application symlinks in `/Applications/`
225
+ - IDE or tool-generated symlinks
226
+ - Homebrew-managed symlinks
227
+
228
+ For example, without filtering you might see:
218
229
  ```bash
219
- # Preview what would be added to database
220
230
  +$ dotx sync --dry-run
231
+ ✓ Found 44 symlink(s)
232
+
233
+ Discovered 25 potential package(s):
234
+ /Users/wolf/dotfiles/bash # ✓ Want this
235
+ 5 symlink(s)
236
+ /Users/wolf/dotfiles/vim # ✓ Want this
237
+ 8 symlink(s)
238
+ /Users/wolf/Library # ✗ Don't want this!
239
+ 1 symlink(s)
240
+ /Applications/Raycast.app/... # ✗ Don't want this!
241
+ 1 symlink(s)
242
+ ```
243
+
244
+ ##### The Solution: `--package-root`
221
245
 
222
- # Interactively rebuild database from filesystem
223
- +$ dotx sync
224
- Found 15 symlink(s) in /Users/wolf
246
+ Use `--package-root` to filter packages to **only** those under specific directories. This is **strongly recommended** to avoid tracking unwanted symlinks:
247
+
248
+ ```bash
249
+ # Filter to only your dotfiles directory
250
+ +$ dotx sync --dry-run --package-root ~/dotfiles
251
+ ✓ Found 44 symlink(s)
252
+ Filtered out 6 symlink(s) not under --package-root
253
+
254
+ Discovered 3 potential package(s):
255
+ /Users/wolf/dotfiles/bash
256
+ 5 symlink(s)
257
+ /Users/wolf/dotfiles/vim
258
+ 8 symlink(s)
259
+ /Users/wolf/dotfiles/git
260
+ 2 symlink(s)
261
+ ```
262
+
263
+ You can specify multiple roots if your packages are in different locations:
264
+
265
+ ```bash
266
+ +$ dotx sync --package-root ~/dotfiles --package-root ~/work/configs
267
+ ```
268
+
269
+ ##### Safety Warning
270
+
271
+ If you run `sync` without `--package-root` and have an empty database, you'll see a warning:
272
+
273
+ ```bash
274
+ +$ dotx sync --dry-run
275
+ ✓ Found 44 symlink(s)
276
+ ⚠ Warning: No --package-root specified and database is empty.
277
+ Consider using --package-root to filter packages (e.g., --package-root ~/dotfiles)
278
+ ```
279
+
280
+ ##### Complete Example
281
+
282
+ ```bash
283
+ # Preview what will be synced (recommended first step)
284
+ +$ dotx sync --dry-run --package-root ~/dotfiles
285
+
286
+ # After reviewing, sync for real
287
+ +$ dotx sync --package-root ~/dotfiles
288
+ ✓ Found 15 symlink(s)
289
+ Filtered out 0 symlink(s) not under --package-root
225
290
 
226
291
  Discovered 3 potential package(s):
227
292
  /Users/wolf/dotfiles/bash
@@ -237,66 +302,58 @@ Continue? [y/N]: y
237
302
  ✓ Recorded 15 installation(s) in database.
238
303
  ```
239
304
 
240
- The `sync` command scans your home directory for symlinks and attempts to determine which package they belong to, then rebuilds the database accordingly.
305
+ **Note:** The `sync` command is **additive** - it updates existing entries and adds new ones, but doesn't delete entries for packages not found. This means running sync with `--package-root` won't remove other packages from your database.
241
306
 
242
- ### How it works
307
+ ##### Cleaning Orphaned Entries with `--clean`
243
308
 
244
- *Documentation to be expanded*
309
+ Over time, your database may accumulate **orphaned entries** - records for symlinks that no longer exist on the filesystem. Use `--clean` to remove these automatically, similar to `git fetch --prune`:
245
310
 
246
- ### What's New in v1.1.0
311
+ ```bash
312
+ # Preview what would be cleaned
313
+ +$ dotx sync --dry-run --clean --package-root ~/dotfiles
314
+ ✓ Found 15 symlink(s)
247
315
 
248
- #### Testing and Quality
249
- - **Comprehensive test coverage**: 77.64% overall (up from 53%)
250
- - **21 new database command tests**: Full integration testing for `list`, `verify`, `show`, `sync`
251
- - **Automated coverage tracking**: pytest-cov integration with HTML reports
252
- - **Bug fix**: Database now correctly stores symlink paths instead of resolved paths
316
+ Would clean orphaned entries:
317
+ bash: 2 orphaned entry(ies)
318
+ vim: 1 orphaned entry(ies)
319
+ Would remove 3 orphaned entry(ies).
253
320
 
254
- #### Documentation
255
- - Added Development section with testing, pre-commit hooks, and integration testing docs
256
- - Added clean-up instructions for development artifacts
257
- - Coverage reports available via `open htmlcov/index.html`
321
+ Dry run - no database changes made.
258
322
 
259
- ### What's New in v1.0.0
323
+ # Clean for real
324
+ +$ dotx sync --clean --package-root ~/dotfiles
325
+ ✓ Found 15 symlink(s)
326
+ Filtered out 0 symlink(s) not under --package-root
260
327
 
261
- #### Installation Database
262
- - **SQLite database** tracks which packages installed which files
263
- - **New commands**: `list`, `verify`, `show`, `sync` for package management
264
- - Database location respects `XDG_DATA_HOME` environment variable
265
- - Export reinstall commands with `dotx list --as-commands` for easy migration
328
+ Discovered 3 potential package(s):
329
+ /Users/wolf/dotfiles/bash
330
+ 5 symlink(s)
331
+ ...
266
332
 
267
- #### Improved Ignore System
268
- - **`.dotxignore` files** replace CLI `-i/--ignore` option (breaking change)
269
- - Full gitignore-style pattern syntax support
270
- - Nested `.dotxignore` files in subdirectories
271
- - Global ignore file at `~/.config/dotx/ignore`
272
- - Negation patterns (`!important.conf`)
333
+ This will rebuild the database with the discovered installations.
334
+ Continue? [y/N]: y
273
335
 
274
- #### Quality Improvements
275
- - Pre-commit hooks with ruff, pyrefly, pytest
276
- - Modern Python type annotations throughout
277
- - Better logging with loguru
278
- - Comprehensive code documentation and comments
336
+ Recorded 15 installation(s) in database.
279
337
 
280
- ### Migration from older versions
338
+ Cleaning orphaned entries...
339
+ ✓ Removed 3 orphaned entry(ies).
340
+ ```
281
341
 
282
- **Breaking change in v1.0.0:** The `-i/--ignore` command-line option has been removed in favor of `.dotxignore` files.
342
+ **When to use `--clean`:**
343
+ - After manually removing symlinks
344
+ - After uninstalling packages without using `dotx uninstall`
345
+ - During regular maintenance to keep database accurate
346
+ - When migrating or reorganizing dotfiles
283
347
 
284
- If you were using:
285
- ```bash
286
- dotx --ignore=README.* --ignore=.mypy_cache install bash
287
- ```
348
+ **Important:** `--clean` removes database entries for files that don't exist. Always preview with `--dry-run` first to ensure you're not removing entries you want to keep.
288
349
 
289
- Now create a `.dotxignore` file in your package:
290
- ```bash
291
- +$ cat > bash/.dotxignore <<EOF
292
- README.*
293
- .mypy_cache
294
- EOF
350
+ ### How it works
295
351
 
296
- +$ dotx install bash
297
- ```
352
+ *Documentation to be expanded*
353
+
354
+ ### Changelog
298
355
 
299
- Or use the global ignore file at `~/.config/dotx/ignore` for patterns that apply to all packages.
356
+ See [CHANGELOG.md](CHANGELOG.md) for version history and release notes.
300
357
 
301
358
  ## Development
302
359
 
@@ -367,10 +424,16 @@ This removes:
367
424
 
368
425
  **Note:** Add `.` at the end (`git clean -fdx .`) to limit cleanup to the current directory only.
369
426
 
370
- ### What's next
427
+ ### Shell Completions
428
+
429
+ dotx includes automatic shell completion via Typer:
430
+
431
+ ```bash
432
+ # Install completion for your shell
433
+ dotx --install-completion
434
+
435
+ # Or show the completion script to customize it
436
+ dotx --show-completion
437
+ ```
371
438
 
372
- Potential future enhancements:
373
- * Support for templates and variable substitution in dotfiles
374
- * Hooks system for running commands before/after installation
375
- * Conflict resolution strategies for overlapping packages
376
- * Shell completions for bash/zsh/fish
439
+ Supports Bash, Zsh, Fish, and PowerShell automatically.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dotx"
3
- version = "2.1.0"
3
+ version = "2.2.1"
4
4
  description = "A command-line tool to install a link-farm to your dotfiles"
5
5
  authors = [
6
6
  { name = "Wolf", email = "Wolf@zv.cx" }
@@ -0,0 +1,119 @@
1
+ """
2
+ Command-line interface for dotx.
3
+
4
+ This module defines the CLI app structure and global options. Individual commands
5
+ are defined in the commands subpackage.
6
+ """
7
+
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Annotated, Optional
11
+
12
+ import click
13
+ import typer
14
+ from loguru import logger
15
+
16
+ from dotx import __version__, __homepage__
17
+ from dotx.options import set_option
18
+
19
+ # Create the Typer app
20
+ app = typer.Typer(
21
+ help="Manage a link farm: (un)install groups of links from source packages.",
22
+ no_args_is_help=True,
23
+ epilog=f"dotx version {__version__} | {__homepage__}",
24
+ )
25
+
26
+
27
+ def version_callback(value: bool):
28
+ """Handle --version flag."""
29
+ if value:
30
+ typer.echo(f"dotx version {__version__}")
31
+ raise typer.Exit()
32
+
33
+
34
+ def configure_logging(debug: bool, verbose: bool, log: Optional[Path]):
35
+ """Configure logging based on CLI options."""
36
+ logger.remove() # Remove default handler
37
+
38
+ # Determine log level
39
+ if debug:
40
+ level = "DEBUG"
41
+ elif verbose:
42
+ level = "INFO"
43
+ else:
44
+ level = "WARNING"
45
+
46
+ # Add handler
47
+ if log:
48
+ logger.add(log, level=level)
49
+ else:
50
+ logger.add(sys.stderr, level=level)
51
+
52
+
53
+ @app.callback()
54
+ def main(
55
+ ctx: click.Context,
56
+ debug: Annotated[
57
+ bool,
58
+ typer.Option("--debug/--no-debug", help="Enable debug logging"),
59
+ ] = False,
60
+ verbose: Annotated[
61
+ bool,
62
+ typer.Option("--verbose/--quiet", help="Enable verbose output / suppress output"),
63
+ ] = False,
64
+ log: Annotated[
65
+ Optional[Path],
66
+ typer.Option(help="Where to write the log (defaults to stderr)"),
67
+ ] = None,
68
+ target: Annotated[
69
+ Optional[Path],
70
+ typer.Option(
71
+ help="Where to install (defaults to $HOME)",
72
+ exists=True,
73
+ file_okay=False,
74
+ dir_okay=True,
75
+ writable=True,
76
+ ),
77
+ ] = None,
78
+ dry_run: Annotated[
79
+ bool,
80
+ typer.Option("--dry-run/--no-dry-run", help="Just echo; don't actually (un)install"),
81
+ ] = False,
82
+ version: Annotated[
83
+ Optional[bool],
84
+ typer.Option("--version", "-V", callback=version_callback, is_eager=True, help="Show version and exit."),
85
+ ] = None,
86
+ ):
87
+ """
88
+ Manage a link farm: (un)install groups of links from source packages.
89
+
90
+ Global options like --debug, --verbose, and --target apply to all commands.
91
+ """
92
+ configure_logging(debug, verbose, log)
93
+
94
+ # Store options in context for commands to access
95
+ ctx.ensure_object(dict)
96
+ if target:
97
+ ctx.obj["TARGET"] = target
98
+ set_option("TARGET", target, ctx)
99
+
100
+ # Set global options
101
+ set_option("DEBUG", debug, ctx)
102
+ set_option("VERBOSE", verbose, ctx)
103
+ set_option("DRYRUN", dry_run, ctx)
104
+
105
+ if log:
106
+ set_option("LOG", log, ctx)
107
+
108
+
109
+ # Register commands from submodules
110
+ from dotx.commands import install_cmd, uninstall_cmd, database
111
+
112
+ install_cmd.register_command(app)
113
+ uninstall_cmd.register_command(app)
114
+ database.register_commands(app)
115
+
116
+
117
+ def cli():
118
+ """Entry point for the CLI."""
119
+ app()
@@ -0,0 +1 @@
1
+ """CLI commands for dotx."""