patchloom: v0.33.0
Patchloom 0.33.0
Windows dests, globs, and line endings now follow the same rules as
Linux. Library hosts can set charset on writes.
Highlights
A dest like *.txt matches files in the current directory only.
sub/*.txt stays in that directory. Use **/*.txt or --glob '*.txt'
when you want nested files. On Windows the CLI expands those dest
patterns itself (cmd.exe does not).
WritePolicyOptions.charset and EditorConfig charset = utf-8-bom
write a leading U+FEFF. charset = utf-8 does not insert one.
utf-16le is invalid_input. api::tidy applies the same charset
when it is not Keep.
A leading UTF-8 BOM is outside regex ^. A lone CR is a line end
for search, replace $, markdown headings, AST lines, and
read --lines.
Breaking changes
WritePolicy and WritePolicyOptions are #[non_exhaustive] and
have a new charset field (CharsetMode, default Keep). Construct
with Default and ..:
let opts = WritePolicyOptions {
charset: CharsetMode::Utf8Bom,
..WritePolicyOptions::default()
};CharsetMode is re-exported from patchloom::api and the crate
root (#2372).
New features
-
Dest globs on search, replace, and tidy.
*.txtis the current
directory only.sub/*.txtis that directory only (not cwd, not
nested).**/*.txtis recursive.--glob '*.txt'still walks
nested files. A miss names dest vs--globand skips the-itip
when the dest glob was empty or cwd-only. Plan, tx, and MCPpath
is one file or directory: do not put*.txtthere. Use replace
"glob"or plan-levelfor_each.glob(#2368, #2370, #2371). -
Charset on library writes. Set
WritePolicyOptions.charsetto
Utf8BomorUtf8.api::tidyhonors a non-Keep charset locally
(planTidyFixhas no charset field). Indent then charset, so a
BOM stays on the first byte. Setting bothdedentandindentis
invalid_input(#2372, #2373). -
EditorConfig
charset. With--respect-editorconfig,
charset = utf-8-bomwrites U+FEFF andcharset = utf-8does not
insert one.utf-16le/utf-16beareinvalid_input(#2358). -
Protobuf AST 0.6.
ast list/ast renameon.protofiles
use tree-sitter-proto 0.6 (#2374).
Bug fixes
-
Windows dests ignored
--cwdor deleted the file.C:fooand
\foodests areinvalid_input(they ignore--cwd). A trailing
slash on a dest no longer treats the file as missing or rolls back
a create. Drive-relative--files-fromlines peel the same way.
BareNULisinvalid_input. Illegal dests (<>"|?*,\\.,
trailing space or dot) peel before open (#2360, #2362, #2364, #2366, #2354, #2307). -
--glob *.txtmissedHit.TXTon Windows. User globs and
.gitignorematch case-insensitively on Windows (#2309, #2310). -
Writes dropped hardlinks, MOTW, and named streams. A Windows
hardlink pair stays linked after Apply.Zone.Identifierand
custom NTFS streams persist through atomic rename. Destinations
past MAX_PATH persist. An 8.3 dest keeps the long name (#2303, #2312, #2356, #2313, #2306). -
--containrejected local UNC and//?/dests. Local
admin-share UNC (\\localhost\C$\...) maps into the workspace.
IPv6 loopback UNC is local, not an ADS path.//?/C:/dests
inside the workspace apply, and backup opens them with a
drive-letter path.\\.\C:\dests that name a real file apply (#2314, #2315, #2321, #2319, #2323). -
Notepad UTF-8 BOM and CR-only files missed matches. JSON,
markdown, prepend, and tx plans accept a leading BOM. Multi-doc
YAML strips the BOM before parse. Regex^skips a leading BOM.
A lone CR is a line end for search, markdown, TOML, AST lines,
read --lines, and replace$(including mid-file CR). Indent
and dedent peel a leading BOM so the first line is not treated
as indented text (#2311, #2316, #2317, #2330, #2331, #2335, #2336, #2337, #2343, #2347, #2326, #2348, #2374). -
Patch dests with
a\stayednot_found. Git headers
a\fileandb\filestrip likea//b/. Mixed grammar
(unified headers plus SEARCH/REPLACE) isinvalid_input(#2349, #2351). -
Quoted YAML
C:\Userswas a unicode escape. A drive-letter
:\\path in a quoted YAML plan isinvalid_inputand names
/or\\\\as the fix (#2357). -
UTF-16
--files-fromlooked like a missing list. The list
peels asinvalid_input(#2355). -
Apply reported success after a fail-restore. A share lock or
other persist failure isrollbackwithapplied: false.
Junctions unlink as junctions. ADS dests refuse (#2304, #2308, #2305). -
Empty-hunk delete dests were not peeled. A missing dest is
not_found. A directory dest isinvalid_input. A dest outside
--containisguard_rejectedbefore exists (#2299, #2301). -
Undo after a case-only rename kept the new casing. Restore
puts the original NTFS casing back (#2346).
Numbers
| Metric | Notes |
|---|---|
| Version | 0.32.0 -> 0.33.0 |
| Focus | Dest globs, charset, Windows dests, BOM and CR line ends |
| Tests | 5000+ (3376 unit + 1617 integration + 10 PTY) |
Upgrading
- Agents: dest
*.txtis cwd-only. Destsub/*.txtis that
directory only. Use dest**/*.txtor--glob '*.txt'for
nested files. Plan/tx/MCPpathis not a dest glob.C:foo
and\foodests areinvalid_input. - Library hosts: construct
WritePolicy/WritePolicyOptions
withDefaultand... Setcharsetwhen you want a BOM or
want one stripped.api::tidyis the high-level writer that
honors charset today.WritePolicynow hascharset; both
structs are#[non_exhaustive]. - EditorConfig:
charset = utf-8-bomwrites U+FEFF.
utf-16le/utf-16befail closed. - Windows:
--globand.gitignoreare case-insensitive.
Hardlink siblings, MOTW, and named streams survive Apply. - Install from crates.io, npm, Homebrew, or Scoop after the tag
ships. On Windows, Scoop is recommended; winget may need
winget source updateafter Microsoft publishes; Chocolatey can
lag while moderation runs.