FileSystem (Polyglot)¶
In [ ]:
#r @"../../../../../../../.nuget/packages/fsharp.control.asyncseq/3.2.1/lib/netstandard2.1/FSharp.Control.AsyncSeq.dll"
#r @"../../../../../../../.nuget/packages/system.reactive/6.0.1-preview.1/lib/net6.0/System.Reactive.dll"
#r @"../../../../../../../.nuget/packages/system.reactive.linq/6.0.1-preview.1/lib/netstandard2.0/System.Reactive.Linq.dll"
#r @"../../../../../../../.nuget/packages/argu/6.2.4/lib/netstandard2.0/Argu.dll"
In [ ]:
#!import ../../lib/fsharp/Notebooks.dib
#!import ../../lib/fsharp/Testing.dib
In [ ]:
#!import ../../lib/fsharp/Common.fs
#!import ../../lib/fsharp/CommonFSharp.fs
#!import ../../lib/fsharp/Async.fs
#!import ../../lib/fsharp/AsyncSeq.fs
#!import ../../lib/fsharp/Runtime.fs
In [ ]:
#if !INTERACTIVE
open Lib
#endif
In [ ]:
open Common
open SpiralFileSystem.Operators
watchDirectory¶
In [ ]:
[<RequireQualifiedAccess>]
type FileSystemChangeType =
| Failure
| Changed
| Created
| Deleted
| Renamed
[<RequireQualifiedAccess>]
type FileSystemChange =
| Failure of exn: exn
| Changed of path: string * content: string option
| Created of path: string * content: string option
| Deleted of path: string
| Renamed of oldPath: string * (string * string option)
let inline watchDirectoryWithFilter filter shouldReadContent path =
let fullPath = path |> System.IO.Path.GetFullPath
let _locals () = $"filter: {filter} / {_locals ()}"
let watcher =
new System.IO.FileSystemWatcher (
Path = fullPath,
NotifyFilter = filter,
EnableRaisingEvents = true,
IncludeSubdirectories = true
)
let inline getEventPath (path : string) =
path |> SpiralSm.trim |> SpiralSm.replace fullPath "" |> SpiralSm.trim_start [| '/'; '\\' |]
let inline ticks () =
System.DateTime.UtcNow.Ticks
let changedStream =
AsyncSeq.subscribeEvent
watcher.Changed
(fun event ->
ticks (),
[ FileSystemChange.Changed (getEventPath event.FullPath, None) ]
)
let deletedStream =
AsyncSeq.subscribeEvent
watcher.Deleted
(fun event ->
ticks (),
[ FileSystemChange.Deleted (getEventPath event.FullPath) ]
)
let createdStream =
AsyncSeq.subscribeEvent
watcher.Created
(fun event ->
let path = getEventPath event.FullPath
ticks (), [
FileSystemChange.Created (path, None)
if SpiralPlatform.is_windows () then
FileSystemChange.Changed (path, None)
])
let renamedStream =
AsyncSeq.subscribeEvent
watcher.Renamed
(fun event ->
ticks (), [
FileSystemChange.Renamed (
getEventPath event.OldFullPath,
(getEventPath event.FullPath, None)
)
]
)
let failureStream =
AsyncSeq.subscribeEvent
watcher.Error
(fun event -> ticks (), [ FileSystemChange.Failure (event.GetException ()) ])
let stream =
[
changedStream
deletedStream
createdStream
renamedStream
failureStream
]
|> FSharp.Control.AsyncSeq.mergeAll
|> FSharp.Control.AsyncSeq.map (fun (t, events) ->
events
|> List.fold
(fun (i, events) event ->
i + 1L,
(t + i, event) :: events)
(0L, [])
|> snd
|> List.rev
)
|> FSharp.Control.AsyncSeq.concatSeq
|> FSharp.Control.AsyncSeq.mapAsyncParallel (fun (t, event) -> async {
match shouldReadContent event, event with
| true, FileSystemChange.Changed (path, _) ->
do! Async.Sleep 5
let! content = fullPath </> path |> SpiralFileSystem.read_all_text_retry_async
return t, FileSystemChange.Changed (path, content)
| true, FileSystemChange.Created (path, _) ->
do! Async.Sleep 5
let! content = fullPath </> path |> SpiralFileSystem.read_all_text_retry_async
return t, FileSystemChange.Created (path, content)
| true, FileSystemChange.Renamed (oldPath, (newPath, _)) ->
let! content = fullPath </> newPath |> SpiralFileSystem.read_all_text_retry_async
return t, FileSystemChange.Renamed (oldPath, (newPath, content))
| _ -> return t, event
})
let disposable =
new_disposable (fun () ->
trace Debug (fun () -> "FileSystem.watchWithFilter / Disposing watch stream") _locals
watcher.EnableRaisingEvents <- false
watcher.Dispose ()
)
stream, disposable
let inline watchDirectory path =
watchDirectoryWithFilter
(System.IO.NotifyFilters.FileName
// ||| System.IO.NotifyFilters.DirectoryName
// ||| System.IO.NotifyFilters.Attributes
//// ||| System.IO.NotifyFilters.Size
||| System.IO.NotifyFilters.LastWrite
//// ||| System.IO.NotifyFilters.LastAccess
// ||| System.IO.NotifyFilters.CreationTime
// ||| System.IO.NotifyFilters.Security
)
path
testEventsRaw (test)¶
In [ ]:
//// test
let inline testEventsRaw
(watchFn : (_ -> bool) -> string -> FSharp.Control.AsyncSeq<int64 * FileSystemChange> * IDisposable)
write
=
let struct (tempDir, tempDisposable) =
"FileSystem.testEventsRaw"
|> SpiralCrypto.hash_text
|> SpiralFileSystem.create_temp_dir'
let stream, disposable = watchFn (fun _ -> true) tempDir
let events = System.Collections.Concurrent.ConcurrentBag ()
let inline iter () =
stream
|> FSharp.Control.AsyncSeq.iterAsyncParallel (fun event -> async { events.Add event })
let run = async {
let! _ = iter () |> Async.StartChild
do! Async.Sleep 250
return! write tempDir
}
try
run
|> Async.runWithTimeout 60000
|> _assertEqual (Some ())
finally
disposable.Dispose ()
tempDisposable.Dispose ()
let eventsLog =
events
|> Seq.toList
|> List.sortBy fst
|> List.fold
(fun (prev, acc) (ticks, event) ->
ticks, (ticks, (if prev = 0L then 0L else ticks - prev), event) :: acc
)
(0L, [])
|> snd
|> List.rev
|> List.map (fun (diff, n, event) -> $"{n} / {diff} / {event}" |> SpiralSm.ellipsis_end 100L)
|> SpiralSm.concat "\n"
let _locals () = $"eventsLog: \n{eventsLog} / {_locals ()}"
trace Debug (fun () -> "FileSystem.testEventsRaw") _locals
events
|> Seq.toList
|> List.sortBy fst
|> List.map snd
|> List.fold
(fun acc event ->
match acc, event with
| FileSystemChange.Changed (lastPath, Some lastContent) as lastEvent :: acc,
FileSystemChange.Changed (path, Some content)
when lastPath = path && content |> SpiralSm.starts_with lastContent
->
event :: acc
| _ -> event :: acc
)
[]
|> List.rev
fast (test)¶
In [ ]:
//// test
let inline write path = async {
let n = 2
for i = 1 to n do
do! $"a{i}" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
do! Async.Sleep 250
for i = 1 to n do
do! $"b{i}" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
do! Async.Sleep 250
for i = 1 to n do
do! path </> $"file{i}.txt" |> SpiralFileSystem.move_file_async (path </> $"file_{i}.txt") |> Async.Ignore
do! Async.Sleep 250
for i = 1 to n do
do! $"c{i}" |> SpiralFileSystem.write_all_text_async (path </> $"file_{i}.txt")
do! Async.Sleep 250
for i = 1 to n do
do! SpiralFileSystem.delete_file_async (path </> $"file_{i}.txt") |> Async.Ignore
do! Async.Sleep 250
}
let inline run () =
let events = testEventsRaw watchDirectory write
events
|> _sequenceEqual [
FileSystemChange.Created ("file1.txt", Some "a1")
FileSystemChange.Changed ("file1.txt", Some "a1")
FileSystemChange.Created ("file2.txt", Some "a2")
FileSystemChange.Changed ("file2.txt", Some "a2")
FileSystemChange.Changed ("file1.txt", Some "b1")
FileSystemChange.Changed ("file2.txt", Some "b2")
FileSystemChange.Renamed ("file1.txt", ("file_1.txt", Some "b1"))
FileSystemChange.Renamed ("file2.txt", ("file_2.txt", Some "b2"))
FileSystemChange.Changed ("file_1.txt", Some "c1")
FileSystemChange.Changed ("file_2.txt", Some "c2")
FileSystemChange.Deleted "file_1.txt"
FileSystemChange.Deleted "file_2.txt"
]
run
|> retry_fn 3
|> _assertEqual (Some ())
Some () 00:00:03 d #1 FileSystem.watchWithFilter / Disposing watch stream / filter: FileName, LastWrite 00:00:03 d #2 FileSystem.testEventsRaw / eventsLog: 0 / 638989491342911185 / Created ("file1.txt", Some "a1") 14231 / 638989491342925416 / Changed ("file1.txt", Some "a1") 1738 / 638989491342927154 / Created ("file2.txt", Some "a2") 43 / 638989491342927197 / Changed ("file2.txt", Some "a2") 2501942 / 638989491345429139 / Changed ("file1.txt", Some "b1") 469 / 638989491345429608 / Changed ("file1.txt", Some "b1") 5655 / 638989491345435263 / Changed ("file2.txt", Some "b2") 225 / 638989491345435488 / Changed ("file2.txt", Some "b2") 2589646 / 638989491348025134 / Renamed ("file1.txt", ("file_1.txt", Some "b1")) 7769 / 638989491348032903 / Renamed ("file2.txt", ("file_2.txt", Some "b2")) 2541171 / 638989491350574074 / Changed ("file_1.txt", Some "c1") 441 / 638989491350574515 / Changed ("file_1.txt", Some "c1") 5728 / 638989491350580243 / Changed ("file_2.txt", Some "c2") 235 / 638989491350580478 / Changed ("file_2.txt", Some "c2") 2554526 / 638989491353135004 / Deleted "file_1.txt" 1253 / 638989491353136257 / Deleted "file_2.txt" [Created ("file1.txt", Some "a1"); Changed ("file1.txt", Some "a1"); Created ("file2.txt", Some "a2"); Changed ("file2.txt", Some "a2"); Changed ("file1.txt", Some "b1"); Changed ("file2.txt", Some "b2"); Renamed ("file1.txt", ("file_1.txt", Some "b1")); Renamed ("file2.txt", ("file_2.txt", Some "b2")); Changed ("file_1.txt", Some "c1"); Changed ("file_2.txt", Some "c2"); Deleted "file_1.txt"; Deleted "file_2.txt"] Some ()
slow (test)¶
In [ ]:
//// test
let inline write path = async {
let n = 2
let contents =
[ 1 .. n ]
|> List.map (string >> String.replicate 1_000_000)
for i = 1 to n do
do! $"{contents.[i - 1]}a" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
do! Async.Sleep 1500
for i = 1 to n do
do! $"{contents.[i - 1]}b" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
do! Async.Sleep 1500
for i = 1 to n do
do! path </> $"file{i}.txt" |> SpiralFileSystem.move_file_async (path </> $"file_{i}.txt") |> Async.Ignore
do! Async.Sleep 1500
for i = 1 to n do
do! $"{contents.[i - 1]}c" |> SpiralFileSystem.write_all_text_async (path </> $"file_{i}.txt")
do! Async.Sleep 1500
for i = 1 to n do
do! SpiralFileSystem.delete_file_async (path </> $"file_{i}.txt") |> Async.Ignore
do! Async.Sleep 1500
}
let inline run () =
let events =
testEventsRaw watchDirectory write
|> List.map (function
| FileSystemChange.Changed (path, Some content) ->
FileSystemChange.Changed (path, content |> Seq.distinct |> Seq.map string |> SpiralSm.concat "" |> Some)
| FileSystemChange.Created (path, Some content) ->
FileSystemChange.Created (path, content |> Seq.distinct |> Seq.map string |> SpiralSm.concat "" |> Some)
| FileSystemChange.Renamed (oldPath, (newPath, Some content)) ->
FileSystemChange.Renamed (
oldPath,
(newPath, content |> Seq.distinct |> Seq.map string |> SpiralSm.concat "" |> Some)
)
| event -> event
)
events
|> _sequenceEqual [
FileSystemChange.Created ("file1.txt", Some "1a")
FileSystemChange.Changed ("file1.txt", Some "1a")
FileSystemChange.Created ("file2.txt", Some "2a")
FileSystemChange.Changed ("file2.txt", Some "2a")
FileSystemChange.Changed ("file1.txt", Some "1b")
FileSystemChange.Changed ("file2.txt", Some "2b")
FileSystemChange.Renamed ("file1.txt", ("file_1.txt", Some "1b"))
FileSystemChange.Renamed ("file2.txt", ("file_2.txt", Some "2b"))
FileSystemChange.Changed ("file_1.txt", Some "1c")
FileSystemChange.Changed ("file_2.txt", Some "2c")
FileSystemChange.Deleted "file_1.txt"
FileSystemChange.Deleted "file_2.txt"
]
run
|> retry_fn 5
|> _assertEqual (Some ())
Some () 00:00:12 d #3 FileSystem.watchWithFilter / Disposing watch stream / filter: FileName, LastWrite 00:00:13 d #4 FileSystem.testEventsRaw / eventsLog: 0 / 638989491368548102 / Created ("file1.txt", ...11111111111111111111111111111111111111111111111a") 3161 / 638989491368551263 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111a") 236 / 638989491368551499 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 80 / 638989491368551579 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 236 / 638989491368551815 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 62 / 638989491368551877 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 693 / 638989491368552570 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 138 / 638989491368552708 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 332 / 638989491368553040 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 72 / 638989491368553112 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 173 / 638989491368553285 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 73 / 638989491368553358 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 106 / 638989491368553464 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 45 / 638989491368553509 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 144 / 638989491368553653 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 82 / 638989491368553735 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 177 / 638989491368553912 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 138 / 638989491368554050 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 111 / 638989491368554161 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 62 / 638989491368554223 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 189 / 638989491368554412 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 36 / 638989491368554448 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 64 / 638989491368554512 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 281 / 638989491368554793 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 42 / 638989491368554835 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 45 / 638989491368554880 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 188 / 638989491368555068 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 175 / 638989491368555243 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 30 / 638989491368555273 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 176 / 638989491368555449 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 88 / 638989491368555537 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 262 / 638989491368555799 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 54 / 638989491368555853 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 44 / 638989491368555897 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 193 / 638989491368556090 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 166 / 638989491368556256 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 55 / 638989491368556311 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 65 / 638989491368556376 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 269 / 638989491368556645 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 81 / 638989491368556726 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 30 / 638989491368556756 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 115 / 638989491368556871 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 199 / 638989491368557070 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 120 / 638989491368557190 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 113 / 638989491368557303 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 71 / 638989491368557374 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 44 / 638989491368557418 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 17406 / 638989491368574824 / Created ("file2.txt...22222222222222222222222222222222222222222222222a") 131 / 638989491368574955 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 59 / 638989491368575014 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 846 / 638989491368575860 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 1387 / 638989491368577247 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 3509 / 638989491368580756 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 669 / 638989491368581425 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 83 / 638989491368581508 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 194 / 638989491368581702 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 44 / 638989491368581746 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 192 / 638989491368581938 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 54 / 638989491368581992 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 188 / 638989491368582180 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 310 / 638989491368582490 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 50 / 638989491368582540 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 3378 / 638989491368585918 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 89 / 638989491368586007 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 42 / 638989491368586049 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 957 / 638989491368587006 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 70 / 638989491368587076 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 1105 / 638989491368588181 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 87 / 638989491368588268 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 8081 / 638989491368596349 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 15040998 / 638989491383637347 / Changed ("file1....11111111111111111111111111111111111111111111111b") 433 / 638989491383637780 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 2613 / 638989491383640393 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 104 / 638989491383640497 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 357 / 638989491383640854 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 213 / 638989491383641067 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 196 / 638989491383641263 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 377 / 638989491383641640 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 472 / 638989491383642112 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 403 / 638989491383642515 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 183 / 638989491383642698 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 184 / 638989491383642882 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 173 / 638989491383643055 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 172 / 638989491383643227 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 164 / 638989491383643391 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 51 / 638989491383643442 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 228 / 638989491383643670 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 162 / 638989491383643832 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 169 / 638989491383644001 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 187 / 638989491383644188 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 165 / 638989491383644353 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 169 / 638989491383644522 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 47 / 638989491383644569 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 268 / 638989491383644837 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 159 / 638989491383644996 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 176 / 638989491383645172 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 156 / 638989491383645328 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 163 / 638989491383645491 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 48 / 638989491383645539 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 195 / 638989491383645734 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 331 / 638989491383646065 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 76 / 638989491383646141 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 241 / 638989491383646382 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 155 / 638989491383646537 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 176 / 638989491383646713 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 176 / 638989491383646889 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 230 / 638989491383647119 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 169 / 638989491383647288 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 173 / 638989491383647461 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 210 / 638989491383647671 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 48 / 638989491383647719 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 166 / 638989491383647885 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 154 / 638989491383648039 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 173 / 638989491383648212 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 165 / 638989491383648377 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 171 / 638989491383648548 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 171 / 638989491383648719 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 50 / 638989491383648769 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 188 / 638989491383648957 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 144 / 638989491383649101 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 169 / 638989491383649270 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 175 / 638989491383649445 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 159 / 638989491383649604 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 189 / 638989491383649793 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 65 / 638989491383649858 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 38 / 638989491383649896 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 299 / 638989491383650195 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 215 / 638989491383650410 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 48 / 638989491383650458 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 183 / 638989491383650641 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 40 / 638989491383650681 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 245 / 638989491383650926 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 234 / 638989491383651160 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 170 / 638989491383651330 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 44 / 638989491383651374 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 200 / 638989491383651574 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 182 / 638989491383651756 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 171 / 638989491383651927 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 49 / 638989491383651976 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 197 / 638989491383652173 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 358 / 638989491383652531 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 247 / 638989491383652778 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 178 / 638989491383652956 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 47 / 638989491383653003 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 208 / 638989491383653211 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 163 / 638989491383653374 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 43 / 638989491383653417 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 236 / 638989491383653653 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 45 / 638989491383653698 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 320 / 638989491383654018 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 45 / 638989491383654063 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 187 / 638989491383654250 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 28 / 638989491383654278 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 183 / 638989491383654461 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 187 / 638989491383654648 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 67 / 638989491383654715 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 39 / 638989491383654754 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 300 / 638989491383655054 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 54 / 638989491383655108 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 219 / 638989491383655327 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 179 / 638989491383655506 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 48 / 638989491383655554 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 203 / 638989491383655757 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 58 / 638989491383655815 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 11881 / 638989491383667696 / Changed ("file2.txt...22222222222222222222222222222222222222222222222b") 114 / 638989491383667810 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 306 / 638989491383668116 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 212 / 638989491383668328 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 45 / 638989491383668373 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 191 / 638989491383668564 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 53 / 638989491383668617 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 198 / 638989491383668815 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 24 / 638989491383668839 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 261 / 638989491383669100 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 29 / 638989491383669129 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 196 / 638989491383669325 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 23 / 638989491383669348 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 194 / 638989491383669542 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 50 / 638989491383669592 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 826 / 638989491383670418 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 57 / 638989491383670475 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 45 / 638989491383670520 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 37 / 638989491383670557 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 253 / 638989491383670810 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 47 / 638989491383670857 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 153 / 638989491383671010 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 598 / 638989491383671608 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 64 / 638989491383671672 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 35 / 638989491383671707 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 227 / 638989491383671934 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 166 / 638989491383672100 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 368 / 638989491383672468 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 302 / 638989491383672770 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 202 / 638989491383672972 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 50 / 638989491383673022 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 195 / 638989491383673217 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 177 / 638989491383673394 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 425 / 638989491383673819 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 60 / 638989491383673879 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 164 / 638989491383674043 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 1224 / 638989491383675267 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222b") 97 / 638989491383675364 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 38 / 638989491383675402 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 223 / 638989491383675625 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 52 / 638989491383675677 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 179 / 638989491383675856 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 162 / 638989491383676018 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 236 / 638989491383676254 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 222 / 638989491383676476 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 181 / 638989491383676657 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 193 / 638989491383676850 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 156 / 638989491383677006 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 511 / 638989491383677517 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 173 / 638989491383677690 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 164 / 638989491383677854 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 234 / 638989491383678088 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 46 / 638989491383678134 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 171 / 638989491383678305 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 173 / 638989491383678478 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 146 / 638989491383678624 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 631 / 638989491383679255 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 183 / 638989491383679438 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 175 / 638989491383679613 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 180 / 638989491383679793 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 159 / 638989491383679952 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 46 / 638989491383679998 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 180 / 638989491383680178 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 45 / 638989491383680223 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 162 / 638989491383680385 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 664 / 638989491383681049 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 123 / 638989491383681172 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 42 / 638989491383681214 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 233 / 638989491383681447 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 199 / 638989491383681646 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 207 / 638989491383681853 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 997 / 638989491383682850 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 68 / 638989491383682918 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 38 / 638989491383682956 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 293 / 638989491383683249 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 206 / 638989491383683455 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 165 / 638989491383683620 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 133 / 638989491383683753 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 527 / 638989491383684280 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 199 / 638989491383684479 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 47 / 638989491383684526 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 163 / 638989491383684689 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 61 / 638989491383684750 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 138 / 638989491383684888 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 15048698 / 638989491398733586 / Renamed ("file1....1111111111111111111111111111111111111111111111b")) 538 / 638989491398734124 / Renamed ("file2.txt",...2222222222222222222222222222222222222222222222b")) 15055228 / 638989491413789352 / Changed ("file_1...11111111111111111111111111111111111111111111111c") 535 / 638989491413789887 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 764 / 638989491413790651 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 128 / 638989491413790779 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 71 / 638989491413790850 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 45 / 638989491413790895 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 434 / 638989491413791329 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 57 / 638989491413791386 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 74 / 638989491413791460 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 44 / 638989491413791504 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 57 / 638989491413791561 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 409 / 638989491413791970 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 95 / 638989491413792065 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 38 / 638989491413792103 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 1058 / 638989491413793161 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 173 / 638989491413793334 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 210 / 638989491413793544 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 708 / 638989491413794252 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 486 / 638989491413794738 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 471 / 638989491413795209 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 87 / 638989491413795296 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 192 / 638989491413795488 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 184 / 638989491413795672 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 314 / 638989491413795986 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 67 / 638989491413796053 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 150 / 638989491413796203 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 171 / 638989491413796374 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 5236 / 638989491413801610 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 114 / 638989491413801724 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 527 / 638989491413802251 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 825 / 638989491413803076 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 77 / 638989491413803153 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 59 / 638989491413803212 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 1296 / 638989491413804508 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 97 / 638989491413804605 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 519 / 638989491413805124 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 80 / 638989491413805204 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 63 / 638989491413805267 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 344 / 638989491413805611 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 230 / 638989491413805841 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 44 / 638989491413805885 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 75 / 638989491413805960 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 354 / 638989491413806314 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 72 / 638989491413806386 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 55 / 638989491413806441 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 337 / 638989491413806778 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 17846 / 638989491413824624 / Changed ("file_2.tx...22222222222222222222222222222222222222222222222c") 197 / 638989491413824821 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 335 / 638989491413825156 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 90 / 638989491413825246 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 164 / 638989491413825410 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 52 / 638989491413825462 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 290 / 638989491413825752 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 113 / 638989491413825865 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 298 / 638989491413826163 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 210 / 638989491413826373 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 60 / 638989491413826433 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 262 / 638989491413826695 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 152 / 638989491413826847 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 168 / 638989491413827015 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 48 / 638989491413827063 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 208 / 638989491413827271 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 160 / 638989491413827431 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 47 / 638989491413827478 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 60 / 638989491413827538 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 848 / 638989491413828386 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 87 / 638989491413828473 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 232 / 638989491413828705 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 57 / 638989491413828762 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 190 / 638989491413828952 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 363 / 638989491413829315 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 367 / 638989491413829682 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 101 / 638989491413829783 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 46 / 638989491413829829 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 348 / 638989491413830177 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 215 / 638989491413830392 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 27 / 638989491413830419 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 174 / 638989491413830593 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 48 / 638989491413830641 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 271 / 638989491413830912 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 49 / 638989491413830961 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 196 / 638989491413831157 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 333 / 638989491413831490 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 65 / 638989491413831555 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 244 / 638989491413831799 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 52 / 638989491413831851 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 369 / 638989491413832220 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 212 / 638989491413832432 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 991 / 638989491413833423 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 77 / 638989491413833500 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 210 / 638989491413833710 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 174 / 638989491413833884 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 53 / 638989491413833937 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 187 / 638989491413834124 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 66 / 638989491413834190 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 175 / 638989491413834365 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 155 / 638989491413834520 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 161 / 638989491413834681 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 166 / 638989491413834847 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 49 / 638989491413834896 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 170 / 638989491413835066 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 66 / 638989491413835132 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 121 / 638989491413835253 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 177 / 638989491413835430 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 39 / 638989491413835469 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 708 / 638989491413836177 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 73 / 638989491413836250 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 40 / 638989491413836290 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 216 / 638989491413836506 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 57 / 638989491413836563 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 157 / 638989491413836720 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 152 / 638989491413836872 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 176 / 638989491413837048 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 165 / 638989491413837213 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 189 / 638989491413837402 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 49 / 638989491413837451 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 148 / 638989491413837599 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 191 / 638989491413837790 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 379 / 638989491413838169 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 61 / 638989491413838230 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 389 / 638989491413838619 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 267 / 638989491413838886 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 53 / 638989491413838939 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 382 / 638989491413839321 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 64 / 638989491413839385 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 431 / 638989491413839816 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 248 / 638989491413840064 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 46 / 638989491413840110 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 325 / 638989491413840435 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 15042778 / 638989491428883213 / Deleted "file_1.txt" 2633 / 638989491428885846 / Deleted "file_2.txt" [Created ("file1.txt", Some "1a"); Changed ("file1.txt", Some "1a"); Created ("file2.txt", Some "2a"); Changed ("file2.txt", Some "2a"); Changed ("file1.txt", Some "1b"); Changed ("file2.txt", Some "2b"); Renamed ("file1.txt", ("file_1.txt", Some "1b")); Renamed ("file2.txt", ("file_2.txt", Some "2b")); Changed ("file_1.txt", Some "1c"); Changed ("file_2.txt", Some "2c"); Deleted "file_1.txt"; Deleted "file_2.txt"] Some ()
testEventsSorted (test)¶
In [ ]:
//// test
let inline sortEvent event =
match event with
| FileSystemChange.Failure _ -> 0
| FileSystemChange.Created _ -> 1
| FileSystemChange.Changed _ -> 2
| FileSystemChange.Renamed (_oldPath, _) -> 3
| FileSystemChange.Deleted _ -> 4
let inline formatEvents events =
events
|> Seq.toList
|> List.sortBy (snd >> sortEvent)
|> List.choose (fun (ticks, event) ->
match event with
| FileSystemChange.Failure _ ->
None
| FileSystemChange.Changed (path, _) ->
Some (ticks, System.IO.Path.GetFileName path, nameof FileSystemChangeType.Changed)
| FileSystemChange.Created (path, _) ->
Some (ticks, System.IO.Path.GetFileName path, nameof FileSystemChangeType.Created)
| FileSystemChange.Deleted path ->
Some (ticks, System.IO.Path.GetFileName path, nameof FileSystemChangeType.Deleted)
| FileSystemChange.Renamed (_oldPath, (path, _)) ->
Some (ticks, System.IO.Path.GetFileName path, nameof FileSystemChangeType.Renamed)
)
|> List.sortBy (fun (_, path, _) -> path)
|> List.distinctBy (fun (_, path, event) -> path, event)
let inline testEventsSorted
(watchFn : string -> FSharp.Control.AsyncSeq<int64 * FileSystemChange> * IDisposable)
write
=
let struct (tempDir, tempDisposable) =
"FileSystem.testEventsSorted"
|> SpiralCrypto.hash_text
|> SpiralFileSystem.create_temp_dir'
let stream, disposable = watchFn tempDir
let events = System.Collections.Concurrent.ConcurrentBag ()
let inline iter () =
stream
|> FSharp.Control.AsyncSeq.iterAsyncParallel (fun event -> async { events.Add event })
let run = async {
let! _ = iter () |> Async.StartChild
do! Async.Sleep 250
return! write tempDir
}
try
run
|> Async.runWithTimeout 5000
|> _assertEqual (Some ())
finally
disposable.Dispose ()
tempDisposable.Dispose ()
let events = formatEvents events
let eventMap =
events
|> List.map (fun (ticks, path, event) -> path, (event, ticks))
|> List.groupBy fst
|> List.map (fun (path, events) ->
let event, _ticks =
events
|> List.map snd
|> List.sortByDescending snd
|> List.head
path, event
)
|> Map.ofList
let eventList =
events
|> List.map (fun (_ticks, path, event) -> path, event)
eventMap, eventList
create and delete (test)¶
In [ ]:
//// test
let inline write path = async {
let n = 3
for i = 1 to n do
do! $"{i}" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
for i = 1 to n do
do! SpiralFileSystem.delete_file_async (path </> $"file{i}.txt") |> Async.Ignore
do! Async.Sleep 150
}
let inline run () =
let eventMap, eventList = testEventsSorted (watchDirectory (fun _ -> false)) write
[
"file1.txt", nameof FileSystemChangeType.Created
"file1.txt", nameof FileSystemChangeType.Changed
"file1.txt", nameof FileSystemChangeType.Deleted
"file2.txt", nameof FileSystemChangeType.Created
"file2.txt", nameof FileSystemChangeType.Changed
"file2.txt", nameof FileSystemChangeType.Deleted
"file3.txt", nameof FileSystemChangeType.Created
"file3.txt", nameof FileSystemChangeType.Changed
"file3.txt", nameof FileSystemChangeType.Deleted
]
|> _sequenceEqual eventList
[
"file1.txt", nameof FileSystemChangeType.Deleted
"file2.txt", nameof FileSystemChangeType.Deleted
"file3.txt", nameof FileSystemChangeType.Deleted
]
|> Map.ofList
|> _sequenceEqual eventMap
run
|> retry_fn 3
|> _assertEqual (Some ())
Some ()
00:00:15 d #5 FileSystem.watchWithFilter / Disposing watch stream / filter: FileName, LastWrite
[("file1.txt", "Created"); ("file1.txt", "Changed"); ("file1.txt", "Deleted"); ("file2.txt", "Created");
("file2.txt", "Changed"); ("file2.txt", "Deleted"); ("file3.txt", "Created"); ("file3.txt", "Changed");
("file3.txt", "Deleted")]
map [("file1.txt", "Deleted"); ("file2.txt", "Deleted"); ("file3.txt", "Deleted")]
Some ()
change (test)¶
In [ ]:
//// test
let inline write path = async {
let n = 2
for i = 1 to n do
do! $"{i}" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
for i = 1 to n do
do! "" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
for i = 1 to n do
do! SpiralFileSystem.delete_file_async (path </> $"file{i}.txt") |> Async.Ignore
do! Async.Sleep 150
}
let inline run () =
let eventMap, eventList = testEventsSorted (watchDirectory (fun _ -> false)) write
[
"file1.txt", nameof FileSystemChangeType.Created
"file1.txt", nameof FileSystemChangeType.Changed
"file1.txt", nameof FileSystemChangeType.Deleted
"file2.txt", nameof FileSystemChangeType.Created
"file2.txt", nameof FileSystemChangeType.Changed
"file2.txt", nameof FileSystemChangeType.Deleted
]
|> _sequenceEqual eventList
[
"file1.txt", nameof FileSystemChangeType.Deleted
"file2.txt", nameof FileSystemChangeType.Deleted
]
|> Map.ofList
|> _sequenceEqual eventMap
run
|> retry_fn 3
|> _assertEqual (Some ())
Some ()
00:00:16 d #6 FileSystem.watchWithFilter / Disposing watch stream / filter: FileName, LastWrite
[("file1.txt", "Created"); ("file1.txt", "Changed"); ("file1.txt", "Deleted"); ("file2.txt", "Created");
("file2.txt", "Changed"); ("file2.txt", "Deleted")]
map [("file1.txt", "Deleted"); ("file2.txt", "Deleted")]
Some ()
rename (test)¶
In [ ]:
//// test
let inline write path = async {
let n = 2
for i = 1 to n do
do! $"{i}" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
for i = 1 to n do
do! path </> $"file{i}.txt" |> SpiralFileSystem.move_file_async (path </> $"file_{i}.txt") |> Async.Ignore
for i = 1 to n do
do! SpiralFileSystem.delete_file_async (path </> $"file_{i}.txt") |> Async.Ignore
do! Async.Sleep 150
}
let inline run () =
let eventMap, eventList = testEventsSorted (watchDirectory (fun _ -> false)) write
[
"file1.txt", nameof FileSystemChangeType.Created
"file1.txt", nameof FileSystemChangeType.Changed
"file2.txt", nameof FileSystemChangeType.Created
"file2.txt", nameof FileSystemChangeType.Changed
"file_1.txt", nameof FileSystemChangeType.Renamed
"file_1.txt", nameof FileSystemChangeType.Deleted
"file_2.txt", nameof FileSystemChangeType.Renamed
"file_2.txt", nameof FileSystemChangeType.Deleted
]
|> _sequenceEqual eventList
[
"file1.txt", nameof FileSystemChangeType.Changed
"file2.txt", nameof FileSystemChangeType.Changed
"file_1.txt", nameof FileSystemChangeType.Deleted
"file_2.txt", nameof FileSystemChangeType.Deleted
]
|> Map.ofList
|> _sequenceEqual eventMap
run
|> retry_fn 3
|> _assertEqual (Some ())
Some ()
00:00:17 d #7 FileSystem.watchWithFilter / Disposing watch stream / filter: FileName, LastWrite
[("file1.txt", "Created"); ("file1.txt", "Changed"); ("file2.txt", "Created"); ("file2.txt", "Changed");
("file_1.txt", "Renamed"); ("file_1.txt", "Deleted"); ("file_2.txt", "Renamed"); ("file_2.txt", "Deleted")]
map [("file1.txt", "Changed"); ("file2.txt", "Changed"); ("file_1.txt", "Deleted"); ("file_2.txt", "Deleted")]
Some ()
full (test)¶
In [ ]:
//// test
let inline write path = async {
let n = 2
for i = 1 to n do
do! $"{i}" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
for i = 1 to n do
do! "" |> SpiralFileSystem.write_all_text_async (path </> $"file{i}.txt")
for i = 1 to n do
do! path </> $"file{i}.txt" |> SpiralFileSystem.move_file_async (path </> $"file_{i}.txt") |> Async.Ignore
for i = 1 to n do
do! $"{i}" |> SpiralFileSystem.write_all_text_async (path </> $"file_{i}.txt")
for i = 1 to n do
do! SpiralFileSystem.delete_file_async (path </> $"file_{i}.txt") |> Async.Ignore
do! Async.Sleep 150
}
let inline run () =
let eventMap, eventList = testEventsSorted (watchDirectory (fun _ -> false)) write
[
"file1.txt", nameof FileSystemChangeType.Created
"file1.txt", nameof FileSystemChangeType.Changed
"file2.txt", nameof FileSystemChangeType.Created
"file2.txt", nameof FileSystemChangeType.Changed
"file_1.txt", nameof FileSystemChangeType.Changed
"file_1.txt", nameof FileSystemChangeType.Renamed
"file_1.txt", nameof FileSystemChangeType.Deleted
"file_2.txt", nameof FileSystemChangeType.Changed
"file_2.txt", nameof FileSystemChangeType.Renamed
"file_2.txt", nameof FileSystemChangeType.Deleted
]
|> _sequenceEqual eventList
[
"file1.txt", nameof FileSystemChangeType.Changed
"file2.txt", nameof FileSystemChangeType.Changed
"file_1.txt", nameof FileSystemChangeType.Deleted
"file_2.txt", nameof FileSystemChangeType.Deleted
]
|> Map.ofList
|> _sequenceEqual eventMap
run
|> retry_fn 3
|> _assertEqual (Some ())
Some ()
00:00:18 d #8 FileSystem.watchWithFilter / Disposing watch stream / filter: FileName, LastWrite
[("file1.txt", "Created"); ("file1.txt", "Changed"); ("file2.txt", "Created"); ("file2.txt", "Changed");
("file_1.txt", "Changed"); ("file_1.txt", "Renamed"); ("file_1.txt", "Deleted"); ("file_2.txt", "Changed");
("file_2.txt", "Renamed"); ("file_2.txt", "Deleted")]
map [("file1.txt", "Changed"); ("file2.txt", "Changed"); ("file_1.txt", "Deleted"); ("file_2.txt", "Deleted")]
Some ()