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 / 638871582587878566 / Created ("file1.txt", Some "a1") 12076 / 638871582587890642 / Changed ("file1.txt", Some "a1") 1924 / 638871582587892566 / Created ("file2.txt", Some "a2") 43 / 638871582587892609 / Changed ("file2.txt", Some "a2") 2488437 / 638871582590381046 / Changed ("file1.txt", Some "b1") 411 / 638871582590381457 / Changed ("file1.txt", Some "b1") 5761 / 638871582590387218 / Changed ("file2.txt", Some "b2") 2556141 / 638871582592943359 / Renamed ("file1.txt", ("file_1.txt", Some "b1")) 6421 / 638871582592949780 / Renamed ("file2.txt", ("file_2.txt", Some "b2")) 2517436 / 638871582595467216 / Changed ("file_1.txt", Some "c1") 531 / 638871582595467747 / Changed ("file_1.txt", Some "c1") 4499 / 638871582595472246 / Changed ("file_2.txt", Some "c2") 203 / 638871582595472449 / Changed ("file_2.txt", Some "c2") 2532066 / 638871582598004515 / Deleted "file_1.txt" 984 / 638871582598005499 / 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 / 638871582612441120 / Created ("file1.txt", ...11111111111111111111111111111111111111111111111a") 3121 / 638871582612444241 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111a") 282 / 638871582612444523 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 59 / 638871582612444582 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 51 / 638871582612444633 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 505 / 638871582612445138 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 410 / 638871582612445548 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 212 / 638871582612445760 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 190 / 638871582612445950 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 292 / 638871582612446242 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 333 / 638871582612446575 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 306 / 638871582612446881 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 201 / 638871582612447082 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 110 / 638871582612447192 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 50 / 638871582612447242 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 125 / 638871582612447367 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 467 / 638871582612447834 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 172 / 638871582612448006 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 144 / 638871582612448150 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 99 / 638871582612448249 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 67 / 638871582612448316 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 703 / 638871582612449019 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 113 / 638871582612449132 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 40 / 638871582612449172 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 330 / 638871582612449502 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 186 / 638871582612449688 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 45 / 638871582612449733 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 255 / 638871582612449988 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 183 / 638871582612450171 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 46 / 638871582612450217 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 68 / 638871582612450285 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 352 / 638871582612450637 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 50 / 638871582612450687 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 232 / 638871582612450919 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 163 / 638871582612451082 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 53 / 638871582612451135 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 241 / 638871582612451376 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 21926 / 638871582612473302 / Created ("file2.txt...22222222222222222222222222222222222222222222222a") 198 / 638871582612473500 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 54 / 638871582612473554 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 761 / 638871582612474315 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 97 / 638871582612474412 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 27 / 638871582612474439 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 166 / 638871582612474605 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 52 / 638871582612474657 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 62 / 638871582612474719 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 169 / 638871582612474888 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 46 / 638871582612474934 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 210 / 638871582612475144 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 51 / 638871582612475195 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 693 / 638871582612475888 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 78 / 638871582612475966 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 240 / 638871582612476206 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 348 / 638871582612476554 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 60 / 638871582612476614 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 272 / 638871582612476886 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 188 / 638871582612477074 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 45 / 638871582612477119 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 210 / 638871582612477329 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 52 / 638871582612477381 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 244 / 638871582612477625 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 46 / 638871582612477671 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 249 / 638871582612477920 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 173 / 638871582612478093 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 47 / 638871582612478140 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 206 / 638871582612478346 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 947 / 638871582612479293 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 85 / 638871582612479378 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 58 / 638871582612479436 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 206 / 638871582612479642 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 158 / 638871582612479800 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 155 / 638871582612479955 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 151 / 638871582612480106 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 153 / 638871582612480259 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 157 / 638871582612480416 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 171 / 638871582612480587 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 47 / 638871582612480634 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 188 / 638871582612480822 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 156 / 638871582612480978 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 185 / 638871582612481163 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 153 / 638871582612481316 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 125 / 638871582612481441 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 164 / 638871582612481605 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 252 / 638871582612481857 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 39 / 638871582612481896 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 118 / 638871582612482014 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 166 / 638871582612482180 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 45 / 638871582612482225 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 200 / 638871582612482425 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 56 / 638871582612482481 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 291 / 638871582612482772 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 160 / 638871582612482932 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 277 / 638871582612483209 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 59 / 638871582612483268 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 40 / 638871582612483308 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 235 / 638871582612483543 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 182 / 638871582612483725 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 53 / 638871582612483778 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 214 / 638871582612483992 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 755 / 638871582612484747 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 41 / 638871582612484788 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 40 / 638871582612484828 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 216 / 638871582612485044 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 210 / 638871582612485254 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 198 / 638871582612485452 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 170 / 638871582612485622 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 164 / 638871582612485786 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 154 / 638871582612485940 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 210 / 638871582612486150 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 183 / 638871582612486333 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 439 / 638871582612486772 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 226 / 638871582612486998 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 30 / 638871582612487028 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 57 / 638871582612487085 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 941 / 638871582612488026 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 76 / 638871582612488102 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 214 / 638871582612488316 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 53 / 638871582612488369 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 123 / 638871582612488492 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 109 / 638871582612488601 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 126 / 638871582612488727 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 46 / 638871582612488773 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 15037563 / 638871582627526336 / Changed ("file1....11111111111111111111111111111111111111111111111b") 604 / 638871582627526940 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 95 / 638871582627527035 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 2845 / 638871582627529880 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 127 / 638871582627530007 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 44 / 638871582627530051 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 218 / 638871582627530269 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 171 / 638871582627530440 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 174 / 638871582627530614 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 183 / 638871582627530797 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 153 / 638871582627530950 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 157 / 638871582627531107 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 184 / 638871582627531291 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 158 / 638871582627531449 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 150 / 638871582627531599 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 168 / 638871582627531767 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 75 / 638871582627531842 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 221 / 638871582627532063 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 226 / 638871582627532289 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 164 / 638871582627532453 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 159 / 638871582627532612 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 805 / 638871582627533417 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 78 / 638871582627533495 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 235 / 638871582627533730 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 91 / 638871582627533821 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 178 / 638871582627533999 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 154 / 638871582627534153 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 152 / 638871582627534305 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 153 / 638871582627534458 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 199 / 638871582627534657 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 175 / 638871582627534832 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 82 / 638871582627534914 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 293 / 638871582627535207 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 50 / 638871582627535257 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 1072 / 638871582627536329 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 328 / 638871582627536657 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 255 / 638871582627536912 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 53 / 638871582627536965 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 174 / 638871582627537139 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 65 / 638871582627537204 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 175 / 638871582627537379 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 165 / 638871582627537544 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 47 / 638871582627537591 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 203 / 638871582627537794 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 131 / 638871582627537925 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 162 / 638871582627538087 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 61 / 638871582627538148 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 213 / 638871582627538361 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 249 / 638871582627538610 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 50 / 638871582627538660 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 1043 / 638871582627539703 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 65 / 638871582627539768 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 41 / 638871582627539809 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 35 / 638871582627539844 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 313 / 638871582627540157 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 159 / 638871582627540316 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 295 / 638871582627540611 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 11651 / 638871582627552262 / Changed ("file1.txt...11111111111111111111111111111111111111111111111b") 11343 / 638871582627563605 / Changed ("file2.txt...22222222222222222222222222222222222222222222222b") 254 / 638871582627563859 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 533 / 638871582627564392 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 77 / 638871582627564469 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 323 / 638871582627564792 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 313 / 638871582627565105 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 50 / 638871582627565155 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 223 / 638871582627565378 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 47 / 638871582627565425 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 299 / 638871582627565724 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 250 / 638871582627565974 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 69 / 638871582627566043 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 543 / 638871582627566586 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 107 / 638871582627566693 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 38 / 638871582627566731 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 1980 / 638871582627568711 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222b") 110 / 638871582627568821 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 231 / 638871582627569052 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 255 / 638871582627569307 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 269 / 638871582627569576 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 46 / 638871582627569622 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 172 / 638871582627569794 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 46 / 638871582627569840 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 169 / 638871582627570009 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 141 / 638871582627570150 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 157 / 638871582627570307 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 169 / 638871582627570476 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 173 / 638871582627570649 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 164 / 638871582627570813 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 43 / 638871582627570856 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 268 / 638871582627571124 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 162 / 638871582627571286 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 181 / 638871582627571467 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 171 / 638871582627571638 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 159 / 638871582627571797 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 59 / 638871582627571856 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 189 / 638871582627572045 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 241 / 638871582627572286 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 225 / 638871582627572511 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 163 / 638871582627572674 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 203 / 638871582627572877 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 470 / 638871582627573347 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 193 / 638871582627573540 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 116 / 638871582627573656 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 148 / 638871582627573804 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 40 / 638871582627573844 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 849 / 638871582627574693 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 66 / 638871582627574759 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 188 / 638871582627574947 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 44 / 638871582627574991 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 166 / 638871582627575157 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 154 / 638871582627575311 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 154 / 638871582627575465 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 175 / 638871582627575640 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 42 / 638871582627575682 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 170 / 638871582627575852 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 42 / 638871582627575894 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 187 / 638871582627576081 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 128 / 638871582627576209 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 300 / 638871582627576509 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 353 / 638871582627576862 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 814 / 638871582627577676 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 59 / 638871582627577735 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 192 / 638871582627577927 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 150 / 638871582627578077 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 175 / 638871582627578252 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 43 / 638871582627578295 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 172 / 638871582627578467 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 185 / 638871582627578652 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 298 / 638871582627578950 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 287 / 638871582627579237 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 165 / 638871582627579402 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 155 / 638871582627579557 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 171 / 638871582627579728 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 142 / 638871582627579870 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 156 / 638871582627580026 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 148 / 638871582627580174 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 163 / 638871582627580337 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 39 / 638871582627580376 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 182 / 638871582627580558 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 399 / 638871582627580957 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 78 / 638871582627581035 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 210 / 638871582627581245 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 164 / 638871582627581409 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 207 / 638871582627581616 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 152 / 638871582627581768 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 36 / 638871582627581804 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 15035929 / 638871582642617733 / Renamed ("file1....1111111111111111111111111111111111111111111111b")) 452 / 638871582642618185 / Renamed ("file2.txt",...2222222222222222222222222222222222222222222222b")) 15035250 / 638871582657653435 / Changed ("file_1...11111111111111111111111111111111111111111111111c") 669 / 638871582657654104 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 2625 / 638871582657656729 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 288 / 638871582657657017 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 529 / 638871582657657546 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 422 / 638871582657657968 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 363 / 638871582657658331 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 266 / 638871582657658597 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 273 / 638871582657658870 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 352 / 638871582657659222 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 275 / 638871582657659497 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 504 / 638871582657660001 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 147 / 638871582657660148 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 1279 / 638871582657661427 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 117 / 638871582657661544 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 221 / 638871582657661765 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 334 / 638871582657662099 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 232 / 638871582657662331 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 229 / 638871582657662560 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 324 / 638871582657662884 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 320 / 638871582657663204 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 505 / 638871582657663709 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 66 / 638871582657663775 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 228 / 638871582657664003 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 54 / 638871582657664057 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 194 / 638871582657664251 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 342 / 638871582657664593 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 1158 / 638871582657665751 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 147 / 638871582657665898 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 102 / 638871582657666000 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 50 / 638871582657666050 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 41 / 638871582657666091 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 2262 / 638871582657668353 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 106 / 638871582657668459 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 169 / 638871582657668628 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 238 / 638871582657668866 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 244 / 638871582657669110 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 217 / 638871582657669327 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 201 / 638871582657669528 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 383 / 638871582657669911 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 63 / 638871582657669974 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 191 / 638871582657670165 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 348 / 638871582657670513 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 244 / 638871582657670757 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 246 / 638871582657671003 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 192 / 638871582657671195 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 201 / 638871582657671396 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 204 / 638871582657671600 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 190 / 638871582657671790 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 211 / 638871582657672001 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 197 / 638871582657672198 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 191 / 638871582657672389 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 215 / 638871582657672604 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 243 / 638871582657672847 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 268 / 638871582657673115 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 5257 / 638871582657678372 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 14951 / 638871582657693323 / Changed ("file_2.tx...22222222222222222222222222222222222222222222222c") 224 / 638871582657693547 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 49 / 638871582657693596 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 248 / 638871582657693844 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 33 / 638871582657693877 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 66 / 638871582657693943 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 328 / 638871582657694271 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 38 / 638871582657694309 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 57 / 638871582657694366 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 169 / 638871582657694535 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 49 / 638871582657694584 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 252 / 638871582657694836 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 211 / 638871582657695047 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 140 / 638871582657695187 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 109 / 638871582657695296 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 194 / 638871582657695490 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 56 / 638871582657695546 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 251 / 638871582657695797 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 53 / 638871582657695850 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 207 / 638871582657696057 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 220 / 638871582657696277 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 354 / 638871582657696631 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 251 / 638871582657696882 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 51 / 638871582657696933 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 50 / 638871582657696983 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 153 / 638871582657697136 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 48 / 638871582657697184 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 283 / 638871582657697467 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 116 / 638871582657697583 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 49 / 638871582657697632 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 753 / 638871582657698385 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 55 / 638871582657698440 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 48 / 638871582657698488 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 171 / 638871582657698659 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 1666 / 638871582657700325 / Changed ("file_2.txt...22222222222222222222222222222222222222222222222c") 1080 / 638871582657701405 / Changed ("file_2.txt...22222222222222222222222222222222222222222222222c") 947 / 638871582657702352 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 433 / 638871582657702785 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 85 / 638871582657702870 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 214 / 638871582657703084 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 155 / 638871582657703239 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 212 / 638871582657703451 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 382 / 638871582657703833 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 72 / 638871582657703905 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 221 / 638871582657704126 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 252 / 638871582657704378 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 614 / 638871582657704992 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 60 / 638871582657705052 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 46 / 638871582657705098 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 778 / 638871582657705876 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 86 / 638871582657705962 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 754 / 638871582657706716 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 69 / 638871582657706785 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 66 / 638871582657706851 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 45 / 638871582657706896 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 1227 / 638871582657708123 / Changed ("file_2.txt...22222222222222222222222222222222222222222222222c") 85 / 638871582657708208 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 45 / 638871582657708253 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 1303 / 638871582657709556 / Changed ("file_2.txt...22222222222222222222222222222222222222222222222c") 76 / 638871582657709632 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 67106 / 638871582657776738 / Changed ("file_2.tx...22222222222222222222222222222222222222222222222c") 14969469 / 638871582672746207 / Deleted "file_1.txt" 5411 / 638871582672751618 / 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 ()