<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/gptel-tools/update_text_file.el, branch main</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-05-16T16:30:04+00:00</updated>
<entry>
<title>feat(gptel-tools): harden path validation with file-truename realpath</title>
<updated>2026-05-16T16:30:04+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-16T16:30:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=244d4c56768fcc60bd1b23fe45df7a57c7b293ec'/>
<id>urn:sha1:244d4c56768fcc60bd1b23fe45df7a57c7b293ec</id>
<content type='text'>
Resolves PATH through file-truename before applying home-directory and
read/write checks across the path-handling tools (git_status, git_log,
git_diff, move_to_trash, read_text_file, update_text_file,
write_text_file, list_directory_files, read_buffer, web_fetch).
Without the resolve step, a symlink under HOME pointing outside HOME
would pass the prefix check but the tool would act on the real target
-- a symlink-escape.

move_to_trash also tightens the trash-bin construction (treats empty
file extensions correctly) and switches the "critical directories"
list to truename-resolved canonical forms so a symlinked ~/.config
can't be trashed via an aliased path.

update_text_file fixes an off-by-one in the line-count derivation
when the source content is empty.

Each source change pairs with tests in tests/test-gptel-tools-*.el
and tests/test-update-text-file.el covering the realpath escape
paths, the empty-extension trash case, and the empty-content line-
count edge.  Combined coverage is now 100% across all ten gptel-tools
source files: 516 / 516 executable lines, 217 tests.
</content>
</entry>
<entry>
<title>feat(gptel-tools): wire update_text_file as a local tool with tests</title>
<updated>2026-05-16T06:18:35+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-16T06:18:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=531f0f19f298e28b42dfb216f6008a1cbc6164d3'/>
<id>urn:sha1:531f0f19f298e28b42dfb216f6008a1cbc6164d3</id>
<content type='text'>
I rewrote `update_text_file.el` in pure Elisp.  The previous version
shelled out to sed for everything, had a stray quote terminator at EOF
(line 149) that broke loading, produced literal backslash-n where
actual newlines were expected, and prompted via `y-or-n-p` redundantly
with gptel's own `:confirm t` flag.

The five operations -- replace, append, prepend, insert-at-line,
delete-lines -- split into pure string transforms that test without
touching the disk.  The file-level wrapper validates the path, enforces
a 10MB size limit, takes a timestamped backup, and writes atomically.
No backup is created when the operation is a no-op.  Patterns are
literal substrings (not regex) so the model can't trip over
metacharacter quoting.

`tests/test-update-text-file.el` covers Normal / Boundary / Error per
operation plus the file-level wrapper.  48 tests green.  Added
`update_text_file` to `cj/gptel-local-tool-features` so gptel exposes
the tool after restart.
</content>
</entry>
<entry>
<title>changing repositories</title>
<updated>2025-10-12T16:47:26+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2025-10-12T16:47:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=092304d9e0ccc37cc0ddaa9b136457e56a1cac20'/>
<id>urn:sha1:092304d9e0ccc37cc0ddaa9b136457e56a1cac20</id>
<content type='text'>
</content>
</entry>
</feed>
