/// <summary>
 /// Create observer for one file.
 /// </summary>
 /// <param name="filesystem"></param>
 /// <param name="patternInfo"></param>
 /// <param name="observer"></param>
 /// <param name="state"></param>
 /// <param name="eventDispatcher"></param>
 public PatternObserver(IFileSystem filesystem, GlobPatternInfo patternInfo, IObserver <IEvent> observer, object state, IEventDispatcher eventDispatcher = default)
     : base(filesystem, patternInfo.Pattern, observer, state, eventDispatcher)
 {
     this.changeToken      = FileProvider.Watch(patternInfo.Pattern);
     this.previousSnapshot = ReadSnapshot();
     this.watcher          = changeToken.RegisterChangeCallback(OnEvent, this);
 }
Esempio n. 2
0
        /// <summary>
        /// Adds glob pattern.
        ///   "**" Matched to for any string of characters including directory separator.
        ///   "*" Matched for any string of characters within the same directory.
        ///   "?" Matched for one character excluding directory separator.
        /// </summary>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public FileScanner AddGlobPattern(string pattern)
        {
            if (pattern == null)
            {
                return(this);
            }

            GlobPatternInfo info = new GlobPatternInfo(pattern);

            // Add to pattern set
            PatternSet set;

            if (!patterns.TryGetValue(info.Stem, out set))
            {
                patterns[info.Stem] = set = new PatternSet();
            }
            set.AddGlobPattern(info, info.SuffixDepth);

            return(this);
        }
        /// <summary>
        /// Attach an <paramref name="observer"/> on to a single file or directory.
        /// Observing a directory will observe the whole subtree.
        ///
        /// WARNING: The Observe implementation browses the subtree of the watched directory path in order to create delta of changes.
        /// </summary>
        /// <param name="filter">path to file or directory. The directory separator is "/". The root is without preceding slash "", e.g. "dir/dir2"</param>
        /// <param name="observer"></param>
        /// <param name="state">(optional) </param>
        /// <param name="eventDispatcher">(optional) event dispatcher</param>
        /// <param name="option">(optional) operation specific option; capability constraint, a session, security token or credential. Used for authenticating, authorizing or restricting the operation.</param>
        /// <returns>dispose handle</returns>
        /// <exception cref="IOException">On unexpected IO error</exception>
        /// <exception cref="SecurityException">If caller did not have permission</exception>
        /// <exception cref="ArgumentNullException"><paramref name="filter"/> is null</exception>
        /// <exception cref="ArgumentException"><paramref name="filter"/> contains only white space, or contains one or more invalid characters</exception>
        /// <exception cref="NotSupportedException">The <see cref="IFileSystem"/> doesn't support observe</exception>
        /// <exception cref="UnauthorizedAccessException">The access requested is not permitted by the operating system for the specified path.</exception>
        /// <exception cref="PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.</exception>
        /// <exception cref="InvalidOperationException">If <paramref name="filter"/> refers to a non-file device, such as "con:", "com1:", "lpt1:", etc.</exception>
        /// <exception cref="ObjectDisposedException"/>
        public virtual IFileSystemObserver Observe(string filter, IObserver <IEvent> observer, object state = null, IEventDispatcher eventDispatcher = default, IOption option = null)
        {
            // Assert observe is enabled.
            if (!CanObserve || !option.CanObserve(true))
            {
                throw new NotSupportedException(nameof(Observe));
            }
            // Assert not diposed
            IFileProvider fp = fileProvider;

            if (fp == null)
            {
                return(new DummyObserver(this, filter, observer, state, eventDispatcher));
            }
            // Parse filter
            GlobPatternInfo patternInfo = new GlobPatternInfo(filter);

            // Monitor single file (or dir, we don't know "dir")
            if (patternInfo.SuffixDepth == 0)
            {
                // Create observer that watches one file
                FileObserver handle = new FileObserver(this, filter, observer, state, eventDispatcher, option.OptionIntersection(this.options));
                // Send handle
                observer.OnNext(new StartEvent(handle, DateTimeOffset.UtcNow));
                // Return handle
                return(handle);
            }
            else
            // Has wildcards, e.g. "**/file.txt"
            {
                // Create handle
                PatternObserver handle = new PatternObserver(this, patternInfo, observer, state, eventDispatcher);
                // Send handle
                observer.OnNext(new StartEvent(handle, DateTimeOffset.UtcNow));
                // Return handle
                return(handle);
            }
        }
 public void GlobPatternInfo()
 {
     {
         GlobPatternInfo gpi = new GlobPatternInfo("");
         Assert.AreEqual("", gpi.Stem);
         Assert.AreEqual("", gpi.Suffix);
         Assert.AreEqual(0, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/dir/file.txt");
         Assert.AreEqual("dir/dir/file.txt", gpi.Stem);
         Assert.AreEqual("", gpi.Suffix);
         Assert.AreEqual(0, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("*.txt");
         Assert.AreEqual("", gpi.Stem);
         Assert.AreEqual("*.txt", gpi.Suffix);
         Assert.AreEqual(1, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("**.txt");
         Assert.AreEqual("", gpi.Stem);
         Assert.AreEqual("**.txt", gpi.Suffix);
         Assert.AreEqual(int.MaxValue, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("/*.txt");
         Assert.AreEqual("/", gpi.Stem);
         Assert.AreEqual("*.txt", gpi.Suffix);
         Assert.AreEqual(1, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("*/*.txt");
         Assert.AreEqual("", gpi.Stem);
         Assert.AreEqual("*/*.txt", gpi.Suffix);
         Assert.AreEqual(2, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("/**.txt");
         Assert.AreEqual("/", gpi.Stem);
         Assert.AreEqual("**.txt", gpi.Suffix);
         Assert.AreEqual(int.MaxValue, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/dir/*/*.txt");
         Assert.AreEqual("dir/dir/", gpi.Stem);
         Assert.AreEqual("*/*.txt", gpi.Suffix);
         Assert.AreEqual(2, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/dir?/*/*.txt");
         Assert.AreEqual("dir/", gpi.Stem);
         Assert.AreEqual("dir?/*/*.txt", gpi.Suffix);
         Assert.AreEqual(3, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/dir/dir/*/*.txt");
         Assert.AreEqual("dir/dir/dir/", gpi.Stem);
         Assert.AreEqual("*/*.txt", gpi.Suffix);
         Assert.AreEqual(2, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/dir/dir?/*/*.txt");
         Assert.AreEqual("dir/dir/", gpi.Stem);
         Assert.AreEqual("dir?/*/*.txt", gpi.Suffix);
         Assert.AreEqual(3, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/dir/dir?/*/**.txt");
         Assert.AreEqual("dir/dir/", gpi.Stem);
         Assert.AreEqual("dir?/*/**.txt", gpi.Suffix);
         Assert.AreEqual(int.MaxValue, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/*/dir/dir/dir/file.txt");
         Assert.AreEqual("dir/", gpi.Stem);
         Assert.AreEqual("*/dir/dir/dir/file.txt", gpi.Suffix);
         Assert.AreEqual(5, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/**");
         Assert.AreEqual("dir/", gpi.Stem);
         Assert.AreEqual("**", gpi.Suffix);
         Assert.AreEqual(int.MaxValue, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/*");
         Assert.AreEqual("dir/", gpi.Stem);
         Assert.AreEqual("*", gpi.Suffix);
         Assert.AreEqual(1, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/");
         Assert.AreEqual("dir/", gpi.Stem);
         Assert.AreEqual("", gpi.Suffix);
         Assert.AreEqual(0, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir");
         Assert.AreEqual("dir", gpi.Stem);
         Assert.AreEqual("", gpi.Suffix);
         Assert.AreEqual(0, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/file.txt");
         Assert.AreEqual("dir/file.txt", gpi.Stem);
         Assert.AreEqual("", gpi.Suffix);
         Assert.AreEqual(0, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/file*.txt");
         Assert.AreEqual("dir/", gpi.Stem);
         Assert.AreEqual("file*.txt", gpi.Suffix);
         Assert.AreEqual(1, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir/file**.txt");
         Assert.AreEqual("dir/", gpi.Stem);
         Assert.AreEqual("file**.txt", gpi.Suffix);
         Assert.AreEqual(int.MaxValue, gpi.SuffixDepth);
     }
     {
         GlobPatternInfo gpi = new GlobPatternInfo("dir*/file.txt");
         Assert.AreEqual("", gpi.Stem);
         Assert.AreEqual("dir*/file.txt", gpi.Suffix);
         Assert.AreEqual(2, gpi.SuffixDepth);
     }
 }