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 / 638788541109309343 / Created ("file1.txt", Some "a1") 13092 / 638788541109322435 / Changed ("file1.txt", Some "a1") 1338 / 638788541109323773 / Created ("file2.txt", Some "a2") 41 / 638788541109323814 / Changed ("file2.txt", Some "a2") 2491917 / 638788541111815731 / Changed ("file1.txt", Some "b1") 376 / 638788541111816107 / Changed ("file1.txt", Some "b1") 4932 / 638788541111821039 / Changed ("file2.txt", Some "b2") 220 / 638788541111821259 / Changed ("file2.txt", Some "b2") 2559165 / 638788541114380424 / Renamed ("file1.txt", ("file_1.txt", Some "b1")) 7233 / 638788541114387657 / Renamed ("file2.txt", ("file_2.txt", Some "b2")) 2519978 / 638788541116907635 / Changed ("file_1.txt", Some "c1") 399 / 638788541116908034 / Changed ("file_1.txt", Some "c1") 5343 / 638788541116913377 / Changed ("file_2.txt", Some "c2") 171 / 638788541116913548 / Changed ("file_2.txt", Some "c2") 2531608 / 638788541119445156 / Deleted "file_1.txt" 1289 / 638788541119446445 / 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 / 638788541134396170 / Created ("file1.txt", ...11111111111111111111111111111111111111111111111a") 2882 / 638788541134399052 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111a") 231 / 638788541134399283 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 341 / 638788541134399624 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 64 / 638788541134399688 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 181 / 638788541134399869 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 179 / 638788541134400048 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 201 / 638788541134400249 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 39 / 638788541134400288 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 189 / 638788541134400477 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 50 / 638788541134400527 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 232 / 638788541134400759 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 78 / 638788541134400837 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 232 / 638788541134401069 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 183 / 638788541134401252 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 76 / 638788541134401328 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 173 / 638788541134401501 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 489 / 638788541134401990 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 84 / 638788541134402074 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 54 / 638788541134402128 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 363 / 638788541134402491 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 168 / 638788541134402659 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 160 / 638788541134402819 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 139 / 638788541134402958 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 161 / 638788541134403119 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 38 / 638788541134403157 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 198 / 638788541134403355 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 487 / 638788541134403842 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 55 / 638788541134403897 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111a") 278 / 638788541134404175 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 180 / 638788541134404355 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 265 / 638788541134404620 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111a") 6126 / 638788541134410746 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111a") 16202 / 638788541134426948 / Created ("file2.txt...22222222222222222222222222222222222222222222222a") 130 / 638788541134427078 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 56 / 638788541134427134 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 292 / 638788541134427426 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 85 / 638788541134427511 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 98 / 638788541134427609 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 45 / 638788541134427654 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 289 / 638788541134427943 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 201 / 638788541134428144 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 51 / 638788541134428195 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 253 / 638788541134428448 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 48 / 638788541134428496 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 539 / 638788541134429035 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 72 / 638788541134429107 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 44 / 638788541134429151 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 215 / 638788541134429366 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 167 / 638788541134429533 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 135 / 638788541134429668 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 217 / 638788541134429885 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 174 / 638788541134430059 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 53 / 638788541134430112 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 1859 / 638788541134431971 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 88 / 638788541134432059 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 42 / 638788541134432101 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 215 / 638788541134432316 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 164 / 638788541134432480 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 162 / 638788541134432642 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 178 / 638788541134432820 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 155 / 638788541134432975 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 272 / 638788541134433247 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 273 / 638788541134433520 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 204 / 638788541134433724 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 161 / 638788541134433885 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 150 / 638788541134434035 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 135 / 638788541134434170 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 148 / 638788541134434318 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 169 / 638788541134434487 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 135 / 638788541134434622 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 302 / 638788541134434924 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 168 / 638788541134435092 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 366 / 638788541134435458 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 268 / 638788541134435726 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 49 / 638788541134435775 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 44 / 638788541134435819 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 298 / 638788541134436117 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 52 / 638788541134436169 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 234 / 638788541134436403 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 183 / 638788541134436586 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 49 / 638788541134436635 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 206 / 638788541134436841 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 191 / 638788541134437032 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 50 / 638788541134437082 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 274 / 638788541134437356 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 48 / 638788541134437404 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 181 / 638788541134437585 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 46 / 638788541134437631 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 1457 / 638788541134439088 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222a") 85 / 638788541134439173 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 215 / 638788541134439388 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 182 / 638788541134439570 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 158 / 638788541134439728 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 161 / 638788541134439889 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 154 / 638788541134440043 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 217 / 638788541134440260 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 161 / 638788541134440421 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 172 / 638788541134440593 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 173 / 638788541134440766 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 187 / 638788541134440953 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 953 / 638788541134441906 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 86 / 638788541134441992 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 188 / 638788541134442180 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 162 / 638788541134442342 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 179 / 638788541134442521 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222a") 51 / 638788541134442572 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222a") 15048379 / 638788541149490951 / Changed ("file1....11111111111111111111111111111111111111111111111b") 323 / 638788541149491274 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 830 / 638788541149492104 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 4059 / 638788541149496163 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 114 / 638788541149496277 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 193 / 638788541149496470 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 165 / 638788541149496635 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 232 / 638788541149496867 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 79 / 638788541149496946 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 183 / 638788541149497129 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 161 / 638788541149497290 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 270 / 638788541149497560 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 63 / 638788541149497623 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 182 / 638788541149497805 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 53 / 638788541149497858 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 227 / 638788541149498085 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 73 / 638788541149498158 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 195 / 638788541149498353 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 179 / 638788541149498532 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 52 / 638788541149498584 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 247 / 638788541149498831 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 58 / 638788541149498889 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 197 / 638788541149499086 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 79 / 638788541149499165 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 205 / 638788541149499370 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 65 / 638788541149499435 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 248 / 638788541149499683 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 60 / 638788541149499743 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 208 / 638788541149499951 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 135 / 638788541149500086 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 52 / 638788541149500138 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 195 / 638788541149500333 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 55 / 638788541149500388 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 292 / 638788541149500680 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 59 / 638788541149500739 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 176 / 638788541149500915 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 74 / 638788541149500989 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 228 / 638788541149501217 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 58 / 638788541149501275 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 222 / 638788541149501497 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 57 / 638788541149501554 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 281 / 638788541149501835 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 59 / 638788541149501894 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 160 / 638788541149502054 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 44 / 638788541149502098 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 256 / 638788541149502354 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 307 / 638788541149502661 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 117 / 638788541149502778 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 41 / 638788541149502819 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 271 / 638788541149503090 / Changed ("file1.txt",...11111111111111111111111111111111111111111111111b") 41 / 638788541149503131 / Changed ("file1.txt", ...11111111111111111111111111111111111111111111111b") 7213 / 638788541149510344 / Changed ("file1.txt"...11111111111111111111111111111111111111111111111b") 17522 / 638788541149527866 / Changed ("file2.txt...22222222222222222222222222222222222222222222222b") 173 / 638788541149528039 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 333 / 638788541149528372 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 217 / 638788541149528589 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 43 / 638788541149528632 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 293 / 638788541149528925 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 188 / 638788541149529113 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 155 / 638788541149529268 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 191 / 638788541149529459 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 45 / 638788541149529504 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 831 / 638788541149530335 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 108 / 638788541149530443 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 44 / 638788541149530487 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 271 / 638788541149530758 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 106 / 638788541149530864 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 183 / 638788541149531047 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 50 / 638788541149531097 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 158 / 638788541149531255 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 257 / 638788541149531512 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 216 / 638788541149531728 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 115 / 638788541149531843 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 39 / 638788541149531882 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 362 / 638788541149532244 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 64 / 638788541149532308 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 222 / 638788541149532530 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 170 / 638788541149532700 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 47 / 638788541149532747 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 194 / 638788541149532941 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 40 / 638788541149532981 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 6436 / 638788541149539417 / Changed ("file2.txt"...22222222222222222222222222222222222222222222222b") 111 / 638788541149539528 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 230 / 638788541149539758 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 321 / 638788541149540079 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 213 / 638788541149540292 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 228 / 638788541149540520 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 193 / 638788541149540713 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 189 / 638788541149540902 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 214 / 638788541149541116 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 252 / 638788541149541368 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 247 / 638788541149541615 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 416 / 638788541149542031 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 64 / 638788541149542095 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 215 / 638788541149542310 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 168 / 638788541149542478 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 167 / 638788541149542645 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 166 / 638788541149542811 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 268 / 638788541149543079 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 159 / 638788541149543238 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 162 / 638788541149543400 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 40 / 638788541149543440 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 173 / 638788541149543613 / Changed ("file2.txt",...22222222222222222222222222222222222222222222222b") 42 / 638788541149543655 / Changed ("file2.txt", ...22222222222222222222222222222222222222222222222b") 15024874 / 638788541164568529 / Renamed ("file1....1111111111111111111111111111111111111111111111b")) 449 / 638788541164568978 / Renamed ("file2.txt",...2222222222222222222222222222222222222222222222b")) 15033664 / 638788541179602642 / Changed ("file_1...11111111111111111111111111111111111111111111111c") 408 / 638788541179603050 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 3283 / 638788541179606333 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 113 / 638788541179606446 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 59 / 638788541179606505 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 52 / 638788541179606557 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 64 / 638788541179606621 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 314 / 638788541179606935 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 357 / 638788541179607292 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 227 / 638788541179607519 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 238 / 638788541179607757 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 265 / 638788541179608022 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 262 / 638788541179608284 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 230 / 638788541179608514 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 257 / 638788541179608771 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 330 / 638788541179609101 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 84 / 638788541179609185 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 892 / 638788541179610077 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 111 / 638788541179610188 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 40 / 638788541179610228 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 46 / 638788541179610274 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 227 / 638788541179610501 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 65 / 638788541179610566 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 732 / 638788541179611298 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 92 / 638788541179611390 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 110 / 638788541179611500 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 582 / 638788541179612082 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 534 / 638788541179612616 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 201 / 638788541179612817 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 98 / 638788541179612915 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 75 / 638788541179612990 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 41 / 638788541179613031 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 691 / 638788541179613722 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 43 / 638788541179613765 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 210 / 638788541179613975 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 190 / 638788541179614165 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 38 / 638788541179614203 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 45 / 638788541179614248 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 314 / 638788541179614562 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 57 / 638788541179614619 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 952 / 638788541179615571 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 92 / 638788541179615663 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 42 / 638788541179615705 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 212 / 638788541179615917 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 77 / 638788541179615994 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 54 / 638788541179616048 / Changed ("file_1.txt",...11111111111111111111111111111111111111111111111c") 200 / 638788541179616248 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 163 / 638788541179616411 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 175 / 638788541179616586 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 173 / 638788541179616759 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 190 / 638788541179616949 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 270 / 638788541179617219 / Changed ("file_1.txt"...11111111111111111111111111111111111111111111111c") 8581 / 638788541179625800 / Changed ("file_1.txt...11111111111111111111111111111111111111111111111c") 7227 / 638788541179633027 / Changed ("file_2.txt...22222222222222222222222222222222222222222222222c") 158 / 638788541179633185 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 364 / 638788541179633549 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 281 / 638788541179633830 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 83 / 638788541179633913 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 198 / 638788541179634111 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 236 / 638788541179634347 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 238 / 638788541179634585 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 73 / 638788541179634658 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 341 / 638788541179634999 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 68 / 638788541179635067 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 47 / 638788541179635114 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 966 / 638788541179636080 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 63 / 638788541179636143 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 43 / 638788541179636186 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 202 / 638788541179636388 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 159 / 638788541179636547 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 160 / 638788541179636707 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 161 / 638788541179636868 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 50 / 638788541179636918 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 174 / 638788541179637092 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 145 / 638788541179637237 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 162 / 638788541179637399 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 171 / 638788541179637570 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 47 / 638788541179637617 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 206 / 638788541179637823 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 55 / 638788541179637878 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 194 / 638788541179638072 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 165 / 638788541179638237 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 745 / 638788541179638982 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 98 / 638788541179639080 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 26 / 638788541179639106 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 197 / 638788541179639303 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 51 / 638788541179639354 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 170 / 638788541179639524 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 150 / 638788541179639674 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 203 / 638788541179639877 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 48 / 638788541179639925 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 176 / 638788541179640101 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 187 / 638788541179640288 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 118 / 638788541179640406 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 188 / 638788541179640594 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 44 / 638788541179640638 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 199 / 638788541179640837 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 49 / 638788541179640886 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 54 / 638788541179640940 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 294 / 638788541179641234 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 48 / 638788541179641282 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 222 / 638788541179641504 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 193 / 638788541179641697 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 47 / 638788541179641744 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 224 / 638788541179641968 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 172 / 638788541179642140 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 43 / 638788541179642183 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 226 / 638788541179642409 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 260 / 638788541179642669 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 52 / 638788541179642721 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 194 / 638788541179642915 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 194 / 638788541179643109 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 171 / 638788541179643280 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 60 / 638788541179643340 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 232 / 638788541179643572 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 173 / 638788541179643745 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 41 / 638788541179643786 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 217 / 638788541179644003 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 178 / 638788541179644181 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 46 / 638788541179644227 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 229 / 638788541179644456 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 196 / 638788541179644652 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 39 / 638788541179644691 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 202 / 638788541179644893 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 192 / 638788541179645085 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 49 / 638788541179645134 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 357 / 638788541179645491 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 64 / 638788541179645555 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 295 / 638788541179645850 / Changed ("file_2.txt"...22222222222222222222222222222222222222222222222c") 42 / 638788541179645892 / Changed ("file_2.txt",...22222222222222222222222222222222222222222222222c") 8515 / 638788541179654407 / Changed ("file_2.txt...22222222222222222222222222222222222222222222222c") 15015814 / 638788541194670221 / Deleted "file_1.txt" 1265 / 638788541194671486 / 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:15 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 ()