-
Notifications
You must be signed in to change notification settings - Fork 323
Expand file tree
/
Copy pathCargo.toml
More file actions
382 lines (352 loc) · 16.3 KB
/
Copy pathCargo.toml
File metadata and controls
382 lines (352 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
[workspace]
members = ["tests/helpers/wt-perf"]
# Include the helper package so a workspace `cargo test` runs its in-package
# CLI tests (which build its binary).
default-members = [".", "tests/helpers/wt-perf"]
# cargo-affected input→test rules. cargo-affected selects tests by Rust-line
# coverage overlap, so a file a test reads at *runtime* (never recorded in
# coverage) maps to no test and would slip through `cargo affected run`. Each
# rule force-selects the owning tests when a matching path changes. `[*.metadata]`
# is excluded from cargo-affected's fingerprint, so editing a rule is
# cache-neutral. See https://github.com/max-sixty/cargo-affected#input-rules.
# insta `.snap` snapshots are read at test time and never appear in coverage, so
# a snapshot edit maps to no test. Route each snapshot to the binary that owns
# it — the finest granularity available without a snapshot→test map. Integration
# snapshots live under tests/; unit-test snapshots under src/, split across the
# lib (`worktrunk`) and the `wt` binary (`worktrunk::bin/wt`).
[[workspace.metadata.affected.rule]]
globs = ["tests/**/*.snap"]
filterset = "binary_id(=worktrunk::integration)"
[[workspace.metadata.affected.rule]]
globs = ["src/**/*.snap"]
filterset = "binary_id(=worktrunk) | binary_id(=worktrunk::bin/wt)"
# tests/integration_tests/readme_sync.rs reads each of these at runtime (via
# fs::read_to_string) and asserts the committed copies stay in sync — both the
# sources (README.md, docs/src/content/docs Markdown, src/cli/mod.rs,
# src/llm.rs, the skill references, Taskfile.yaml)
# and the generated artifacts it regenerates and compares against (the
# dev/*.example.toml files, docs/public/llms.txt, the agent-skills index.json).
# Editing any of them flips the test, but coverage can't link a runtime-read
# file to it.
[[workspace.metadata.affected.rule]]
globs = [
"README.md",
"docs/**/*.md",
"docs/public/llms.txt",
"docs/public/.well-known/agent-skills/index.json",
"docs/src/generated/terminal-styles.json",
"dev/*.toml",
"src/cli/mod.rs",
"src/llm.rs",
"Taskfile.yaml",
"skills/**/*.md",
]
filterset = "test(/readme_sync/)"
# The AUR PKGBUILD hand-copies the fish completion `fish_completion_content`
# generates; `test_aur_pkgbuild_ships_the_current_fish_completion` reads it at
# test time (fs::read_to_string), so coverage can't link the two.
[[workspace.metadata.affected.rule]]
globs = [".github/aur/PKGBUILD"]
filterset = "test(/aur_pkgbuild/)"
[package]
name = "worktrunk"
version = "0.80.0"
edition = "2024"
rust-version = "1.98"
build = "build.rs"
repository = "https://github.com/max-sixty/worktrunk"
homepage = "https://worktrunk.dev"
description = "A CLI for Git worktree management, designed for parallel AI agent workflows"
license = "MIT OR Apache-2.0"
default-run = "wt"
exclude = [".agents/skills/**"]
[package.metadata.release]
# Allow releases from any branch (GitHub Actions uses detached HEAD)
allow-branch = ["*"]
consolidate-commits = true
[package.metadata.cargo-udeps.ignore]
# `which` is used only on Windows (#[cfg(windows)] in src/shell_exec.rs).
# `petname-macros` is not referenced in code — its exact pin keeps the proc
# macro version aligned with `petname` (see the dependency comment below).
normal = ["which", "petname-macros"]
[features]
# Disabled: Enable testing for shells that require extra installation steps (nushell, powershell, elvish, xonsh, oil)
# tier-2-integration-tests = []
# Enable syntax highlighting for bash commands in output (requires tree-sitter)
# This is optional to avoid C compilation issues on some platforms
default = ["cli", "syntax-highlighting"]
# Enables the `wt` binary and everything specific to the CLI: argument parsing,
# interactive picker, rich terminal rendering, and the markdown help pager.
# Library consumers (e.g. `worktrunk-sync`) should depend on worktrunk with
# `default-features = false` to avoid pulling these in.
cli = [
"dep:clap",
"dep:clap_complete",
"dep:crossterm",
"dep:humantime",
"dep:skim",
"dep:ratatui",
"dep:ansi-to-tui",
"dep:tokio",
"dep:arboard",
"dep:open",
"dep:termimad",
"dep:tracing-log",
"dep:tracing-subscriber",
]
syntax-highlighting = ["dep:tree-sitter-bash", "dep:tree-sitter-highlight"]
# Enable shell/PTY integration tests (needs bash, zsh, fish, nu, pwsh, and jq on PATH)
# Includes: shell wrapper tests, PTY-based approval prompts, TUI select, progressive rendering
shell-integration-tests = []
# Enable benchmarks whose fixture is too large for hosted CI: the
# large-repository prune fixture (multi-gigabyte linked worktrees, cached under
# target/wt-perf/bench-repos). The daily benchmarks workflow runs plain `cargo bench`
# and must never build it; opt in locally with
# `cargo bench --bench prune --features large-repository-benches`.
large-repository-benches = []
# Install git-wt binary so `git wt` works as a git subcommand
git-wt = []
[lib]
name = "worktrunk"
path = "src/lib.rs"
[[bin]]
name = "wt"
path = "src/main.rs"
required-features = ["cli"]
# Also install as git-wt so `git wt <command>` works as a git subcommand.
# Primarily useful on Windows where `wt` conflicts with Windows Terminal.
# See: https://github.com/max-sixty/worktrunk/issues/133
# Install with: cargo install worktrunk --features git-wt
[[bin]]
name = "git-wt"
path = "src/git_wt.rs"
required-features = ["cli", "git-wt"]
# `git_wt.rs` is `include!("main.rs")`, so its unit tests are byte-identical
# duplicates of the `wt` binary's. Running them adds no coverage and breaks
# under `cargo hack test --feature-powerset`: insta derives snapshot filenames
# from the crate name, so the duplicates look for `git_wt__*.snap` files that
# don't exist (only `wt__*`). The `check` powerset still compiles this target.
test = false
# The integration suite execs the `wt` binary (needs `cli`) and snapshots its
# rendered output, which bakes in syntax highlighting (needs
# `syntax-highlighting`). Declaring both lets `cargo hack test
# --feature-powerset` skip this target on combinations that can't satisfy it
# rather than fail; lib and doc tests still run on every combination.
[[test]]
name = "integration"
path = "tests/integration.rs"
required-features = ["cli", "syntax-highlighting"]
# Deliberately a second binary rather than another module under `integration`:
# it latches process-wide cancellation state, which would take out any test
# running beside it in the same process. See the file's module docs.
[[test]]
name = "cancel_background"
path = "tests/cancel_background.rs"
[dependencies]
anyhow = "1.0.102"
anstream = "1.0"
anstyle = "1.0.13"
ansi-str = "0.9"
color-print = "0.3.7"
askama = { version = "0.16", default-features = false, features = ["derive", "std"] }
# Floor is 0.4.31, not 0.4: `DateTime::from_timestamp` (utils.rs, statusline.rs,
# backup.rs) landed in chrono 0.4.31. `-Z minimal-versions` otherwise resolves
# 0.4.0 and our own lib fails to compile.
chrono = "0.4.31"
# `unstable-markdown` renders our `///` doc-comments as styled help (bold inline
# code, literal `[experimental]`). skim 0.20 pulled it in transitively; skim 4
# (default-features = false) does not, so depend on it explicitly to keep help
# output stable rather than reverting to raw text.
clap = { version = "4.6", features = ["derive", "unstable-ext", "wrap_help", "unstable-markdown"], optional = true }
clap_complete = { version = "4.6", features = ["unstable-dynamic"], optional = true }
crossbeam-channel = "0.5"
crossterm = { version = "0.29", optional = true }
indexmap = { version = "2.14", features = ["serde"] }
etcetera = "0.11"
# `log` is still used pervasively for application logging; events flow into
# `tracing` via `tracing-log::LogTracer` (CLI binary only).
log = "0.4.31"
# 0.1.30 added the `enabled!` macro `src/trace/emit.rs::Span::drop` uses to
# elide span emission when the subscriber doesn't care. Older versions only
# expose the per-level macros and dispatcher checks.
tracing = "0.1.35"
# Compatibility shim: forward `log::*` macros into `tracing`. ~100 call sites
# across the codebase keep using `log::debug!` etc.; only the routing layer
# moved.
tracing-log = { version = "0.2.0", optional = true }
# Layered subscribers do the routing today's `Route` enum used to. `env-filter`
# replaces env_logger's RUST_LOG parsing; `fmt` provides the writer + format
# scaffolding; `registry` composes layers. Pinned to ≥ 0.3.17: that's when
# `EnvFilter::builder().with_default_directive(...).from_env_lossy()` (used in
# `src/logging.rs`) stabilized on top of the per-layer filtering rework.
tracing-subscriber = { version = "0.3.17", default-features = false, features = ["ansi", "env-filter", "fmt", "registry"], optional = true }
# Only enable needed features - saves ~200KB by excluding debug, macros, multi_template.
# `unstable_machinery` exposes the parser `src/config/deprecation.rs` migrates retired
# template variables through, rather than re-deriving MiniJinja's grammar by hand; it
# pulls in `internal_debug`, which costs ~116KB of that saving back (~67KB stripped).
minijinja = { version = "2.20", default-features = false, features = [
"builtins",
"serde",
"std_collections",
"unstable_machinery",
] }
rayon = "1.12"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.150"
shell-escape = "0.1"
shellexpand = "3.1"
strsim = "0.11.1"
strum = { version = "0.28", features = ["derive"] }
synoptic = "2"
terminal_size = "0.4.3"
toml = { version = "1.0", features = ["preserve_order"] }
toml_edit = { version = "0.25", features = ["serde"] }
# tree-sitter-bash may lag behind tree-sitter-highlight (0.25.x works with
# tree-sitter-highlight 0.27.x).
# These are optional dependencies controlled by the "syntax-highlighting" feature.
# To build without C compilation requirements, use: cargo install worktrunk --no-default-features --features cli
tree-sitter-bash = { version = "0.25.1", optional = true }
tree-sitter-highlight = { version = "0.27", optional = true }
unicode-width = "0.2.1"
wrap-ansi = "0.1"
osc8 = "0.1.0"
supports-hyperlinks = "3"
home = "0.5.12"
humantime = { version = "2.2", optional = true }
once_cell = "1.21.4"
dirs = "7.0"
normalize-path = "0.2.1"
path-slash = "0.2"
pathdiff = "0.2"
which = "8.0.2"
# Cross-platform path canonicalization that avoids Windows verbatim paths (\\?\)
# which external tools like git cannot handle. On Unix, it's a no-op wrapper.
dunce = "1.0"
termimad = { version = "0.35.1", optional = true }
urlencoding = "2.1"
regex = "1.12.3"
ignore = "0.4"
reflink-copy = "0.1"
# Atomic, no-overwrite rename (renameat2 / renamex_np / MoveFileExW) for
# `--clobber` backups — closes the check-then-rename TOCTOU. Keeps the FFI
# (and its `unsafe`) out of this crate, which is `unsafe_code = "forbid"`.
renamore = "0.3"
dashmap = "6.2.1"
fs2 = "0.4.3"
sanitize-filename = "0.6.0"
schemars = { version = "1.2.1", features = ["derive"] }
# SHA-256 is used for persistent cache keys (e.g., summary diff hashes in
# `.git/wt/cache/summary/`). stdlib's `DefaultHasher` is not guaranteed
# stable across Rust versions, so we need a deterministic algorithm on disk.
sha2 = "0.11"
# Wordlists for the `codename` template filter. PINNED EXACT — bumping this
# can silently shift every existing user's codename-derived worktree path,
# orphaning their on-disk worktrees. Coordinate any version change as a
# breaking-change rollout (see `test_codename_outputs_are_stable` and
# `src/config/expansion.rs::codename`). We use only the static wordlists,
# not the random-name generator, so `default-rng` and `clap` stay off.
petname = { version = "=3.2.0", default-features = false, features = ["default-words"] }
# PINNED EXACT to match `petname`: its caret dependency otherwise permits a
# different proc-macro version, but the generated code and runtime re-exports
# require an exact match. Keep both pins in lockstep.
petname-macros = "=3.2.0"
tempfile = "3.27"
# Timed waits on child processes (`Cmd::timeout`, `Cmd::delayed_stream`, the
# picker's pager). Replaced `wait-timeout`, whose SIGCHLD handler aborts the
# process when its self-pipe write fails — see "Timed waits" in `shell_exec`.
shared_child = "1.1"
# Interactive picker (`wt switch`) TUI stack, pulled in only by the `cli`
# feature's `dep:` entries. These are platform-neutral (skim 4.x is the
# ratatui/crossterm rewrite, which supports Windows), so they live in the main
# table — not under `[target.'cfg(unix)']` — or the picker fails to compile on
# Windows.
#
# skim 4.x is the ratatui-based rewrite; the 0.20 line used the now-abandoned
# tuikit backend (we previously vendored a patched skim-tuikit fork). The
# picker feeds rows as a custom `SkimItem` whose `display()` returns a ratatui
# `Line`, so `ratatui` + `ansi-to-tui` below convert the picker's pre-rendered
# ANSI rows into styled lines.
#
# `default-features = false` drops skim's own CLI (`clap` / `clap_mangen` / …):
# worktrunk embeds the picker as a library and never shells out to the `sk`
# binary. `frizbee` keeps skim's default fuzzy matcher.
# Floor is 4.8, not 4: the picker is written against 4.8's `ratatui 0.30.1`
# API, and earlier 4.x compile against an incompatible ratatui (`-Z
# minimal-versions` otherwise resolves skim 4.6 against ratatui 0.30.1 and fails
# to build).
# skim 5.3.1 (bumped in #3526) regressed the picker on the legacy Windows
# console — every picker PTY test failed with "Keyboard progressive enhancement
# not implemented for the legacy Windows API", reddening the Windows test job,
# so the pin held at the last-Windows-green 5.1.0. 5.5.0 guards that path ("Do
# not panic on push/pop keyboard enhancement flags failure") and is
# Windows-green again. Kept as an exact pin; it can relax to a range now that
# the keyboard-enhancement path no longer regresses the legacy console.
skim = { version = "=5.7.2", optional = true, default-features = false, features = ["frizbee"] }
# Pinned to skim's ratatui line so the `Line` type `display()` returns is the
# same one skim consumes. `ansi-to-tui` parses ANSI SGR codes into ratatui spans.
# Floor is 0.30.1: 0.30.0 is a broken release (its `#[instability::unstable]`
# attribute fails to compile).
ratatui = { version = "0.30.1", optional = true }
ansi-to-tui = { version = "8.0.1", optional = true }
# Already in the tree via skim (its event loop is tokio-based). The picker drives
# skim through the public `Skim::init`/`run` API rather than the all-in-one
# `Skim::run_with` so it can grab `event_sender()` and push `Event::Render` while
# collect mutates rows in place — skim 4.x renders on demand, not on a heartbeat.
# `Runtime::new()` needs `rt-multi-thread`; `event_sender()` is a `sync::mpsc`.
tokio = { version = "1.52.3", optional = true, default-features = false, features = ["rt-multi-thread", "sync"] }
# Picker row shortcuts: `alt-y` copies the selected branch to the system
# clipboard, `alt-o` opens its PR/MR URL in the browser. Both are cross-platform
# (so they sit in the main table alongside the picker stack, not under
# `[target.'cfg(unix)']`). `arboard` drops `default-features` to skip the `image`
# crate — the picker only copies text — while keeping `wayland-data-control` so
# Linux Wayland clipboards work alongside X11 and macOS.
arboard = { version = "3.4", optional = true, default-features = false, features = ["wayland-data-control"] }
open = { version = "5.3", optional = true }
[target.'cfg(unix)'.dependencies]
# Unix-only syscall crates: `nix` (process/signal) backs the fsmonitor reap and
# `signal-hook` forwards Ctrl-C to child process groups. Gating keeps both out of
# the Windows dependency graph.
nix = { version = "0.31.3", default-features = false, features = ["process", "signal"] }
signal-hook = "0.4.1"
[build-dependencies]
vergen-gitcl = { version = "10.0.0", features = ["build"] }
[dev-dependencies]
insta = { version = "1.47.2", features = ["yaml", "redactions", "filters"] }
insta-cmd = "0.7"
rstest = "0.27"
tempfile = "3.27"
toml = "1.0"
criterion = "0.8"
portable-pty = "0.9"
regex = "1.12.3"
vt100 = "0.16.2"
wt-perf = { path = "tests/helpers/wt-perf" }
similar = "3.1.1"
jsonschema = { version = "0.58", default-features = false }
[[bench]]
name = "alias"
harness = false
[[bench]]
name = "completion"
harness = false
[[bench]]
name = "list"
harness = false
[[bench]]
name = "time_to_first_output"
harness = false
[[bench]]
name = "remove"
harness = false
[[bench]]
name = "prune"
harness = false
[[bench]]
name = "picker_preview"
harness = false
[lints.rust]
unsafe_code = "forbid"
# The profile that 'dist' will build with
[profile.dist]
inherits = "release"
lto = "thin"