dploy 0.1.3__tar.gz → 0.2.0rc1__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.
- dploy-0.2.0rc1/.gitattributes +5 -0
- dploy-0.2.0rc1/.github/workflows/ci.yml +54 -0
- dploy-0.2.0rc1/.github/workflows/release.yaml +50 -0
- dploy-0.2.0rc1/.gitignore +16 -0
- dploy-0.2.0rc1/AGENTS.md +21 -0
- dploy-0.2.0rc1/CHANGELOG.md +233 -0
- dploy-0.2.0rc1/CLAUDE.md +1 -0
- dploy-0.2.0rc1/CONTEXT.md +105 -0
- dploy-0.2.0rc1/PKG-INFO +121 -0
- dploy-0.1.3/PKG-INFO → dploy-0.2.0rc1/README.md +44 -21
- dploy-0.2.0rc1/docs/adr/0001-windows-permission-validation.md +67 -0
- dploy-0.2.0rc1/docs/agents/domain.md +51 -0
- dploy-0.2.0rc1/docs/agents/issue-tracker.md +45 -0
- dploy-0.2.0rc1/docs/agents/triage-labels.md +13 -0
- dploy-0.2.0rc1/dploy/__init__.py +94 -0
- {dploy-0.1.3 → dploy-0.2.0rc1}/dploy/__main__.py +17 -17
- dploy-0.2.0rc1/dploy/_winaccess.py +203 -0
- dploy-0.2.0rc1/dploy/actions.py +207 -0
- dploy-0.2.0rc1/dploy/cli.py +173 -0
- {dploy-0.1.3 → dploy-0.2.0rc1}/dploy/error.py +49 -37
- dploy-0.2.0rc1/dploy/ignore.py +96 -0
- dploy-0.2.0rc1/dploy/linkcmd.py +119 -0
- dploy-0.2.0rc1/dploy/main.py +138 -0
- dploy-0.2.0rc1/dploy/py.typed +0 -0
- dploy-0.2.0rc1/dploy/stowcmd.py +711 -0
- dploy-0.2.0rc1/dploy/utils.py +225 -0
- {dploy-0.1.3 → dploy-0.2.0rc1}/dploy/version.py +5 -5
- dploy-0.2.0rc1/invoke.yaml +2 -0
- dploy-0.2.0rc1/pyproject.toml +100 -0
- dploy-0.2.0rc1/tasks.py +123 -0
- dploy-0.2.0rc1/tests/__init__.py +0 -0
- dploy-0.2.0rc1/tests/conftest.py +231 -0
- dploy-0.2.0rc1/tests/test_clean.py +140 -0
- dploy-0.2.0rc1/tests/test_cli.py +159 -0
- dploy-0.2.0rc1/tests/test_ignore.py +228 -0
- dploy-0.2.0rc1/tests/test_link.py +129 -0
- dploy-0.2.0rc1/tests/test_stow.py +499 -0
- dploy-0.2.0rc1/tests/test_unstow.py +517 -0
- dploy-0.2.0rc1/tests/test_utils.py +271 -0
- dploy-0.2.0rc1/tests/utils.py +249 -0
- dploy-0.2.0rc1/uv.lock +476 -0
- dploy-0.1.3/README.md +0 -63
- dploy-0.1.3/dploy/__init__.py +0 -35
- dploy-0.1.3/dploy/actions.py +0 -217
- dploy-0.1.3/dploy/cli.py +0 -114
- dploy-0.1.3/dploy/ignore.py +0 -67
- dploy-0.1.3/dploy/linkcmd.py +0 -81
- dploy-0.1.3/dploy/main.py +0 -125
- dploy-0.1.3/dploy/stowcmd.py +0 -442
- dploy-0.1.3/dploy/utils.py +0 -123
- dploy-0.1.3/pyproject.toml +0 -36
- {dploy-0.1.3 → dploy-0.2.0rc1}/LICENSE.txt +0 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# This checkout is shared between Windows and Linux (via Dropbox), so the same
|
|
2
|
+
# physical files are opened by both. Normalize to LF everywhere -- including in
|
|
3
|
+
# the working tree on Windows -- so that editing from one side does not rewrite
|
|
4
|
+
# every file from the other side's point of view.
|
|
5
|
+
* text=auto eol=lf
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ master ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ master ]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
|
|
13
|
+
runs-on: ${{ matrix.os }}
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
18
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
# hatch-vcs reads the version from tags, so it needs the full history.
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
|
|
26
|
+
- name: Enable symlinks on Windows
|
|
27
|
+
if: runner.os == 'Windows'
|
|
28
|
+
run: |
|
|
29
|
+
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /v "AllowDevelopmentWithoutDevLicense" /d 1 /f
|
|
30
|
+
git config --global core.symlinks true
|
|
31
|
+
|
|
32
|
+
- name: Install uv
|
|
33
|
+
uses: astral-sh/setup-uv@v5
|
|
34
|
+
with:
|
|
35
|
+
enable-cache: true
|
|
36
|
+
cache-dependency-glob: "uv.lock"
|
|
37
|
+
|
|
38
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
39
|
+
run: uv python install ${{ matrix.python-version }}
|
|
40
|
+
|
|
41
|
+
- name: Install dependencies
|
|
42
|
+
run: uv sync --all-groups
|
|
43
|
+
|
|
44
|
+
- name: Lint (pylint, ruff, ty)
|
|
45
|
+
run: uv run invoke lint
|
|
46
|
+
|
|
47
|
+
- name: Reformat Check (ruff)
|
|
48
|
+
run: uv run invoke reformat-check
|
|
49
|
+
|
|
50
|
+
- name: Metrics (radon)
|
|
51
|
+
run: uv run invoke metrics
|
|
52
|
+
|
|
53
|
+
- name: Test (pytest)
|
|
54
|
+
run: uv run invoke test
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI when a version tag is pushed, for example:
|
|
4
|
+
# git tag 0.2.0 && git push origin 0.2.0
|
|
5
|
+
# The package version comes from the tag (hatch-vcs), so there is no version
|
|
6
|
+
# to edit by hand. Before tagging, set the date in CHANGELOG.md.
|
|
7
|
+
#
|
|
8
|
+
# One-time setup on PyPI: add this repository and workflow (release.yaml) as a
|
|
9
|
+
# trusted publisher for the project, with the environment name "pypi".
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
push:
|
|
13
|
+
tags:
|
|
14
|
+
- "[0-9]+.[0-9]+.[0-9]+*"
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
name: Build distributions
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
# hatch-vcs reads the version from tags, so it needs the full history.
|
|
24
|
+
fetch-depth: 0
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v5
|
|
28
|
+
|
|
29
|
+
- name: Build
|
|
30
|
+
run: uv build
|
|
31
|
+
|
|
32
|
+
- uses: actions/upload-artifact@v4
|
|
33
|
+
with:
|
|
34
|
+
name: dist
|
|
35
|
+
path: dist/
|
|
36
|
+
|
|
37
|
+
publish:
|
|
38
|
+
name: Publish to PyPI
|
|
39
|
+
needs: build
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
environment: pypi
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write # required for PyPI trusted publishing
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/download-artifact@v4
|
|
46
|
+
with:
|
|
47
|
+
name: dist
|
|
48
|
+
path: dist/
|
|
49
|
+
|
|
50
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
dploy-0.2.0rc1/AGENTS.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# dploy
|
|
2
|
+
|
|
3
|
+
A command-line stow/link/unstow utility for managing dotfiles and other
|
|
4
|
+
symlinked file trees.
|
|
5
|
+
|
|
6
|
+
## Agent skills
|
|
7
|
+
|
|
8
|
+
### Issue tracker
|
|
9
|
+
|
|
10
|
+
Issues live as GitHub issues in `arecarn/dploy`, managed with the `gh` CLI. See
|
|
11
|
+
`docs/agents/issue-tracker.md`.
|
|
12
|
+
|
|
13
|
+
### Triage labels
|
|
14
|
+
|
|
15
|
+
Default canonical role names (`needs-triage`, `needs-info`, `ready-for-agent`,
|
|
16
|
+
`ready-for-human`, `wontfix`). See `docs/agents/triage-labels.md`.
|
|
17
|
+
|
|
18
|
+
### Domain docs
|
|
19
|
+
|
|
20
|
+
Single-context: `CONTEXT.md` and `docs/adr/` at the repo root (created lazily,
|
|
21
|
+
absence is not an error). See `docs/agents/domain.md`.
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Change Log
|
|
2
|
+
|
|
3
|
+
The format of this change log is based on [Keep a Changelog](http://keepachangelog.com/)
|
|
4
|
+
|
|
5
|
+
All changes documented here should be written with the goal give the end-user
|
|
6
|
+
(not other developers) a summarized view of the changes since the last release,
|
|
7
|
+
organized by order of importance.
|
|
8
|
+
|
|
9
|
+
## [0.2.0] - Unreleased
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added a `--skip-conflicts` flag to `stow` that links everything that
|
|
14
|
+
doesn't conflict with an existing, unmanaged file instead of aborting the
|
|
15
|
+
whole command. Dploy exits with status `2` when some files were skipped.
|
|
16
|
+
- Added a `--no-folding` flag to `stow` and `unstow`, matching GNU Stow's
|
|
17
|
+
flag of the same name, that keeps each file as its own individual link
|
|
18
|
+
instead of folding a destination directory into one link.
|
|
19
|
+
- Added a `--dotfiles` flag to `stow` and `unstow`, matching GNU Stow's flag
|
|
20
|
+
of the same name: a package entry named `dot-foo` is linked as `.foo`.
|
|
21
|
+
`unstow` removes links by what they point at, so it does not need the flag.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **Breaking:** Renamed `source`/`sources`/`dest` to `package`/`packages`/
|
|
26
|
+
`destination` across the public API and the CLI, to match the terms
|
|
27
|
+
`CONTEXT.md` defines. This affects the `stow`, `unstow`, and `clean`
|
|
28
|
+
function parameters and CLI arguments. The `link` command's argument stays
|
|
29
|
+
`source`, since it takes a single file or directory, not a package.
|
|
30
|
+
- Switch to uv for dependency management instead of Poetry.
|
|
31
|
+
- Use hatchling as the build system.
|
|
32
|
+
- Switch CI from Travis CI and AppVeyor to GitHub Actions.
|
|
33
|
+
- Move Pylint configuration to pyproject.toml and remove in-code suppressions.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- On Windows, a link to a directory is now created as a directory symlink
|
|
38
|
+
instead of a file symlink, which did not work.
|
|
39
|
+
- On Windows, existing links are now recognized as pointing at their
|
|
40
|
+
package. Windows reports link targets with a `\\?\` prefix, which made
|
|
41
|
+
every comparison with the package path fail.
|
|
42
|
+
- On Windows, dploy now decides whether two paths are the same file by asking
|
|
43
|
+
the file system instead of comparing path text, so a different spelling of
|
|
44
|
+
one path (letter case, short names) no longer counts as a different file.
|
|
45
|
+
- An ignore pattern the file system rejects, which Windows does for some
|
|
46
|
+
patterns POSIX accepts, is now skipped instead of crashing stow, unstow
|
|
47
|
+
and clean.
|
|
48
|
+
- On Windows, permission checks now read the file's ACL instead of only the
|
|
49
|
+
read-only flag, so an unreadable or unwritable path is reported before
|
|
50
|
+
anything changes rather than raising `PermissionError` part way through.
|
|
51
|
+
- Blank lines in `.dploystowignore`, or an empty `--ignore` pattern, no
|
|
52
|
+
longer crash stow/unstow/clean.
|
|
53
|
+
- Stowing a second package that shares a directory two or more levels deep
|
|
54
|
+
with an already-stowed package no longer writes into the first package's
|
|
55
|
+
source tree.
|
|
56
|
+
- Recursive ignore patterns, like `**/*.swp`, no longer cause dploy to skip
|
|
57
|
+
the whole folder a matching file lives in, including when that folder is
|
|
58
|
+
shared with another package being stowed.
|
|
59
|
+
- `unstow` no longer leaves behind an empty directory when all of its
|
|
60
|
+
contents are removed within the same run, for example a subdirectory
|
|
61
|
+
cleared while its parent directory only contained that one entry.
|
|
62
|
+
- `clean` now removes dangling links. It previously removed nothing, because
|
|
63
|
+
it could not match a link to its package unless the package sat directly in
|
|
64
|
+
the working directory and the link's target had no `..` in it. An unreadable
|
|
65
|
+
directory is now reported as an error instead of crashing.
|
|
66
|
+
- `link` now reports a clean error when the destination's parent is a file
|
|
67
|
+
instead of a directory. It previously crashed with a traceback.
|
|
68
|
+
|
|
69
|
+
## [0.1.3] - 2026-02-13
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
|
|
73
|
+
- Added a `dploy clean` subcommand.
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
|
|
77
|
+
- Switch to Poetry for packaging instead of setuptools.
|
|
78
|
+
- Require at least Python >= 3.10.
|
|
79
|
+
- Use black for auto formatting instead of yapf.
|
|
80
|
+
- Use custom *DployError* exceptions.
|
|
81
|
+
- Version is now sourced from pyproject.toml via importlib.metadata.
|
|
82
|
+
|
|
83
|
+
### Fixed
|
|
84
|
+
|
|
85
|
+
- Print syntax help if no valid subcommand was provided.
|
|
86
|
+
- Fixed pytest.
|
|
87
|
+
- Fixed invoke tasks to work with Poetry and Python 3.13.
|
|
88
|
+
|
|
89
|
+
### Removed
|
|
90
|
+
|
|
91
|
+
- Removed requirements.txt in favor of pyproject.toml dependency groups.
|
|
92
|
+
|
|
93
|
+
## [0.1.2] - 2017-10-26
|
|
94
|
+
|
|
95
|
+
### Changed
|
|
96
|
+
|
|
97
|
+
- Renamed the CLI --quiet option to --silent because it better reflects the
|
|
98
|
+
effect of the option
|
|
99
|
+
|
|
100
|
+
### Fixed
|
|
101
|
+
|
|
102
|
+
- Fix bug causing unstow to delete dest directory when unfolding.
|
|
103
|
+
When unstowing and nearly all actions have been collected additional checking
|
|
104
|
+
to find candidates for folding i.e. when a directory contains symlinks to
|
|
105
|
+
files that all share the same parent directory. It just so happens that the
|
|
106
|
+
dest directory passed into unstow could also meet this same criteria and would
|
|
107
|
+
be deleted in error.
|
|
108
|
+
|
|
109
|
+
- Produce a helpful error when stowing or unstowing with duplicate sources.
|
|
110
|
+
Before stow would fail, when conflicts were found, and unstow would succeed in
|
|
111
|
+
unstowing a duplicate source the first time, but fail after trying to unstow
|
|
112
|
+
nothing. By catching the bug before hand the error message is much clearer.
|
|
113
|
+
|
|
114
|
+
- Fix bug stowing or linking paths that cannot be relative to each other and
|
|
115
|
+
caused a silent failure.
|
|
116
|
+
e.g. with windows paths: `dploy stow C:\some\path D:\other\Path`
|
|
117
|
+
Since the symbolic links can't use a relative path fallback to the absolute
|
|
118
|
+
version of the path passed in.
|
|
119
|
+
|
|
120
|
+
## [0.1.1] - 2016-12-29
|
|
121
|
+
|
|
122
|
+
### Fix
|
|
123
|
+
|
|
124
|
+
- Added a MANIFEST.in to fix installation via PyPi
|
|
125
|
+
|
|
126
|
+
## [0.1.0] - 2016-12-29
|
|
127
|
+
|
|
128
|
+
### Changed
|
|
129
|
+
|
|
130
|
+
- Added Dates to Change log releases
|
|
131
|
+
|
|
132
|
+
### Fixed
|
|
133
|
+
|
|
134
|
+
- Fixed change log formatting
|
|
135
|
+
- Fix PyPi Package so it can be installed
|
|
136
|
+
|
|
137
|
+
## [0.0.5] - 2016-12-28
|
|
138
|
+
|
|
139
|
+
### Added
|
|
140
|
+
|
|
141
|
+
- Added --ignore argument to stow and unstow commands, to specify patterns file
|
|
142
|
+
to ignore.
|
|
143
|
+
- Added reading of .dploystowignore files in the directories of sources for
|
|
144
|
+
ignore patterns that are additional to those specified via --ignore
|
|
145
|
+
- Added optional is_silent & is_dry_run arguments to dploy.stow() dploy.unstow()
|
|
146
|
+
and dploy.link(), This is analogous to the --dry-run and --quiet command line
|
|
147
|
+
arguments. These function arguments default to is_silent=True and
|
|
148
|
+
is_dry_run=False.
|
|
149
|
+
- Added redundant check to make sure dploy never deletes anything other than a
|
|
150
|
+
symbolic link
|
|
151
|
+
- Check for source and dest new consideration was taken for sources
|
|
152
|
+
and dests directories that have invalid execute permissions.
|
|
153
|
+
|
|
154
|
+
### Changed
|
|
155
|
+
|
|
156
|
+
- Check for additional issues with sub commands that are similar to the initial
|
|
157
|
+
checks done on the input of stow and unstow
|
|
158
|
+
- Prevent redundant errors when the src or dest are not directories
|
|
159
|
+
- Clarify some error messages
|
|
160
|
+
- Display the user inputted source and dest paths instead of absolute paths in
|
|
161
|
+
the output
|
|
162
|
+
- Clarify error messages for file and symbolic link conflicts
|
|
163
|
+
- Make the output of dploy stow and unstow deterministic across file systems
|
|
164
|
+
- Changed the output of failing dploy sub commands so they print as many
|
|
165
|
+
detected issues as possible before aborting
|
|
166
|
+
- Print all conflicts while stowing instead of just the first conflict, and
|
|
167
|
+
print what exactly the conflict is
|
|
168
|
+
|
|
169
|
+
### Fixed
|
|
170
|
+
|
|
171
|
+
- Fixed issue when unstowing where some stowed packages directories created
|
|
172
|
+
during the stowing process via unfolding would not be deleted.
|
|
173
|
+
- Fix issue unstowing a folded dir with a stray link
|
|
174
|
+
- This fixed the following scenario: Given a dest directory with stowed
|
|
175
|
+
packages that share a folded directory, that also contains a stray link
|
|
176
|
+
along with the links created by stowing. When the stowed packages are
|
|
177
|
+
unstowed Then the folded directory was re-folded using the parent
|
|
178
|
+
directory of the single stray link and possibly linking new files that
|
|
179
|
+
were never intended to be linked there. When what was desired was the
|
|
180
|
+
directory to just remain with the single stray symlink.
|
|
181
|
+
- Fix an improperly handled expetion that occurred when unstowing a package that
|
|
182
|
+
had it's destination directories execute permission unset.
|
|
183
|
+
|
|
184
|
+
## [0.0.4] - 2016-09-13
|
|
185
|
+
|
|
186
|
+
### Added
|
|
187
|
+
|
|
188
|
+
- Add folding of the remaining links that would be around after calling unstow
|
|
189
|
+
- Add Checks for conflicts between multiple sources for stow
|
|
190
|
+
- Add checking to see if args are directories for stow and unstow
|
|
191
|
+
- Add check the permissions for source and dest before running a command
|
|
192
|
+
- Add error handling for source permissions errors for stow and unstow
|
|
193
|
+
- CLI: Add a --dry-run flag to show what would be done
|
|
194
|
+
- CLI: Add a --quiet option to suppress normal output
|
|
195
|
+
- CLI: Add handling for canceling the program with CTRL-C
|
|
196
|
+
- CLI: Add a message for case when a source is already unlinked
|
|
197
|
+
|
|
198
|
+
### Changed
|
|
199
|
+
|
|
200
|
+
- Relicense under MIT
|
|
201
|
+
- Make dploy module usage silent
|
|
202
|
+
- Clarify message when a source argument is the same the dest argument
|
|
203
|
+
- Have the dploy module throw exceptions that the CLI module would handle
|
|
204
|
+
instead of just printing to stdout
|
|
205
|
+
|
|
206
|
+
### Fixed
|
|
207
|
+
|
|
208
|
+
- CLI: Fix link to take only take one source
|
|
209
|
+
- Fix link source arg so it takes a string not a list
|
|
210
|
+
- Fix console output to print the correct command name e.g. stow, link, and
|
|
211
|
+
unstow
|
|
212
|
+
- Fix issue where files could be deleted during unstow folding
|
|
213
|
+
- Fix bug that would cause an unexpected and unhanded exception when there was
|
|
214
|
+
link in the destination directory that pointed to a non existing location in
|
|
215
|
+
the source.
|
|
216
|
+
- Fix issue in stow and unstow where source and dest could be the same. This
|
|
217
|
+
issue made it possible to delete files when unstow had the same
|
|
218
|
+
parameters for both source and dest. It also didn't make sense to try to stow
|
|
219
|
+
a directory into itself, since there will always be conflicts.
|
|
220
|
+
|
|
221
|
+
## [0.0.3] - 2016-04-11
|
|
222
|
+
|
|
223
|
+
### Added
|
|
224
|
+
|
|
225
|
+
- Adds support for python 3.3
|
|
226
|
+
- Add an unstow command to undo stowing
|
|
227
|
+
|
|
228
|
+
### Changed
|
|
229
|
+
|
|
230
|
+
- Stow command is run in two passes and check for conflicts first before making
|
|
231
|
+
any changes
|
|
232
|
+
|
|
233
|
+
- General bug fixes and improvements.
|
dploy-0.2.0rc1/CLAUDE.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# dploy
|
|
2
|
+
|
|
3
|
+
dploy creates and removes symbolic links so that the contents of one directory
|
|
4
|
+
appear inside another, in the manner of GNU Stow, on Windows, Linux, and macOS.
|
|
5
|
+
|
|
6
|
+
## Language
|
|
7
|
+
|
|
8
|
+
### What gets linked
|
|
9
|
+
|
|
10
|
+
**Package**:
|
|
11
|
+
A directory whose contents are linked into a destination as a unit. Packages are
|
|
12
|
+
always named explicitly on the command line; dploy has no directory it searches
|
|
13
|
+
for them.
|
|
14
|
+
_Avoid_: source, source directory, stow package
|
|
15
|
+
|
|
16
|
+
**Destination**:
|
|
17
|
+
The directory a package's contents are linked into.
|
|
18
|
+
_Avoid_: target, target directory, dest
|
|
19
|
+
|
|
20
|
+
**Target**:
|
|
21
|
+
The path a symbolic link points at. A link's target is what it refers to, never
|
|
22
|
+
where it lives.
|
|
23
|
+
_Avoid_: referent, linked-to path
|
|
24
|
+
|
|
25
|
+
**Dangling link**:
|
|
26
|
+
A symbolic link whose target no longer exists.
|
|
27
|
+
_Avoid_: broken link, orphaned link, stale link
|
|
28
|
+
|
|
29
|
+
### Dot-file names
|
|
30
|
+
|
|
31
|
+
**Dotfile translation**:
|
|
32
|
+
With `--dotfiles`, linking a package entry named `dot-foo` under the destination
|
|
33
|
+
name `.foo`. A name where `dot-` is followed by nothing or by a dot is never
|
|
34
|
+
translated.
|
|
35
|
+
_Avoid_: dot renaming, dot expansion
|
|
36
|
+
|
|
37
|
+
**Literal name**:
|
|
38
|
+
A package entry's own name, such as `dot-foo`.
|
|
39
|
+
_Avoid_: original name, source name
|
|
40
|
+
|
|
41
|
+
**Translated name**:
|
|
42
|
+
The name dotfile translation gives an entry, such as `.foo`. For an entry that is
|
|
43
|
+
not translated, it is the same as the literal name.
|
|
44
|
+
_Avoid_: dot name, renamed name
|
|
45
|
+
|
|
46
|
+
**Matching by target**:
|
|
47
|
+
How unstow finds the links to remove: a link is removed because its target is
|
|
48
|
+
inside the package, whichever of the entry's two names it carries. A file or link
|
|
49
|
+
that does not point into the package is never touched.
|
|
50
|
+
_Avoid_: name matching, flag matching
|
|
51
|
+
|
|
52
|
+
### Operations
|
|
53
|
+
|
|
54
|
+
**Stow**:
|
|
55
|
+
Linking the contents of a package into a destination. Stowing is idempotent:
|
|
56
|
+
stowing an already-stowed package reports the links as already in place.
|
|
57
|
+
_Avoid_: install, deploy, apply
|
|
58
|
+
|
|
59
|
+
**Unstow**:
|
|
60
|
+
Removing the links a stow produced, recognised by their target rather than by
|
|
61
|
+
their name. Also idempotent.
|
|
62
|
+
_Avoid_: uninstall, remove, undeploy
|
|
63
|
+
|
|
64
|
+
**Clean**:
|
|
65
|
+
Removing dangling links in a destination that point into a given package. Unlike
|
|
66
|
+
unstow, it acts on links whose targets are already gone.
|
|
67
|
+
_Avoid_: prune, sweep, garbage collect
|
|
68
|
+
|
|
69
|
+
**Link**:
|
|
70
|
+
Creating a single symbolic link at an exact path, rather than linking a whole
|
|
71
|
+
package's contents. Where the distinction matters, say "the link command" for
|
|
72
|
+
the operation and "a symbolic link" for the thing.
|
|
73
|
+
_Avoid_: symlink (as the name of the operation)
|
|
74
|
+
|
|
75
|
+
**Folding**:
|
|
76
|
+
Replacing a destination directory whose links all point into one package
|
|
77
|
+
directory with a single link to that directory.
|
|
78
|
+
_Avoid_: collapsing, compacting
|
|
79
|
+
|
|
80
|
+
**Unfolding**:
|
|
81
|
+
Replacing a link to a directory with a real directory containing links to that
|
|
82
|
+
directory's contents, so a second package can contribute entries alongside the
|
|
83
|
+
first.
|
|
84
|
+
_Avoid_: expanding, exploding
|
|
85
|
+
|
|
86
|
+
### How work is described
|
|
87
|
+
|
|
88
|
+
**Action**:
|
|
89
|
+
A single filesystem change dploy intends to make: creating a link, removing a
|
|
90
|
+
link, creating a directory, removing a directory. Actions are collected and
|
|
91
|
+
validated as a set before any of them run, so a command either applies fully or
|
|
92
|
+
not at all.
|
|
93
|
+
_Avoid_: operation, step, task, change
|
|
94
|
+
|
|
95
|
+
**Conflict**:
|
|
96
|
+
A reason a collected set of actions cannot be applied, such as a destination
|
|
97
|
+
entry that is not a link dploy created, or two packages claiming the same
|
|
98
|
+
destination path. Conflicts are reported together and abort the command before
|
|
99
|
+
any action runs.
|
|
100
|
+
_Avoid_: error, clash, collision
|
|
101
|
+
|
|
102
|
+
**Ignore pattern**:
|
|
103
|
+
A glob that excludes matching entries of a package from being linked. Patterns
|
|
104
|
+
come from the command line or from a `.dploystowignore` file beside the package.
|
|
105
|
+
_Avoid_: exclude pattern, skip pattern, filter
|
dploy-0.2.0rc1/PKG-INFO
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: dploy
|
|
3
|
+
Version: 0.2.0rc1
|
|
4
|
+
Summary: Provides functionality similar to GNU Stow as a cross platform CLI tool and Python 3 module
|
|
5
|
+
Project-URL: Homepage, https://github.com/arecarn/dploy
|
|
6
|
+
Author-email: Ryan Carney <arecarn@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE.txt
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Dploy
|
|
22
|
+
|
|
23
|
+
Dploy is a tool for creating symbolic links similarly to [GNU
|
|
24
|
+
Stow](https://www.gnu.org/software/stow/). It is provided as a CLI tool and
|
|
25
|
+
Python 3.10+ module and supports Windows, Linux, and OSX.
|
|
26
|
+
|
|
27
|
+
Dploy's command `stow` creates symbolic links to the contents of packages in a
|
|
28
|
+
specified destination directory. Repeating the
|
|
29
|
+
`stow` command with the same arguments will confirm that the contents of the
|
|
30
|
+
package have been symbolically linked.
|
|
31
|
+
|
|
32
|
+
Dploy's command `unstow` removes symbolic links that resulted from `stow`
|
|
33
|
+
commands. Repeating the `unstow` command with the same arguments will confirm
|
|
34
|
+
that the links to stowed packages have been removed.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
* Latest Release: `pip install dploy`
|
|
39
|
+
* Development Version: `pip install git+https://github.com/arecarn/dploy.git`
|
|
40
|
+
|
|
41
|
+
## Basic CLI Usage
|
|
42
|
+
|
|
43
|
+
* `dploy stow <package-directory>... <destination-directory>`
|
|
44
|
+
* `dploy unstow <package-directory>... <destination-directory>`
|
|
45
|
+
* `dploy clean <package-directory>... <destination-directory>`
|
|
46
|
+
* `dploy --help`
|
|
47
|
+
|
|
48
|
+
### Dot-file names
|
|
49
|
+
|
|
50
|
+
`stow --dotfiles` stows a package entry named `dot-something` as a destination
|
|
51
|
+
entry named `.something`:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
dploy stow --dotfiles ~/dotfiles/bash ~
|
|
55
|
+
# ~/dotfiles/bash/dot-bashrc -> ~/.bashrc
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This keeps the files visible in the package directory while they land as
|
|
59
|
+
dot-files in the destination.
|
|
60
|
+
|
|
61
|
+
`unstow` does not need `--dotfiles`. It finds links by what they point at, so it
|
|
62
|
+
removes them whether they are named `dot-something` or `.something`. It still
|
|
63
|
+
accepts the flag, for symmetry with `stow`; with it, an unrelated file already
|
|
64
|
+
named `.something` is reported as a conflict. `clean` is unaffected for the
|
|
65
|
+
same reason.
|
|
66
|
+
|
|
67
|
+
An entry whose name is `dot-` followed by nothing or by a dot (`dot-`,
|
|
68
|
+
`dot-.`, `dot-..`, `dot-.hidden`) is left untranslated, as GNU Stow does; the
|
|
69
|
+
first two would otherwise resolve to the destination directory or its parent.
|
|
70
|
+
|
|
71
|
+
## Rationale
|
|
72
|
+
|
|
73
|
+
Dploy started out as simple Python script to create symbolic links to my
|
|
74
|
+
dotfiles for Windows, Mac, and Linux. Over time I keep improving and tweaking my
|
|
75
|
+
script to suit my needs, but I was running into a problem. Keeping all the
|
|
76
|
+
files I wanted to link in a config file was becoming a real pain in the neck.
|
|
77
|
+
|
|
78
|
+
I started looking for another solution to solve my problem, and found many
|
|
79
|
+
alternatives but none of them seemed to be a good fit. The solution that seemed
|
|
80
|
+
the most promising was using GNU Stow. It seemed like the most simple elegant
|
|
81
|
+
solution to the problem. The only issue was that it didn't support Windows.
|
|
82
|
+
|
|
83
|
+
Then I thought to myself, why can't I just create my own version of Stow that
|
|
84
|
+
work on Windows, Linux and OSX. So after that my I started morphing
|
|
85
|
+
simple python script into what would become Dploy and learned a lot more about
|
|
86
|
+
python in the process.
|
|
87
|
+
|
|
88
|
+
## How does it compare with GNU Stow?
|
|
89
|
+
|
|
90
|
+
Below are just a few few major points of comparison between GNU stow and Dploy.
|
|
91
|
+
|
|
92
|
+
* Like GNU Stow Dploy runs in two passes. First by collecting the actions
|
|
93
|
+
required to complete the command and verifying that the command can
|
|
94
|
+
completed without any issues. If no issues are detected then the second
|
|
95
|
+
pass executes these actions are execute to complete the command. Otherwise
|
|
96
|
+
Dploy will exit and indicate why the command can not be completed. This way a
|
|
97
|
+
stow or unstow operation is atomic and never partially done.
|
|
98
|
+
|
|
99
|
+
* Like Stow, Dploy supports tree folding and tree unfolding. Like Stow's
|
|
100
|
+
`--no-folding`, passing `--no-folding` to `stow` or `unstow` disables
|
|
101
|
+
folding, so each file gets its own link inside a real directory.
|
|
102
|
+
|
|
103
|
+
* Unlike Stow, Dploy requires an explicit package(s) and a destination
|
|
104
|
+
directory.
|
|
105
|
+
|
|
106
|
+
* Unlike Stow, Dploy does not have any concept of ownership, but will only
|
|
107
|
+
operate on symbolic links and the creation or removal of directories for these
|
|
108
|
+
symbolic links.
|
|
109
|
+
|
|
110
|
+
* Unlike Stow, Dploy's `unstow` removes a destination directory that becomes
|
|
111
|
+
empty as a result of removing its symbolic links, even if that directory
|
|
112
|
+
existed before `stow` created any links inside it. Dploy keeps no state
|
|
113
|
+
across invocations, so it cannot distinguish a directory it created from
|
|
114
|
+
one that already existed.
|
|
115
|
+
|
|
116
|
+
* `stow`'s `--skip-conflicts` flag is the one opt-in exception to the
|
|
117
|
+
atomicity described above: files that conflict with an existing,
|
|
118
|
+
unmanaged destination entry are skipped and reported, while every other
|
|
119
|
+
file in the package is still linked. `dploy` exits with status `2` when
|
|
120
|
+
this happens, so a script can tell a partial stow apart from a full
|
|
121
|
+
success (status `0`) or a fatal error (status `1`).
|