Skip to content

Keep symbolic links and permissions when the editor saves - #329

Merged
matt-edmondson merged 3 commits into
mainfrom
claude/project-thread-5pmmk1-324
Oct 22, 2026
Merged

matt-edmondson merged 3 commits into
mainfrom
claude/project-thread-5pmmk1-324

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Requested by Matt · project thread

Fixes #324.

The atomic save from #297 writes a temporary file and renames it over the target. A rename replaces a directory entry rather than a file, which caused two regressions:

  • Symbolic links broke. A schema shared through a link turned into a plain file holding the new content, while the file the link pointed to kept the old content.
  • Permissions reset. The saved file took the process's default mode, so a group-writable schema became writable by its owner only.

Changes in SchemaFile.WriteAtomically:

  • The path is first followed through its links to the file it finally names. The temporary file is written beside that file, and that file is the one replaced.
  • If the path isn't a link it is used as is. This matters for a first save: resolving a path that doesn't exist yet throws.
  • On non-Windows systems, the existing file's Unix mode is copied onto the temporary file before File.Replace.

Two tests in SchemaFileTests cover this, and I ran both against main first to confirm they fail there:

  • SavingThroughASymbolicLinkUpdatesTheFileItNames checks that the link is still a link and the file it names has the new content. It is skipped as inconclusive where links can't be created, such as on Windows without the privilege.
  • SavingOverAFileKeepsItsPermissions checks that a group-writable mode is kept. It is skipped on Windows.

I ran Schema.Editor.Test locally and all 33 tests pass. The container only has SDK 10.0.1xx, so for that local run I temporarily changed global.json and overrode the compiler. Neither change is committed.


Generated by Claude Code

The atomic save (#297) renamed a temporary file over the target, which replaces the
directory entry: a symbolic link became a plain file and the shared schema it named
kept the old content, and the saved file took the process's default mode. The save
now follows the path to the file it finally names and replaces that, and copies the
existing file's Unix mode onto the temporary file first.

Fixes #324

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9FBXHS37WoAF87LDY2ZVV
@matt-edmondson matt-edmondson self-assigned this Oct 22, 2026
Refusing unknown options (#310) and the --no-data flag landed separately, and
validate's list of known options was left empty, so 'validate --no-data' exited
1 with the usage text and TestValidateSkipsDataFilesWhenAskedTo fails on main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L9FBXHS37WoAF87LDY2ZVV

Copy link
Copy Markdown
Contributor Author

The failing test here was TestValidateSkipsDataFilesWhenAskedTo, which is red on main too, not something this PR changed. I merged the fix from #330 into this branch so CI can go green; it will drop out of the diff once #330 merges.


Generated by Claude Code

@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 98eca91 into main Oct 22, 2026
16 checks passed
@matt-edmondson
matt-edmondson deleted the claude/project-thread-5pmmk1-324 branch October 22, 2026 13:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants