Beispiel #1
0
        public ISetChanges <AbsolutePath> ToLiveLinq(bool includeFileContentChanges, PathObservationMethod observationMethod = PathObservationMethod.Default)
        {
            if (observationMethod == PathObservationMethod.Default)
            {
                observationMethod = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? PathObservationMethod.FileSystemWatcher : PathObservationMethod.FsWatchDefault;
            }

            if (observationMethod == PathObservationMethod.FileSystemWatcher)
            {
                return(ToLiveLinqWithFileSystemWatcher(_path, includeFileContentChanges)
                       .ToDictionaryLiveLinq(x => x, x => x.GetPathType()).KeysAsSet());
            }

            return(ToLiveLinqWithFsWatch(_path, includeFileContentChanges, observationMethod));
        }
Beispiel #2
0
        private ISetChanges <AbsolutePath> ToLiveLinqWithFsWatch(AbsolutePath root, bool includeFileContentChanges, PathObservationMethod observationMethod)
        {
            // TODO - add support for FSWatch events on Windows and Linux as well. Although I think I already support all the ones on Linux
            // and the FileSystemWatcher class on Windows should be sufficient, it would be nice to have this support for
            // completeness' sake.

            ReactiveProcess proc;

            var recursiveArg = IncludeSubdirectories ? "--recursive" : string.Empty;

            if (observationMethod == PathObservationMethod.FsWatchDefault)
            {
                proc = IoService.ReactiveProcessFactory.Start("fswatch", $"-0 {recursiveArg} \"{root}\"");
            }
            else if (observationMethod == PathObservationMethod.FsWatchPollMonitor)
            {
                proc = IoService.ReactiveProcessFactory.Start("fswatch", $"--monitor=poll_monitor -0 {recursiveArg} \"{root}\"");
            }
            else if (observationMethod == PathObservationMethod.FsWatchFsEventsMonitor)
            {
                proc = IoService.ReactiveProcessFactory.Start("fswatch", $"--monitor=fsevents_monitor -0 {recursiveArg} \"{root}\"");
            }
            else if (observationMethod == PathObservationMethod.FsWatchKQueueMonitor)
            {
                proc = IoService.ReactiveProcessFactory.Start("fswatch", $"--monitor=kqueue_monitor -0 {recursiveArg} \"{root}\"");
            }
            else
            {
                throw new ArgumentException($"Unknown path observation method: {observationMethod}");
            }

            var initialState = this
                               .ToImmutableDictionary(x => x, x => x.GetPathType());

            var resultObservable = proc.StandardOutput
                                   .Scan(new { StringBuilder = new StringBuilder(), BuiltString = (string)null },
                                         (state, ch) =>
            {
                if (ch == 0)
                {
                    return(new
                    {
                        StringBuilder = new StringBuilder(), BuiltString = state.StringBuilder.ToString()
                    });
                }

                state.StringBuilder.Append(ch);
                return(new { state.StringBuilder, BuiltString = (string)null });
            }).Where(state => state.BuiltString != null).Select(state => state.BuiltString)
                                   .Scan(new { State = initialState, LastEvents = (IDictionaryChangeStrict <AbsolutePath, PathType>[])null },
                                         (state, itemString) =>
            {
                var item = IoService.TryParseAbsolutePath(itemString).Value;
                if (state.State.ContainsKey(item))
                {
                    if (File.Exists(itemString) || Directory.Exists(itemString))
                    {
                        if (includeFileContentChanges)
                        {
                            return(new
                            {
                                state.State,
                                LastEvents = new []
                                {
                                    LiveLinq.Utility.DictionaryRemove(MoreCollections.Utility.KeyValuePair(item, state.State[item])),
                                    LiveLinq.Utility.DictionaryAdd(MoreCollections.Utility.KeyValuePair(item, item.GetPathType()))
                                }
                            });
                        }
                        else
                        {
                            return(new
                            {
                                state.State,
                                LastEvents = new IDictionaryChangeStrict <AbsolutePath, PathType> [0]
                            });
                        }
                    }
                    else
                    {
                        // TODO - fix bug where when a directory is deleted, subdirectories and subfolders are not removed from the state.

                        return(new
                        {
                            State = state.State.Remove(item),
                            LastEvents = new IDictionaryChangeStrict <AbsolutePath, PathType>[]
                            {
                                LiveLinq.Utility.DictionaryRemove(MoreCollections.Utility.KeyValuePair(item, state.State[item])),
                            }
                        });
                    }
                }
                else
                {
                    return(new
                    {
                        State = state.State.Add(item, item.GetPathType()),
                        LastEvents = new IDictionaryChangeStrict <AbsolutePath, PathType>[]
                        {
                            LiveLinq.Utility.DictionaryAdd(MoreCollections.Utility.KeyValuePair(item, item.GetPathType())),
                        }
                    });
                }
            })
                                   .SelectMany(state => state.LastEvents);

            resultObservable = Observable.Return(LiveLinq.Utility.DictionaryAdd(initialState))
                               .Concat(resultObservable);

            var result = resultObservable.ToLiveLinq().KeysAsSet();

            if (!string.IsNullOrWhiteSpace(_pattern))
            {
                var regex = IoService.FileNamePatternToRegex(_pattern);
                result = result.Where(path => regex.IsMatch(path.Name));
            }

            return(result);
        }