module Model open System open System.IO open System.Security.Cryptography type Outcome = | Cached | Installed let private checksum path = use input = File.OpenRead path SHA256.HashData input |> Convert.ToHexString |> _.ToLowerInvariant() let install expected destination (download: Stream -> unit) = if File.Exists destination && checksum destination = expected then Cached else Directory.CreateDirectory(Path.GetDirectoryName destination) |> ignore let temporary = destination + ".incoming" try do use output = File.Create temporary download output if checksum temporary <> expected then invalidOp "model checksum differs" File.Move(temporary, destination, true) Installed finally if File.Exists temporary then File.Delete temporary