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 / 638798684478652663 / Created ("file1.txt", Some "a1") 12823 / 638798684478665486 / Changed ("file1.txt", Some "a1") 1594 / 638798684478667080 / Created ("file2.txt", Some "a2") 45 / 638798684478667125 / Changed ("file2.txt", Some "a2") 2492153 / 638798684481159278 / Changed ("file1.txt", Some "b1") 398 / 638798684481159676 / Changed ("file1.txt", Some "b1") 5173 / 638798684481164849 / Changed ("file2.txt", Some "b2") 208 / 638798684481165057 / Changed ("file2.txt", Some "b2") 2563582 / 638798684483728639 / Renamed ("file1.txt", ("file_1.txt", Some "b1")) 7851 / 638798684483736490 / Renamed ("file2.txt", ("file_2.txt", Some "b2")) 2522425 / 638798684486258915 / Changed ("file_1.txt", Some "c1") 591 / 638798684486259506 / Changed ("file_1.txt", Some "c1") 4767 / 638798684486264273 / Changed ("file_2.txt", Some "c2") 209 / 638798684486264482 / Changed ("file_2.txt", Some "c2") 2535006 / 638798684488799488 / Deleted "file_1.txt" 1109 / 638798684488800597 / 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 / 638798684503572973 / Created ("file1.txt", ...11111111111111111111111111111111111111111111111a") 3560 / 638798684503576533 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111a") 265 / 638798684503576798 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 55 / 638798684503576853 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 63 / 638798684503576916 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 43 / 638798684503576959 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 340 / 638798684503577299 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 121 / 638798684503577420 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 179 / 638798684503577599 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 239 / 638798684503577838 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 64 / 638798684503577902 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 87 / 638798684503577989 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 84 / 638798684503578073 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 234 / 638798684503578307 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 109 / 638798684503578416 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 83 / 638798684503578499 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 166 / 638798684503578665 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 308 / 638798684503578973 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 99 / 638798684503579072 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 60 / 638798684503579132 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 234 / 638798684503579366 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 164 / 638798684503579530 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 71 / 638798684503579601 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 229 / 638798684503579830 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 261 / 638798684503580091 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 192 / 638798684503580283 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 170 / 638798684503580453 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 178 / 638798684503580631 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 54 / 638798684503580685 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 216 / 638798684503580901 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 70 / 638798684503580971 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 229 / 638798684503581200 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 179 / 638798684503581379 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 53 / 638798684503581432 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 137 / 638798684503581569 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 148 / 638798684503581717 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 182 / 638798684503581899 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 68 / 638798684503581967 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 203 / 638798684503582170 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 55 / 638798684503582225 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 196 / 638798684503582421 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 59 / 638798684503582480 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 177 / 638798684503582657 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 56 / 638798684503582713 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 165 / 638798684503582878 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 169 / 638798684503583047 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 53 / 638798684503583100 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 193 / 638798684503583293 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 56 / 638798684503583349 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 168 / 638798684503583517 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 48 / 638798684503583565 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 213 / 638798684503583778 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 227 / 638798684503584005 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 207 / 638798684503584212 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 153 / 638798684503584365 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 144 / 638798684503584509 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 151 / 638798684503584660 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 163 / 638798684503584823 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 165 / 638798684503584988 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 141 / 638798684503585129 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 133 / 638798684503585262 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 138 / 638798684503585400 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 162 / 638798684503585562 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 40 / 638798684503585602 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 222 / 638798684503585824 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 122 / 638798684503585946 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 40 / 638798684503585986 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 6987 / 638798684503592973 / Created ("file2.txt"...22222222222222222222222222222222222222222222222a") 151 / 638798684503593124 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 290 / 638798684503593414 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 244 / 638798684503593658 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 1034 / 638798684503594692 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 83 / 638798684503594775 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 46 / 638798684503594821 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 258 / 638798684503595079 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 58 / 638798684503595137 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 55 / 638798684503595192 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 189 / 638798684503595381 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 53 / 638798684503595434 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 191 / 638798684503595625 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 55 / 638798684503595680 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 156 / 638798684503595836 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 166 / 638798684503596002 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 51 / 638798684503596053 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 143 / 638798684503596196 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 149 / 638798684503596345 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 153 / 638798684503596498 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 50 / 638798684503596548 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 196 / 638798684503596744 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 153 / 638798684503596897 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 65 / 638798684503596962 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 168 / 638798684503597130 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 50 / 638798684503597180 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 186 / 638798684503597366 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 51 / 638798684503597417 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 226 / 638798684503597643 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 55 / 638798684503597698 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 226 / 638798684503597924 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 58 / 638798684503597982 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 156 / 638798684503598138 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 48 / 638798684503598186 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 204 / 638798684503598390 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 53 / 638798684503598443 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 268 / 638798684503598711 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 225 / 638798684503598936 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 345 / 638798684503599281 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 40 / 638798684503599321 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 45 / 638798684503599366 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 2270 / 638798684503601636 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 101 / 638798684503601737 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 524 / 638798684503602261 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 47 / 638798684503602308 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 44 / 638798684503602352 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 379 / 638798684503602731 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 57 / 638798684503602788 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 166 / 638798684503602954 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 543 / 638798684503603497 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 56 / 638798684503603553 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 1055 / 638798684503604608 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 2156 / 638798684503606764 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 97 / 638798684503606861 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 981 / 638798684503607842 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 15040378 / 638798684518648220 / Changed ("file1....11111111111111111111111111111111111111111111111b") 425 / 638798684518648645 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 605 / 638798684518649250 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 1340 / 638798684518650590 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 164 / 638798684518650754 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 57 / 638798684518650811 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 1183 / 638798684518651994 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 106 / 638798684518652100 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 30 / 638798684518652130 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 47 / 638798684518652177 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 195 / 638798684518652372 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 52 / 638798684518652424 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 149 / 638798684518652573 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 1662 / 638798684518654235 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 101 / 638798684518654336 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 122 / 638798684518654458 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 338 / 638798684518654796 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 102 / 638798684518654898 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 51 / 638798684518654949 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 301 / 638798684518655250 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 62 / 638798684518655312 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 44 / 638798684518655356 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 225 / 638798684518655581 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 53 / 638798684518655634 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 201 / 638798684518655835 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 186 / 638798684518656021 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 72 / 638798684518656093 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 1350 / 638798684518657443 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 93 / 638798684518657536 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 401 / 638798684518657937 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 2618 / 638798684518660555 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 98 / 638798684518660653 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 55 / 638798684518660708 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 239 / 638798684518660947 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 176 / 638798684518661123 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 170 / 638798684518661293 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 235 / 638798684518661528 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 64 / 638798684518661592 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 1067 / 638798684518662659 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 283 / 638798684518662942 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 245 / 638798684518663187 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 272 / 638798684518663459 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 304 / 638798684518663763 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 423 / 638798684518664186 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 209 / 638798684518664395 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 199 / 638798684518664594 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 803 / 638798684518665397 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 83 / 638798684518665480 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 201 / 638798684518665681 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 55 / 638798684518665736 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 174 / 638798684518665910 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 201 / 638798684518666111 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 187 / 638798684518666298 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 189 / 638798684518666487 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 229 / 638798684518666716 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 166 / 638798684518666882 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 50 / 638798684518666932 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 176 / 638798684518667108 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 50 / 638798684518667158 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 188 / 638798684518667346 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 241 / 638798684518667587 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 251 / 638798684518667838 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 48 / 638798684518667886 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 248 / 638798684518668134 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 15901 / 638798684518684035 / Changed ("file2.txt...22222222222222222222222222222222222222222222222b") 131 / 638798684518684166 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 321 / 638798684518684487 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 168 / 638798684518684655 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 65 / 638798684518684720 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 144 / 638798684518684864 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 53 / 638798684518684917 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 154 / 638798684518685071 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 172 / 638798684518685243 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 286 / 638798684518685529 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 38 / 638798684518685567 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 364 / 638798684518685931 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 70 / 638798684518686001 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 215 / 638798684518686216 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 50 / 638798684518686266 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 159 / 638798684518686425 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 49 / 638798684518686474 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 373 / 638798684518686847 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 69 / 638798684518686916 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 233 / 638798684518687149 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 37 / 638798684518687186 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 157 / 638798684518687343 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 390 / 638798684518687733 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 54 / 638798684518687787 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 189 / 638798684518687976 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 158 / 638798684518688134 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 242 / 638798684518688376 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 71 / 638798684518688447 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 144 / 638798684518688591 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 49 / 638798684518688640 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 402 / 638798684518689042 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 237 / 638798684518689279 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 53 / 638798684518689332 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 199 / 638798684518689531 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 156 / 638798684518689687 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 220 / 638798684518689907 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 168 / 638798684518690075 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 210 / 638798684518690285 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 201 / 638798684518690486 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 48 / 638798684518690534 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 804 / 638798684518691338 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 67 / 638798684518691405 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 192 / 638798684518691597 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 175 / 638798684518691772 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 157 / 638798684518691929 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 49 / 638798684518691978 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 174 / 638798684518692152 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 51 / 638798684518692203 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 193 / 638798684518692396 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 159 / 638798684518692555 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 196 / 638798684518692751 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 160 / 638798684518692911 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 48 / 638798684518692959 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 171 / 638798684518693130 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 683 / 638798684518693813 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 76 / 638798684518693889 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 42 / 638798684518693931 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 197 / 638798684518694128 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 61 / 638798684518694189 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 179 / 638798684518694368 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 164 / 638798684518694532 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 193 / 638798684518694725 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 160 / 638798684518694885 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 160 / 638798684518695045 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 147 / 638798684518695192 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 160 / 638798684518695352 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 221 / 638798684518695573 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 315 / 638798684518695888 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 57 / 638798684518695945 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 198 / 638798684518696143 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 806 / 638798684518696949 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 84 / 638798684518697033 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 45 / 638798684518697078 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 217 / 638798684518697295 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 53 / 638798684518697348 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 178 / 638798684518697526 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 163 / 638798684518697689 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 162 / 638798684518697851 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 157 / 638798684518698008 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 49 / 638798684518698057 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 188 / 638798684518698245 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 58 / 638798684518698303 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 184 / 638798684518698487 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 188 / 638798684518698675 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 322 / 638798684518698997 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 182 / 638798684518699179 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 53 / 638798684518699232 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 209 / 638798684518699441 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 43 / 638798684518699484 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 215 / 638798684518699699 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 46 / 638798684518699745 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 213 / 638798684518699958 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 196 / 638798684518700154 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 32 / 638798684518700186 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 195 / 638798684518700381 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 26 / 638798684518700407 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 218 / 638798684518700625 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 15016146 / 638798684533716771 / Renamed ("file1....1111111111111111111111111111111111111111111111b")) 388 / 638798684533717159 / Renamed ("file2.txt",...2222222222222222222222222222222222222222222222b")) 15065577 / 638798684548782736 / Changed ("file_1...11111111111111111111111111111111111111111111111c") 401 / 638798684548783137 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 15330 / 638798684548798467 / Changed ("file_1.tx...11111111111111111111111111111111111111111111111c") 19633 / 638798684548818100 / Changed ("file_2.tx...22222222222222222222222222222222222222222222222c") 200 / 638798684548818300 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 366 / 638798684548818666 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 394 / 638798684548819060 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 532 / 638798684548819592 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 45 / 638798684548819637 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 196 / 638798684548819833 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 31 / 638798684548819864 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 189 / 638798684548820053 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 35 / 638798684548820088 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 237 / 638798684548820325 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 17 / 638798684548820342 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 179 / 638798684548820521 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 34 / 638798684548820555 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 214 / 638798684548820769 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 219 / 638798684548820988 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 179 / 638798684548821167 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 115 / 638798684548821282 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 150 / 638798684548821432 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 135 / 638798684548821567 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 140 / 638798684548821707 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 103 / 638798684548821810 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 176 / 638798684548821986 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 170 / 638798684548822156 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 33 / 638798684548822189 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 164 / 638798684548822353 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 171 / 638798684548822524 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 153 / 638798684548822677 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 155 / 638798684548822832 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 167 / 638798684548822999 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 35 / 638798684548823034 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 382 / 638798684548823416 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 115 / 638798684548823531 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 148 / 638798684548823679 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 33 / 638798684548823712 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 194 / 638798684548823906 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 167 / 638798684548824073 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 144 / 638798684548824217 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 52 / 638798684548824269 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 741 / 638798684548825010 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 220 / 638798684548825230 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 162 / 638798684548825392 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 165 / 638798684548825557 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 141 / 638798684548825698 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 163 / 638798684548825861 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 154 / 638798684548826015 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 171 / 638798684548826186 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 122 / 638798684548826308 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 456 / 638798684548826764 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 43 / 638798684548826807 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 236 / 638798684548827043 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 149 / 638798684548827192 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 168 / 638798684548827360 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 177 / 638798684548827537 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 154 / 638798684548827691 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 149 / 638798684548827840 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 156 / 638798684548827996 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 188 / 638798684548828184 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 141 / 638798684548828325 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 138 / 638798684548828463 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 161 / 638798684548828624 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 304 / 638798684548828928 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 246 / 638798684548829174 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 131 / 638798684548829305 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 354 / 638798684548829659 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 37 / 638798684548829696 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 182 / 638798684548829878 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 190 / 638798684548830068 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 163 / 638798684548830231 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 151 / 638798684548830382 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 227 / 638798684548830609 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 159 / 638798684548830768 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 200 / 638798684548830968 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 149 / 638798684548831117 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 32 / 638798684548831149 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 199 / 638798684548831348 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 54 / 638798684548831402 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 621 / 638798684548832023 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 51 / 638798684548832074 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 206 / 638798684548832280 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 153 / 638798684548832433 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 149 / 638798684548832582 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 442 / 638798684548833024 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 209 / 638798684548833233 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 154 / 638798684548833387 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 155 / 638798684548833542 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 182 / 638798684548833724 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 8632 / 638798684548842356 / Changed ("file_2.txt...22222222222222222222222222222222222222222222222c") 15009073 / 638798684563851429 / Deleted "file_1.txt" 2570 / 638798684563853999 / 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 ()