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 / 638859607878752173 / Created ("file1.txt", Some "a1") 12090 / 638859607878764263 / Changed ("file1.txt", Some "a1") 1550 / 638859607878765813 / Created ("file2.txt", Some "a2") 45 / 638859607878765858 / Changed ("file2.txt", Some "a2") 2475825 / 638859607881241683 / Changed ("file1.txt", Some "b1") 547 / 638859607881242230 / Changed ("file1.txt", Some "b1") 4958 / 638859607881247188 / Changed ("file2.txt", Some "b2") 238 / 638859607881247426 / Changed ("file2.txt", Some "b2") 2556224 / 638859607883803650 / Renamed ("file1.txt", ("file_1.txt", Some "b1")) 8930 / 638859607883812580 / Renamed ("file2.txt", ("file_2.txt", Some "b2")) 2518549 / 638859607886331129 / Changed ("file_1.txt", Some "c1") 1591 / 638859607886332720 / Changed ("file_1.txt", Some "c1") 4917 / 638859607886337637 / Changed ("file_2.txt", Some "c2") 599 / 638859607886338236 / Changed ("file_2.txt", Some "c2") 2528208 / 638859607888866444 / Deleted "file_1.txt" 1091 / 638859607888867535 / 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 / 638859607902957734 / Created ("file1.txt", ...11111111111111111111111111111111111111111111111a") 3176 / 638859607902960910 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111a") 311 / 638859607902961221 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 351 / 638859607902961572 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 229 / 638859607902961801 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 194 / 638859607902961995 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 61 / 638859607902962056 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 77 / 638859607902962133 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 464 / 638859607902962597 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 136 / 638859607902962733 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 44 / 638859607902962777 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 540 / 638859607902963317 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 123 / 638859607902963440 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 320 / 638859607902963760 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 84 / 638859607902963844 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 89 / 638859607902963933 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 172 / 638859607902964105 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 117 / 638859607902964222 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 89 / 638859607902964311 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 828 / 638859607902965139 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 96 / 638859607902965235 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 51 / 638859607902965286 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 455 / 638859607902965741 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 59 / 638859607902965800 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 43 / 638859607902965843 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 299 / 638859607902966142 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 191 / 638859607902966333 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 43 / 638859607902966376 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 200 / 638859607902966576 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 161 / 638859607902966737 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 70 / 638859607902966807 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 41 / 638859607902966848 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 277 / 638859607902967125 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 39 / 638859607902967164 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 42 / 638859607902967206 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 299 / 638859607902967505 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 62 / 638859607902967567 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 67 / 638859607902967634 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 380 / 638859607902968014 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 257 / 638859607902968271 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 17578 / 638859607902985849 / Created ("file2.txt...22222222222222222222222222222222222222222222222a") 117 / 638859607902985966 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 36 / 638859607902986002 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 54 / 638859607902986056 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 43 / 638859607902986099 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 296 / 638859607902986395 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 53 / 638859607902986448 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 274 / 638859607902986722 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 57 / 638859607902986779 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 328 / 638859607902987107 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 68 / 638859607902987175 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 4358 / 638859607902991533 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 89 / 638859607902991622 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 51 / 638859607902991673 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 1004 / 638859607902992677 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 81 / 638859607902992758 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 1021 / 638859607902993779 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 84 / 638859607902993863 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 849 / 638859607902994712 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 82 / 638859607902994794 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 51 / 638859607902994845 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 394 / 638859607902995239 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 332 / 638859607902995571 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 43 / 638859607902995614 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 430 / 638859607902996044 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 56 / 638859607902996100 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 539 / 638859607902996639 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 61 / 638859607902996700 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 47 / 638859607902996747 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 1245 / 638859607902997992 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 292 / 638859607902998284 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 32 / 638859607902998316 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 909 / 638859607902999225 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 79 / 638859607902999304 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 40 / 638859607902999344 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 907 / 638859607903000251 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 68 / 638859607903000319 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 1109 / 638859607903001428 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 15021867 / 638859607918023295 / Changed ("file1....11111111111111111111111111111111111111111111111b") 287 / 638859607918023582 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 3518 / 638859607918027100 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 133 / 638859607918027233 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 67 / 638859607918027300 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 198 / 638859607918027498 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 230 / 638859607918027728 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 180 / 638859607918027908 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 71 / 638859607918027979 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 369 / 638859607918028348 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 212 / 638859607918028560 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 168 / 638859607918028728 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 152 / 638859607918028880 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 164 / 638859607918029044 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 157 / 638859607918029201 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 123 / 638859607918029324 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 69 / 638859607918029393 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 162 / 638859607918029555 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 191 / 638859607918029746 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 154 / 638859607918029900 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 170 / 638859607918030070 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 154 / 638859607918030224 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 170 / 638859607918030394 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 177 / 638859607918030571 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 159 / 638859607918030730 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 155 / 638859607918030885 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 162 / 638859607918031047 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 156 / 638859607918031203 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 159 / 638859607918031362 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 342 / 638859607918031704 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 345 / 638859607918032049 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 866 / 638859607918032915 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 73 / 638859607918032988 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 224 / 638859607918033212 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 192 / 638859607918033404 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 220 / 638859607918033624 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 191 / 638859607918033815 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 163 / 638859607918033978 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 50 / 638859607918034028 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 175 / 638859607918034203 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 52 / 638859607918034255 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 186 / 638859607918034441 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 50 / 638859607918034491 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 463 / 638859607918034954 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 133 / 638859607918035087 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 272 / 638859607918035359 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 63 / 638859607918035422 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 54 / 638859607918035476 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 478 / 638859607918035954 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 312 / 638859607918036266 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 56 / 638859607918036322 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 722 / 638859607918037044 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 78 / 638859607918037122 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 46 / 638859607918037168 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 234 / 638859607918037402 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 290 / 638859607918037692 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 43 / 638859607918037735 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 483 / 638859607918038218 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 65 / 638859607918038283 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 831 / 638859607918039114 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 74 / 638859607918039188 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 11548 / 638859607918050736 / Changed ("file1.txt...11111111111111111111111111111111111111111111111b") 110 / 638859607918050846 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 52 / 638859607918050898 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 46 / 638859607918050944 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 149 / 638859607918051093 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 206 / 638859607918051299 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 115 / 638859607918051414 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 250 / 638859607918051664 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 227 / 638859607918051891 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 204 / 638859607918052095 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 173 / 638859607918052268 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 119 / 638859607918052387 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 169 / 638859607918052556 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 117 / 638859607918052673 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 170 / 638859607918052843 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 114 / 638859607918052957 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 183 / 638859607918053140 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 211 / 638859607918053351 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 224 / 638859607918053575 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 52 / 638859607918053627 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 129 / 638859607918053756 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 118 / 638859607918053874 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 167 / 638859607918054041 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 106 / 638859607918054147 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 138 / 638859607918054285 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 123 / 638859607918054408 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 120 / 638859607918054528 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 118 / 638859607918054646 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 132 / 638859607918054778 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 108 / 638859607918054886 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 188 / 638859607918055074 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 118 / 638859607918055192 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 131 / 638859607918055323 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 203 / 638859607918055526 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 57 / 638859607918055583 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 170 / 638859607918055753 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 151 / 638859607918055904 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 211 / 638859607918056115 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 224 / 638859607918056339 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 259 / 638859607918056598 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 867 / 638859607918057465 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 79 / 638859607918057544 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 128 / 638859607918057672 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 188 / 638859607918057860 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 118 / 638859607918057978 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 318 / 638859607918058296 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 165 / 638859607918058461 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 138 / 638859607918058599 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 207 / 638859607918058806 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 213 / 638859607918059019 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 212 / 638859607918059231 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 120 / 638859607918059351 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 207 / 638859607918059558 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 54 / 638859607918059612 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 119 / 638859607918059731 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 149 / 638859607918059880 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 106 / 638859607918059986 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 189 / 638859607918060175 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 141 / 638859607918060316 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 124 / 638859607918060440 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 118 / 638859607918060558 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 118 / 638859607918060676 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 171 / 638859607918060847 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 121 / 638859607918060968 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 752 / 638859607918061720 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 67 / 638859607918061787 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 120 / 638859607918061907 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 197 / 638859607918062104 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 48 / 638859607918062152 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 180 / 638859607918062332 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 64 / 638859607918062396 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 122 / 638859607918062518 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 126 / 638859607918062644 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 164 / 638859607918062808 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 153 / 638859607918062961 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 136 / 638859607918063097 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 120 / 638859607918063217 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 116 / 638859607918063333 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 68 / 638859607918063401 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 237 / 638859607918063638 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 211 / 638859607918063849 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 175 / 638859607918064024 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 116 / 638859607918064140 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 168 / 638859607918064308 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 114 / 638859607918064422 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 193 / 638859607918064615 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 51 / 638859607918064666 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 126 / 638859607918064792 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 112 / 638859607918064904 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 172 / 638859607918065076 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 120 / 638859607918065196 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 163 / 638859607918065359 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 130 / 638859607918065489 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 204 / 638859607918065693 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 203 / 638859607918065896 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 191 / 638859607918066087 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 31 / 638859607918066118 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 45 / 638859607918066163 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 831 / 638859607918066994 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 15020086 / 638859607933087080 / Renamed ("file1....1111111111111111111111111111111111111111111111b")) 323 / 638859607933087403 / Renamed ("file2.txt",...2222222222222222222222222222222222222222222222b")) 15028449 / 638859607948115852 / Changed ("file_1...11111111111111111111111111111111111111111111111c") 216 / 638859607948116068 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 693 / 638859607948116761 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 5718 / 638859607948122479 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 106 / 638859607948122585 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 29 / 638859607948122614 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 237 / 638859607948122851 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 38 / 638859607948122889 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 394 / 638859607948123283 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 196 / 638859607948123479 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 28 / 638859607948123507 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 201 / 638859607948123708 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 31 / 638859607948123739 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 165 / 638859607948123904 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 33 / 638859607948123937 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 242 / 638859607948124179 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 120 / 638859607948124299 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 138 / 638859607948124437 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 153 / 638859607948124590 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 40 / 638859607948124630 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 158 / 638859607948124788 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 138 / 638859607948124926 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 129 / 638859607948125055 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 120 / 638859607948125175 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 153 / 638859607948125328 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 29 / 638859607948125357 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 561 / 638859607948125918 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 38 / 638859607948125956 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 194 / 638859607948126150 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 171 / 638859607948126321 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 145 / 638859607948126466 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 136 / 638859607948126602 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 138 / 638859607948126740 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 148 / 638859607948126888 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 149 / 638859607948127037 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 126 / 638859607948127163 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 120 / 638859607948127283 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 395 / 638859607948127678 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 148 / 638859607948127826 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 148 / 638859607948127974 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 358 / 638859607948128332 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 55 / 638859607948128387 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 155 / 638859607948128542 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 128 / 638859607948128670 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 140 / 638859607948128810 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 140 / 638859607948128950 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 135 / 638859607948129085 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 102 / 638859607948129187 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 126 / 638859607948129313 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 147 / 638859607948129460 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 173 / 638859607948129633 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 29 / 638859607948129662 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 135 / 638859607948129797 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 17642 / 638859607948147439 / Changed ("file_2.tx...22222222222222222222222222222222222222222222222c") 123 / 638859607948147562 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 379 / 638859607948147941 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 200 / 638859607948148141 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 337 / 638859607948148478 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 279 / 638859607948148757 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 130 / 638859607948148887 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 223 / 638859607948149110 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 207 / 638859607948149317 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 32 / 638859607948149349 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 216 / 638859607948149565 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 143 / 638859607948149708 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 31 / 638859607948149739 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 198 / 638859607948149937 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 367 / 638859607948150304 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 46 / 638859607948150350 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 157 / 638859607948150507 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 34 / 638859607948150541 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 168 / 638859607948150709 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 232 / 638859607948150941 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 143 / 638859607948151084 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 106 / 638859607948151190 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 837 / 638859607948152027 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 198 / 638859607948152225 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 137 / 638859607948152362 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 155 / 638859607948152517 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 147 / 638859607948152664 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 182 / 638859607948152846 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 142 / 638859607948152988 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 152 / 638859607948153140 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 155 / 638859607948153295 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 131 / 638859607948153426 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 135 / 638859607948153561 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 153 / 638859607948153714 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 138 / 638859607948153852 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 146 / 638859607948153998 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 139 / 638859607948154137 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 134 / 638859607948154271 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 150 / 638859607948154421 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 151 / 638859607948154572 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 136 / 638859607948154708 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 45 / 638859607948154753 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 162 / 638859607948154915 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 196 / 638859607948155111 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 155 / 638859607948155266 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 142 / 638859607948155408 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 133 / 638859607948155541 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 144 / 638859607948155685 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 109 / 638859607948155794 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 144 / 638859607948155938 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 138 / 638859607948156076 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 147 / 638859607948156223 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 1399 / 638859607948157622 / Changed ("file_2.txt...22222222222222222222222222222222222222222222222c") 174 / 638859607948157796 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 178 / 638859607948157974 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 297 / 638859607948158271 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 147 / 638859607948158418 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 162 / 638859607948158580 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 137 / 638859607948158717 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 152 / 638859607948158869 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 138 / 638859607948159007 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 129 / 638859607948159136 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 158 / 638859607948159294 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 161 / 638859607948159455 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 140 / 638859607948159595 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 140 / 638859607948159735 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 133 / 638859607948159868 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 158 / 638859607948160026 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 148 / 638859607948160174 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 140 / 638859607948160314 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 171 / 638859607948160485 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 140 / 638859607948160625 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 154 / 638859607948160779 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 135 / 638859607948160914 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 174 / 638859607948161088 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 153 / 638859607948161241 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 151 / 638859607948161392 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 156 / 638859607948161548 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 175 / 638859607948161723 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 36 / 638859607948161759 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 245 / 638859607948162004 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 162 / 638859607948162166 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 34 / 638859607948162200 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 192 / 638859607948162392 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 157 / 638859607948162549 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 145 / 638859607948162694 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 35 / 638859607948162729 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 205 / 638859607948162934 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 151 / 638859607948163085 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 32 / 638859607948163117 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 221 / 638859607948163338 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 123 / 638859607948163461 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 165 / 638859607948163626 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 47 / 638859607948163673 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 205 / 638859607948163878 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 154 / 638859607948164032 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 32 / 638859607948164064 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 174 / 638859607948164238 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 19 / 638859607948164257 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 173 / 638859607948164430 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 29 / 638859607948164459 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 868 / 638859607948165327 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 64 / 638859607948165391 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 15022000 / 638859607963187391 / Deleted "file_1.txt" 2693 / 638859607963190084 / 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:14 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 ()