google / renameio

Package renameio provides a way to atomically create or replace a file or symbolic link.
Apache License 2.0
609 stars 27 forks source link

Atomic simultaneous file rename and contents replacement? #16

Closed twpayne closed 5 years ago

twpayne commented 5 years ago

I don't think that this is possible, but I suspect that you'll be able to find the definitive answer.

I want to remove an existing file and replace it with a new file with new contents in a single atomic operation.

The specific case is (chezmoi again...):

I have a file called foo. I want to atomically replace it with encrypted_foo where the contents of encrypted_foo are the previous contents of foo but encrypted with some key. At no time do I want both foo and encrypted_foo to exist (because then the state is ambiguous, with two sources of truth) and neither do I want neither to exist (because then foo is lost).

It is possible that duplicating the directory containing foo and then replacing that directory with a new directory containing encrypted_foo might do the job, but maybe there's an easier method?

Thanks, and feel free to close this issue if it's not possible.

stapelberg commented 5 years ago

It is possible that duplicating the directory containing foo and then replacing that directory with a new directory containing encrypted_foo might do the job, but maybe there's an easier method?

Using different directories is the only way I know of. Note that you can’t atomically replace a directory, though (from rename(2)):

oldpath can specify a directory. In this case, newpath must either not exist, or it must specify an empty directory.

One way to get around this is to use a symbolic link. I’m doing this in pgt-gopath: https://github.com/Debian/pkg-go-tools/blob/31d6c2510aace2dfbcc2699eec039da91c614cd1/cmd/pgt-gopath/gopath.go#L44

I don’t think that strategy works well for chezmoi, though, as you typically have much less control over the directory layout.

twpayne commented 5 years ago

Thanks very much for the answer. That all makes sense.