mirror of
https://github.com/Smaug123/WoofWare.Expect
synced 2025-10-05 04:28:40 +00:00
Atomic file writes (#12)
This commit is contained in:
22
.envrc
22
.envrc
@@ -1 +1,23 @@
|
||||
use flake
|
||||
DOTNET_PATH=$(readlink "$(which dotnet)")
|
||||
SETTINGS_FILE=$(find . -maxdepth 1 -type f -name '*.sln.DotSettings.user')
|
||||
MSBUILD=$(realpath "$(find "$(dirname "$DOTNET_PATH")/../share/dotnet/sdk" -maxdepth 2 -type f -name MSBuild.dll)")
|
||||
if [ -f "$SETTINGS_FILE" ] ; then
|
||||
xmlstarlet ed --inplace \
|
||||
-N wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" \
|
||||
-N x="http://schemas.microsoft.com/winfx/2006/xaml" \
|
||||
-N s="clr-namespace:System;assembly=mscorlib" \
|
||||
-N ss="urn:shemas-jetbrains-com:settings-storage-xaml" \
|
||||
--update "//s:String[@x:Key='/Default/Environment/Hierarchy/Build/BuildTool/DotNetCliExePath/@EntryValue']" \
|
||||
--value "$(realpath "$(dirname "$DOTNET_PATH")/../share/dotnet/dotnet")" \
|
||||
"$SETTINGS_FILE"
|
||||
|
||||
xmlstarlet ed --inplace \
|
||||
-N wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation" \
|
||||
-N x="http://schemas.microsoft.com/winfx/2006/xaml" \
|
||||
-N s="clr-namespace:System;assembly=mscorlib" \
|
||||
-N ss="urn:shemas-jetbrains-com:settings-storage-xaml" \
|
||||
--update "//s:String[@x:Key='/Default/Environment/Hierarchy/Build/BuildTool/CustomBuildToolPath/@EntryValue']" \
|
||||
--value "$MSBUILD" \
|
||||
"$SETTINGS_FILE"
|
||||
fi
|
||||
|
@@ -270,7 +270,7 @@ type ExpectBuilder (mode : Mode) =
|
||||
let lines = File.ReadAllLines state.Caller.FilePath
|
||||
let oldContents = String.concat "\n" lines
|
||||
let lines = SnapshotUpdate.updateSnapshotAtLine lines state.Caller.LineNumber actual
|
||||
File.WriteAllLines (state.Caller.FilePath, lines)
|
||||
File.writeAllLines lines state.Caller.FilePath
|
||||
failwith ("Snapshot successfully updated. Previous contents:\n" + oldContents)
|
||||
|
||||
match CompletedSnapshotGeneric.passesAssertion state with
|
||||
|
32
WoofWare.Expect/File.fs
Normal file
32
WoofWare.Expect/File.fs
Normal file
@@ -0,0 +1,32 @@
|
||||
namespace WoofWare.Expect
|
||||
|
||||
open System
|
||||
open System.IO
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module internal File =
|
||||
|
||||
/// Standard attempt at an atomic file write.
|
||||
/// It may fail to be atomic if the working directory somehow spans multiple volumes,
|
||||
/// and of course with external network storage all bets are off.
|
||||
let writeAllLines (lines : string[]) (path : string) : unit =
|
||||
let file = FileInfo path
|
||||
|
||||
let tempFile =
|
||||
Path.Combine (file.Directory.FullName, file.Name + "." + Guid.NewGuid().ToString () + ".tmp")
|
||||
|
||||
try
|
||||
File.WriteAllLines (tempFile, lines)
|
||||
// Atomicity guarantees are undocumented, but on Unix this is an atomic `rename` call
|
||||
// https://github.com/dotnet/runtime/blob/9a4be5b56d81aa04c7ea687c02b3f4e64c83761b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Unix.cs#L181
|
||||
// and on Windows this is an atomic ReplaceFile:
|
||||
// https://github.com/dotnet/runtime/blob/9a4be5b56d81aa04c7ea687c02b3f4e64c83761b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystem.Windows.cs#L92
|
||||
// calls https://github.com/dotnet/runtime/blob/9a4be5b56d81aa04c7ea687c02b3f4e64c83761b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs#L12
|
||||
// which calls ReplaceFileW, whose atomicity guarantees are again apparently undocumented,
|
||||
// but 4o-turbo, Opus 4, and Gemini 2.5 Flash all think it's atomic.
|
||||
File.Replace (tempFile, path, null)
|
||||
finally
|
||||
try
|
||||
File.Delete tempFile
|
||||
with _ ->
|
||||
()
|
@@ -300,5 +300,5 @@ module internal SnapshotUpdate =
|
||||
|
||||
let newContents = updateAllLines contents sources
|
||||
|
||||
System.IO.File.WriteAllLines (callerFile, newContents)
|
||||
File.writeAllLines newContents callerFile
|
||||
)
|
||||
|
@@ -18,6 +18,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="AssemblyInfo.fs" />
|
||||
<Compile Include="Text.fs" />
|
||||
<Compile Include="File.fs" />
|
||||
<Compile Include="Domain.fs" />
|
||||
<Compile Include="SnapshotUpdate.fs" />
|
||||
<Compile Include="Config.fs" />
|
||||
|
Reference in New Issue
Block a user