Commit a391b3c
committed
fix: preserve symlinked destinations in atomic config writes
atomicWriteFile and atomicWriteFileAsync wrote a temp file beside the
literal destination path and renamed over it. rename(2) replaces a
directory entry, so when the destination was itself a symlink the rename
destroyed the link and left a plain file in its place.
This breaks dotfiles-managed setups, where ~/.codex/config.toml is a
symlink into a tracked repo. The first injected write silently converts
it to a real file and the repo stops receiving updates. Nothing surfaces
the divergence: the live config keeps working, so the stale repo copy
looks current until someone diffs it.
Resolve the destination through realpath before choosing the temp path.
Both the temp file and the rename target then live inside the link's real
directory, so the entry replaced is the real file and the link survives.
Same-filesystem atomicity is preserved because the temp stays beside its
resolved target, and an unresolvable path falls back to the literal path,
which is correct for a first write and for a dangling link.1 parent 3f1730b commit a391b3c
2 files changed
Lines changed: 90 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
107 | 129 | | |
108 | 130 | | |
109 | 131 | | |
| |||
115 | 137 | | |
116 | 138 | | |
117 | 139 | | |
118 | | - | |
| 140 | + | |
| 141 | + | |
119 | 142 | | |
120 | 143 | | |
121 | 144 | | |
122 | 145 | | |
123 | 146 | | |
124 | | - | |
| 147 | + | |
125 | 148 | | |
126 | 149 | | |
127 | 150 | | |
| |||
201 | 224 | | |
202 | 225 | | |
203 | 226 | | |
204 | | - | |
| 227 | + | |
| 228 | + | |
205 | 229 | | |
206 | 230 | | |
207 | 231 | | |
208 | 232 | | |
209 | 233 | | |
210 | | - | |
| 234 | + | |
211 | 235 | | |
212 | 236 | | |
213 | 237 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| |||
1669 | 1669 | | |
1670 | 1670 | | |
1671 | 1671 | | |
| 1672 | + | |
| 1673 | + | |
| 1674 | + | |
| 1675 | + | |
| 1676 | + | |
| 1677 | + | |
| 1678 | + | |
| 1679 | + | |
| 1680 | + | |
| 1681 | + | |
| 1682 | + | |
| 1683 | + | |
| 1684 | + | |
| 1685 | + | |
| 1686 | + | |
| 1687 | + | |
| 1688 | + | |
| 1689 | + | |
| 1690 | + | |
| 1691 | + | |
| 1692 | + | |
| 1693 | + | |
| 1694 | + | |
| 1695 | + | |
| 1696 | + | |
| 1697 | + | |
| 1698 | + | |
| 1699 | + | |
| 1700 | + | |
| 1701 | + | |
| 1702 | + | |
| 1703 | + | |
| 1704 | + | |
| 1705 | + | |
| 1706 | + | |
| 1707 | + | |
| 1708 | + | |
| 1709 | + | |
| 1710 | + | |
| 1711 | + | |
| 1712 | + | |
| 1713 | + | |
| 1714 | + | |
| 1715 | + | |
| 1716 | + | |
| 1717 | + | |
| 1718 | + | |
| 1719 | + | |
| 1720 | + | |
| 1721 | + | |
| 1722 | + | |
| 1723 | + | |
| 1724 | + | |
| 1725 | + | |
| 1726 | + | |
| 1727 | + | |
| 1728 | + | |
| 1729 | + | |
| 1730 | + | |
| 1731 | + | |
0 commit comments