devlaunch 0.0.9__tar.gz → 0.0.11__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 (22) hide show
  1. {devlaunch-0.0.9 → devlaunch-0.0.11}/.gitignore +3 -0
  2. {devlaunch-0.0.9 → devlaunch-0.0.11}/PKG-INFO +109 -3
  3. {devlaunch-0.0.9 → devlaunch-0.0.11}/README.md +108 -1
  4. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/dl.py +338 -82
  5. devlaunch-0.0.11/devlaunch/workspace_id.py +222 -0
  6. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/worktree/__init__.py +3 -0
  7. devlaunch-0.0.11/devlaunch/worktree/migration.py +264 -0
  8. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/worktree/storage.py +20 -7
  9. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/worktree/workspace_clone.py +77 -53
  10. {devlaunch-0.0.9 → devlaunch-0.0.11}/pyproject.toml +1 -2
  11. {devlaunch-0.0.9 → devlaunch-0.0.11}/LICENSE +0 -0
  12. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/__init__.py +0 -0
  13. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/aid.py +0 -0
  14. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/completion.py +0 -0
  15. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/completion_loader.py +0 -0
  16. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/completions/__init__.py +0 -0
  17. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/completions/dl.bash +0 -0
  18. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/gh_auth.py +0 -0
  19. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/worktree/branch_manager.py +0 -0
  20. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/worktree/config.py +0 -0
  21. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/worktree/models.py +0 -0
  22. {devlaunch-0.0.9 → devlaunch-0.0.11}/devlaunch/worktree/repo_manager.py +0 -0
@@ -184,3 +184,6 @@ logs/
184
184
 
185
185
  # uv is not this project's package manager (pixi.lock is authoritative)
186
186
  uv.lock
187
+
188
+ # Agent worktrees (local scratch; never committed)
189
+ .claude/worktrees/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devlaunch
3
- Version: 0.0.9
3
+ Version: 0.0.11
4
4
  Summary: DevLaunch - A streamlined CLI for devpod workspaces
5
5
  Project-URL: Source, https://github.com/blooop/devlaunch
6
6
  Project-URL: Home, https://github.com/blooop/devlaunch
@@ -8,7 +8,6 @@ Author-email: Austin Gregg-Smith <blooop@gmail.com>
8
8
  License-Expression: MIT
9
9
  License-File: LICENSE
10
10
  Requires-Dist: iterfzf>=1.0.0
11
- Requires-Dist: tomli-w>=1.0.0
12
11
  Requires-Dist: tomli>=2.0.0
13
12
  Provides-Extra: test
14
13
  Requires-Dist: coverage<=7.14.1,>=7.5.4; extra == 'test'
@@ -123,6 +122,83 @@ dl user/repo@branch # Create from specific branch
123
122
  dl ./path # Create from local path
124
123
  ```
125
124
 
125
+ ## Workspace IDs
126
+
127
+ `dl user/repo@branch` derives one id that names both the devpod workspace (what you
128
+ see in `dl --ls`) and the clone directory under `~/.cache/devlaunch/repos/`:
129
+
130
+ ```
131
+ <repo-slug>-<branch-slug>-<syllables> at most 38 characters
132
+
133
+ blooop/devlaunch@main -> devlaunch-main-zovomobo
134
+ blooop/devlaunch@feature/auth -> devlaunch-feature-auth-poliseno
135
+ blooop/devlaunch@feature-auth -> devlaunch-feature-auth-nesatabe
136
+ blooop/test_renv@nb4 -> test-renv-nb4-polenita
137
+ kinisi-robotics/kinisi_ros@ags-devcontainer-tooling-support
138
+ -> kinisi-ros-ags-devcontainer-t-lenevere
139
+ blooop/devlaunch@dependabot/github_actions/codecov/codecov-action-6
140
+ -> devlaunch-dependabot-codecov-sifivasa
141
+ ```
142
+
143
+ The eight-character syllable suffix is a hash of the full `(owner, repo, branch)` triple.
144
+ It is what makes the id unique: the readable part is shortened to fit the length limit,
145
+ and shortening it does not affect whether two branches share an id. Long branch names
146
+ drop whole `/`-separated middle segments before losing characters, so the part that
147
+ identifies the branch survives. Note the third and fourth lines above: `feature/auth` and
148
+ `feature-auth` read the same once slugged but are different branches, and they get
149
+ different ids.
150
+
151
+ Owner and repo are matched case-insensitively, the way GitHub treats them, so
152
+ `dl NVIDIA/cuda-samples@main` and `dl nvidia/cuda-samples@main` are the same workspace.
153
+ Branch names are case-sensitive, because git refs are.
154
+
155
+ URL specs (`dl github.com/owner/repo`) get an id in the same shape, with the suffix
156
+ hashed over the URL.
157
+
158
+ The id is also the container hostname, so it stays well inside the 38-character budget
159
+ to leave room for tools that add their own prefixes.
160
+
161
+ Branch names must be safe as both git refs and directory names — a name with a space or
162
+ a leading dash is rejected rather than quietly rewritten.
163
+
164
+ ### Upgrading from an older devlaunch
165
+
166
+ This id format is new, and the directories and containers on your machine were named by
167
+ the previous scheme. The first `dl user/repo…` command after upgrading migrates the cache
168
+ once and prints what it did. `dl --help`, `dl --version`, `dl --ls` and opening an existing
169
+ workspace by name do not trigger it.
170
+
171
+ **Your clone directories are renamed.** What was
172
+ `~/.cache/devlaunch/repos/blooop/devlaunch/main` becomes
173
+ `~/.cache/devlaunch/repos/blooop/devlaunch/devlaunch-main-zovomobo`. A workspace is a git
174
+ clone whose `origin` points at the `.bare` cache next to it, and `.bare` does not move, so
175
+ this is a plain rename: branches, history and **uncommitted changes all survive** — only
176
+ the folder name changes. `metadata.json` is updated in the same pass, so nothing is left
177
+ pointing at the old name.
178
+
179
+ **Your existing devpod containers keep their old ids and are orphaned.** The next
180
+ `dl user/repo@branch` builds a fresh container under the new id. dl does not delete
181
+ containers for you — deleting by id is how a running sidecar got destroyed the last time
182
+ something tried ([kinisi_ros#9766](https://github.com/kinisi-robotics/kinisi_ros/pull/9766)) —
183
+ so it prints a one-line notice with the count and writes the old ids to
184
+ `~/.cache/devlaunch/orphaned-workspaces.txt`. Remove them when you are ready:
185
+
186
+ ```bash
187
+ xargs -r -n1 devpod delete < ~/.cache/devlaunch/orphaned-workspaces.txt
188
+ ```
189
+
190
+ **A clone directory with no metadata record is left alone.** Nothing records which branch
191
+ it was cloned for, and the old directory name cannot be turned back into one — `feature/auth`
192
+ and `feature-auth` both became `feature-auth` — so a guessed name would be worse than no
193
+ rename. Those directories stay exactly where they are and are listed in
194
+ `~/.cache/devlaunch/unmigrated-clones.txt`.
195
+
196
+ Running dl again changes nothing: the migration is keyed on the `version` field in
197
+ `metadata.json`, not on directory names, so a branch that happens to look like a new-scheme
198
+ id is never mistaken for one. If a migration is interrupted, the next run finishes it — the
199
+ version is written last, in the same atomic save as the new paths, so it never claims more
200
+ than the filesystem has actually done.
201
+
126
202
  ## Workspace Commands
127
203
 
128
204
  | Command | Description |
@@ -199,7 +275,23 @@ stays in place — including one it was given before you set
199
275
  | `dl --prune-worktrees [days]` | Remove unused worktrees (default: 30 days) |
200
276
  | `dl --refresh` | Refresh completion cache |
201
277
  | `dl --help, -h` | Show this help |
202
- | `dl --version` | Show version |
278
+ | `dl --version` | Show version (an editable install also names the tree it runs from) |
279
+
280
+ A released install prints the version and nothing else. An install made in
281
+ editable mode says so and names the checkout it resolves to, so two builds of
282
+ the same version are told apart at a glance:
283
+
284
+ ```bash
285
+ $ dl --version
286
+ dl 0.0.9
287
+
288
+ $ dl-next --version # editable install of a working tree
289
+ dl 0.0.9 (dev, editable from /path/to/your/devlaunch)
290
+ ```
291
+
292
+ `aid --version` reports the same thing under its own name. The provenance comes
293
+ from the installed package's own PEP 610 metadata; an install that records none
294
+ just prints the bare version.
203
295
 
204
296
  ## Examples
205
297
 
@@ -221,6 +313,7 @@ dl blooop/devlaunch stop # Stop workspace
221
313
  - **GitHub Shorthand**: Use `owner/repo` instead of full URLs - automatically expands to `github.com/owner/repo`
222
314
  - **Branch Support**: Specify branches with `owner/repo@branch` syntax
223
315
  - **Fast Autocomplete**: Completion cache for ~3ms response time (vs ~700ms without cache)
316
+ - **One Round-Trip Per Question**: every `devpod` call costs ~0.45s, far more than `dl` itself, so a command reads the workspace list at most once — and `dl <ws> -- <cmd>` skips the extra round-trip that names an interactive prompt, since a one-shot command has none
224
317
 
225
318
  ## Worktree Backend
226
319
 
@@ -256,6 +349,19 @@ After running `dl --install`, you get intelligent tab completion:
256
349
  - File/directory paths when starting with `./`, `/`, or `~`
257
350
  - All global flags (`--ls`, `--install`, etc.) and workspace commands
258
351
 
352
+ ### How the completion cache stays current
353
+
354
+ The data behind completions lives in `~/.cache/devlaunch/completions.json`, and
355
+ building it means a `git ls-remote` per known repo — seconds of work. So it is
356
+ rebuilt in the background at most once an hour (the same interval the worktree
357
+ backend uses for lazy fetches), and at most once per `dl` invocation. Commands
358
+ that change your workspaces (starting, stopping or deleting one) rebuild it as
359
+ soon as they finish, regardless of when it was last built. Commands with no use
360
+ for it — `dl --help`, `dl --version` — do not touch it at all.
361
+
362
+ A branch created on a remote in the last hour may therefore not be offered yet.
363
+ `dl --refresh` rebuilds the cache immediately and ignores the interval.
364
+
259
365
  ## Development
260
366
 
261
367
  This project uses [pixi](https://pixi.sh) for environment management.
@@ -100,6 +100,83 @@ dl user/repo@branch # Create from specific branch
100
100
  dl ./path # Create from local path
101
101
  ```
102
102
 
103
+ ## Workspace IDs
104
+
105
+ `dl user/repo@branch` derives one id that names both the devpod workspace (what you
106
+ see in `dl --ls`) and the clone directory under `~/.cache/devlaunch/repos/`:
107
+
108
+ ```
109
+ <repo-slug>-<branch-slug>-<syllables> at most 38 characters
110
+
111
+ blooop/devlaunch@main -> devlaunch-main-zovomobo
112
+ blooop/devlaunch@feature/auth -> devlaunch-feature-auth-poliseno
113
+ blooop/devlaunch@feature-auth -> devlaunch-feature-auth-nesatabe
114
+ blooop/test_renv@nb4 -> test-renv-nb4-polenita
115
+ kinisi-robotics/kinisi_ros@ags-devcontainer-tooling-support
116
+ -> kinisi-ros-ags-devcontainer-t-lenevere
117
+ blooop/devlaunch@dependabot/github_actions/codecov/codecov-action-6
118
+ -> devlaunch-dependabot-codecov-sifivasa
119
+ ```
120
+
121
+ The eight-character syllable suffix is a hash of the full `(owner, repo, branch)` triple.
122
+ It is what makes the id unique: the readable part is shortened to fit the length limit,
123
+ and shortening it does not affect whether two branches share an id. Long branch names
124
+ drop whole `/`-separated middle segments before losing characters, so the part that
125
+ identifies the branch survives. Note the third and fourth lines above: `feature/auth` and
126
+ `feature-auth` read the same once slugged but are different branches, and they get
127
+ different ids.
128
+
129
+ Owner and repo are matched case-insensitively, the way GitHub treats them, so
130
+ `dl NVIDIA/cuda-samples@main` and `dl nvidia/cuda-samples@main` are the same workspace.
131
+ Branch names are case-sensitive, because git refs are.
132
+
133
+ URL specs (`dl github.com/owner/repo`) get an id in the same shape, with the suffix
134
+ hashed over the URL.
135
+
136
+ The id is also the container hostname, so it stays well inside the 38-character budget
137
+ to leave room for tools that add their own prefixes.
138
+
139
+ Branch names must be safe as both git refs and directory names — a name with a space or
140
+ a leading dash is rejected rather than quietly rewritten.
141
+
142
+ ### Upgrading from an older devlaunch
143
+
144
+ This id format is new, and the directories and containers on your machine were named by
145
+ the previous scheme. The first `dl user/repo…` command after upgrading migrates the cache
146
+ once and prints what it did. `dl --help`, `dl --version`, `dl --ls` and opening an existing
147
+ workspace by name do not trigger it.
148
+
149
+ **Your clone directories are renamed.** What was
150
+ `~/.cache/devlaunch/repos/blooop/devlaunch/main` becomes
151
+ `~/.cache/devlaunch/repos/blooop/devlaunch/devlaunch-main-zovomobo`. A workspace is a git
152
+ clone whose `origin` points at the `.bare` cache next to it, and `.bare` does not move, so
153
+ this is a plain rename: branches, history and **uncommitted changes all survive** — only
154
+ the folder name changes. `metadata.json` is updated in the same pass, so nothing is left
155
+ pointing at the old name.
156
+
157
+ **Your existing devpod containers keep their old ids and are orphaned.** The next
158
+ `dl user/repo@branch` builds a fresh container under the new id. dl does not delete
159
+ containers for you — deleting by id is how a running sidecar got destroyed the last time
160
+ something tried ([kinisi_ros#9766](https://github.com/kinisi-robotics/kinisi_ros/pull/9766)) —
161
+ so it prints a one-line notice with the count and writes the old ids to
162
+ `~/.cache/devlaunch/orphaned-workspaces.txt`. Remove them when you are ready:
163
+
164
+ ```bash
165
+ xargs -r -n1 devpod delete < ~/.cache/devlaunch/orphaned-workspaces.txt
166
+ ```
167
+
168
+ **A clone directory with no metadata record is left alone.** Nothing records which branch
169
+ it was cloned for, and the old directory name cannot be turned back into one — `feature/auth`
170
+ and `feature-auth` both became `feature-auth` — so a guessed name would be worse than no
171
+ rename. Those directories stay exactly where they are and are listed in
172
+ `~/.cache/devlaunch/unmigrated-clones.txt`.
173
+
174
+ Running dl again changes nothing: the migration is keyed on the `version` field in
175
+ `metadata.json`, not on directory names, so a branch that happens to look like a new-scheme
176
+ id is never mistaken for one. If a migration is interrupted, the next run finishes it — the
177
+ version is written last, in the same atomic save as the new paths, so it never claims more
178
+ than the filesystem has actually done.
179
+
103
180
  ## Workspace Commands
104
181
 
105
182
  | Command | Description |
@@ -176,7 +253,23 @@ stays in place — including one it was given before you set
176
253
  | `dl --prune-worktrees [days]` | Remove unused worktrees (default: 30 days) |
177
254
  | `dl --refresh` | Refresh completion cache |
178
255
  | `dl --help, -h` | Show this help |
179
- | `dl --version` | Show version |
256
+ | `dl --version` | Show version (an editable install also names the tree it runs from) |
257
+
258
+ A released install prints the version and nothing else. An install made in
259
+ editable mode says so and names the checkout it resolves to, so two builds of
260
+ the same version are told apart at a glance:
261
+
262
+ ```bash
263
+ $ dl --version
264
+ dl 0.0.9
265
+
266
+ $ dl-next --version # editable install of a working tree
267
+ dl 0.0.9 (dev, editable from /path/to/your/devlaunch)
268
+ ```
269
+
270
+ `aid --version` reports the same thing under its own name. The provenance comes
271
+ from the installed package's own PEP 610 metadata; an install that records none
272
+ just prints the bare version.
180
273
 
181
274
  ## Examples
182
275
 
@@ -198,6 +291,7 @@ dl blooop/devlaunch stop # Stop workspace
198
291
  - **GitHub Shorthand**: Use `owner/repo` instead of full URLs - automatically expands to `github.com/owner/repo`
199
292
  - **Branch Support**: Specify branches with `owner/repo@branch` syntax
200
293
  - **Fast Autocomplete**: Completion cache for ~3ms response time (vs ~700ms without cache)
294
+ - **One Round-Trip Per Question**: every `devpod` call costs ~0.45s, far more than `dl` itself, so a command reads the workspace list at most once — and `dl <ws> -- <cmd>` skips the extra round-trip that names an interactive prompt, since a one-shot command has none
201
295
 
202
296
  ## Worktree Backend
203
297
 
@@ -233,6 +327,19 @@ After running `dl --install`, you get intelligent tab completion:
233
327
  - File/directory paths when starting with `./`, `/`, or `~`
234
328
  - All global flags (`--ls`, `--install`, etc.) and workspace commands
235
329
 
330
+ ### How the completion cache stays current
331
+
332
+ The data behind completions lives in `~/.cache/devlaunch/completions.json`, and
333
+ building it means a `git ls-remote` per known repo — seconds of work. So it is
334
+ rebuilt in the background at most once an hour (the same interval the worktree
335
+ backend uses for lazy fetches), and at most once per `dl` invocation. Commands
336
+ that change your workspaces (starting, stopping or deleting one) rebuild it as
337
+ soon as they finish, regardless of when it was last built. Commands with no use
338
+ for it — `dl --help`, `dl --version` — do not touch it at all.
339
+
340
+ A branch created on a remote in the last hour may therefore not be offered yet.
341
+ `dl --refresh` rebuilds the cache immediately and ignores the interval.
342
+
236
343
  ## Development
237
344
 
238
345
  This project uses [pixi](https://pixi.sh) for environment management.