From 15d975684d146f207a973f3c4dab65848803a845 Mon Sep 17 00:00:00 2001 From: Jonathan Chambers Date: Wed, 21 Jul 2021 12:55:51 -0400 Subject: [PATCH 1/3] Add default FileSystemWatcher to unityaot profile (case 1344045). --- .../IO/FileSystemWatcher.UnknownUnix.cs | 31 + .../src/System/IO/FileSystemWatcher.cs | 803 ++++++++++++++++++ .../linux_unityaot_System.dll.exclude.sources | 3 + .../System/linux_unityaot_System.dll.sources | 8 +- .../macos_unityaot_System.dll.exclude.sources | 4 + .../System/macos_unityaot_System.dll.sources | 7 +- .../win32_unityaot_System.dll.exclude.sources | 3 + .../System/win32_unityaot_System.dll.sources | 8 +- 8 files changed, 864 insertions(+), 3 deletions(-) create mode 100644 external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs create mode 100644 external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs diff --git a/external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs b/external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs new file mode 100644 index 000000000000..d017c759e3e8 --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs @@ -0,0 +1,31 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#if MONO && (!MOBILE || UNITY_AOT) + +using System; +using System.IO; +namespace System.IO.CoreFX +#else + +namespace System.IO +#endif +{ + public partial class FileSystemWatcher + { + /// Called when FileSystemWatcher is finalized. + private void FinalizeDispose() + { + } + + private void StartRaisingEvents() + { + throw new PlatformNotSupportedException(); + } + + private void StopRaisingEvents() + { + throw new PlatformNotSupportedException(); + } + } +} diff --git a/external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs b/external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs new file mode 100644 index 000000000000..ee11a05859be --- /dev/null +++ b/external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs @@ -0,0 +1,803 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO.Enumeration; +using System.Threading; +using System.Threading.Tasks; + +#if MONO && (!MOBILE || MOBILE_DESKTOP_HOST || UNITY_AOT) + +using System; +using System.IO; +namespace System.IO.CoreFX +#else + +namespace System.IO +#endif +{ + /// + /// Listens to the system directory change notifications and + /// raises events when a directory or file within a directory changes. + /// + public partial class FileSystemWatcher : Component, ISupportInitialize + { + // Filters collection + private readonly NormalizedFilterCollection _filters = new NormalizedFilterCollection(); + + // Directory being monitored + private string _directory; + + // The watch filter for the API call. + private const NotifyFilters c_defaultNotifyFilters = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; + private NotifyFilters _notifyFilters = c_defaultNotifyFilters; + + // Flag to watch subtree of this directory + private bool _includeSubdirectories = false; + + // Flag to note whether we are attached to the thread pool and responding to changes + private bool _enabled = false; + + // Are we in init? + private bool _initializing = false; + + // Buffer size + private uint _internalBufferSize = 8192; + + // Used for synchronization + private bool _disposed; + + // Event handlers + private FileSystemEventHandler _onChangedHandler = null; + private FileSystemEventHandler _onCreatedHandler = null; + private FileSystemEventHandler _onDeletedHandler = null; + private RenamedEventHandler _onRenamedHandler = null; + private ErrorEventHandler _onErrorHandler = null; + + // To validate the input for "path" + private static readonly char[] s_wildcards = new char[] { '?', '*' }; + + private const int c_notifyFiltersValidMask = (int)(NotifyFilters.Attributes | + NotifyFilters.CreationTime | + NotifyFilters.DirectoryName | + NotifyFilters.FileName | + NotifyFilters.LastAccess | + NotifyFilters.LastWrite | + NotifyFilters.Security | + NotifyFilters.Size); + +#if DEBUG + static FileSystemWatcher() + { + int s_notifyFiltersValidMask = 0; + foreach (int enumValue in Enum.GetValues(typeof(NotifyFilters))) + s_notifyFiltersValidMask |= enumValue; + Debug.Assert(c_notifyFiltersValidMask == s_notifyFiltersValidMask, "The NotifyFilters enum has changed. The c_notifyFiltersValidMask must be updated to reflect the values of the NotifyFilters enum."); + } +#endif + + /// + /// Initializes a new instance of the class. + /// + public FileSystemWatcher() + { + _directory = string.Empty; + } + + /// + /// Initializes a new instance of the class, + /// given the specified directory to monitor. + /// + public FileSystemWatcher(string path) + { + CheckPathValidity(path); + _directory = path; + } + + /// + /// Initializes a new instance of the class, + /// given the specified directory and type of files to monitor. + /// + public FileSystemWatcher(string path, string filter) + { + CheckPathValidity(path); + _directory = path; + Filter = filter ?? throw new ArgumentNullException(nameof(filter)); + } + + /// + /// Gets or sets the type of changes to watch for. + /// + public NotifyFilters NotifyFilter + { + get + { + return _notifyFilters; + } + set + { + if (((int)value & ~c_notifyFiltersValidMask) != 0) + throw new ArgumentException(SR.Format(SR.InvalidEnumArgument, nameof(value), (int)value, nameof(NotifyFilters))); + + if (_notifyFilters != value) + { + _notifyFilters = value; + + Restart(); + } + } + } + + public Collection Filters => _filters; + + /// + /// Gets or sets a value indicating whether the component is enabled. + /// + public bool EnableRaisingEvents + { + get + { + return _enabled; + } + set + { + if (_enabled == value) + { + return; + } + + if (IsSuspended()) + { + _enabled = value; // Alert the Component to start watching for events when EndInit is called. + } + else + { + if (value) + { + StartRaisingEventsIfNotDisposed(); // will set _enabled to true once successfully started + } + else + { + StopRaisingEvents(); // will set _enabled to false + } + } + } + } + + /// + /// Gets or sets the filter string, used to determine what files are monitored in a directory. + /// + public string Filter + { + get + { + return Filters.Count == 0 ? "*" : Filters[0]; + } + set + { + Filters.Clear(); + Filters.Add(value); + } + } + + /// + /// Gets or sets a value indicating whether subdirectories within the specified path should be monitored. + /// + public bool IncludeSubdirectories + { + get + { + return _includeSubdirectories; + } + set + { + if (_includeSubdirectories != value) + { + _includeSubdirectories = value; + + Restart(); + } + } + } + + /// + /// Gets or sets the size of the internal buffer. + /// + public int InternalBufferSize + { + get + { + return (int)_internalBufferSize; + } + set + { + if (_internalBufferSize != value) + { + if (value < 4096) + { + _internalBufferSize = 4096; + } + else + { + _internalBufferSize = (uint)value; + } + + Restart(); + } + } + } + + /// Allocates a buffer of the requested internal buffer size. + /// The allocated buffer. + private byte[] AllocateBuffer() + { + try + { + return new byte[_internalBufferSize]; + } + catch (OutOfMemoryException) + { + throw new OutOfMemoryException(SR.Format(SR.BufferSizeTooLarge, _internalBufferSize)); + } + } + + /// + /// Gets or sets the path of the directory to watch. + /// + public string Path + { + get + { + return _directory; + } + set + { + value = (value == null) ? string.Empty : value; + if (!string.Equals(_directory, value, PathInternal.StringComparison)) + { + if (value.Length == 0) + throw new ArgumentException(SR.Format(SR.InvalidDirName, value), nameof(Path)); + + if (!Directory.Exists(value)) + throw new ArgumentException(SR.Format(SR.InvalidDirName_NotExists, value), nameof(Path)); + + _directory = value; + Restart(); + } + } + } + + /// + /// Occurs when a file or directory in the specified is changed. + /// + public event FileSystemEventHandler Changed + { + add + { + _onChangedHandler += value; + } + remove + { + _onChangedHandler -= value; + } + } + + /// + /// Occurs when a file or directory in the specified is created. + /// + public event FileSystemEventHandler Created + { + add + { + _onCreatedHandler += value; + } + remove + { + _onCreatedHandler -= value; + } + } + + /// + /// Occurs when a file or directory in the specified is deleted. + /// + public event FileSystemEventHandler Deleted + { + add + { + _onDeletedHandler += value; + } + remove + { + _onDeletedHandler -= value; + } + } + + /// + /// Occurs when the internal buffer overflows. + /// + public event ErrorEventHandler Error + { + add + { + _onErrorHandler += value; + } + remove + { + _onErrorHandler -= value; + } + } + + /// + /// Occurs when a file or directory in the specified + /// is renamed. + /// + public event RenamedEventHandler Renamed + { + add + { + _onRenamedHandler += value; + } + remove + { + _onRenamedHandler -= value; + } + } + + protected override void Dispose(bool disposing) + { + try + { + if (disposing) + { + //Stop raising events cleans up managed and + //unmanaged resources. + StopRaisingEvents(); + + // Clean up managed resources + _onChangedHandler = null; + _onCreatedHandler = null; + _onDeletedHandler = null; + _onRenamedHandler = null; + _onErrorHandler = null; + } + else + { + FinalizeDispose(); + } + } + finally + { + _disposed = true; + base.Dispose(disposing); + } + } + + private static void CheckPathValidity(string path) + { + if (path == null) + throw new ArgumentNullException(nameof(path)); + + // Early check for directory parameter so that an exception can be thrown as early as possible. + if (path.Length == 0) + throw new ArgumentException(SR.Format(SR.InvalidDirName, path), nameof(path)); + + if (!Directory.Exists(path)) + throw new ArgumentException(SR.Format(SR.InvalidDirName_NotExists, path), nameof(path)); + } + + /// + /// Sees if the name given matches the name filter we have. + /// + private bool MatchPattern(ReadOnlySpan relativePath) + { +#if MONO + if (relativePath.IsWhiteSpace()) + return false; +#endif + ReadOnlySpan name = IO.Path.GetFileName(relativePath); + + if (name.Length == 0) + return false; + + string[] filters = _filters.GetFilters(); + if (filters.Length == 0) + return true; + + foreach (string filter in filters) + { + if (FileSystemName.MatchesSimpleExpression(filter, name, ignoreCase: !PathInternal.IsCaseSensitive)) + return true; + } + + return false; + } + + /// + /// Raises the event to each handler in the list. + /// + private void NotifyInternalBufferOverflowEvent() + { + _onErrorHandler?.Invoke(this, new ErrorEventArgs( + new InternalBufferOverflowException(SR.Format(SR.FSW_BufferOverflow, _directory)))); + } + + /// + /// Raises the event to each handler in the list. + /// + private void NotifyRenameEventArgs(WatcherChangeTypes action, ReadOnlySpan name, ReadOnlySpan oldName) + { + // filter if there's no handler or neither new name or old name match a specified pattern + RenamedEventHandler handler = _onRenamedHandler; + if (handler != null && + (MatchPattern(name) || MatchPattern(oldName))) + { + handler(this, new RenamedEventArgs(action, _directory, name.IsEmpty ? null : name.ToString(), oldName.IsEmpty ? null : oldName.ToString())); + } + } + + private FileSystemEventHandler GetHandler(WatcherChangeTypes changeType) + { + switch (changeType) + { + case WatcherChangeTypes.Created: + return _onCreatedHandler; + case WatcherChangeTypes.Deleted: + return _onDeletedHandler; + case WatcherChangeTypes.Changed: + return _onChangedHandler; + } + + Debug.Fail("Unknown FileSystemEvent change type! Value: " + changeType); + return null; + } + + /// + /// Raises the event to each handler in the list. + /// + private void NotifyFileSystemEventArgs(WatcherChangeTypes changeType, ReadOnlySpan name) + { + FileSystemEventHandler handler = GetHandler(changeType); + + if (handler != null && MatchPattern(name.IsEmpty ? _directory : name)) + { + handler(this, new FileSystemEventArgs(changeType, _directory, name.IsEmpty ? null : name.ToString())); + } + } + + /// + /// Raises the event to each handler in the list. + /// + private void NotifyFileSystemEventArgs(WatcherChangeTypes changeType, string name) + { + FileSystemEventHandler handler = GetHandler(changeType); + + if (handler != null && MatchPattern(string.IsNullOrEmpty(name) ? _directory : name)) + { + handler(this, new FileSystemEventArgs(changeType, _directory, name)); + } + } + + /// + /// Raises the event. + /// + [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] + protected void OnChanged(FileSystemEventArgs e) + { + InvokeOn(e, _onChangedHandler); + } + + /// + /// Raises the event. + /// + [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] + protected void OnCreated(FileSystemEventArgs e) + { + InvokeOn(e, _onCreatedHandler); + } + + /// + /// Raises the event. + /// + [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] + protected void OnDeleted(FileSystemEventArgs e) + { + InvokeOn(e, _onDeletedHandler); + } + + private void InvokeOn(FileSystemEventArgs e, FileSystemEventHandler handler) + { + if (handler != null) + { + ISynchronizeInvoke syncObj = SynchronizingObject; + if (syncObj != null && syncObj.InvokeRequired) + syncObj.BeginInvoke(handler, new object[] { this, e }); + else + handler(this, e); + } + } + + /// + /// Raises the event. + /// + [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] + protected void OnError(ErrorEventArgs e) + { + ErrorEventHandler handler = _onErrorHandler; + if (handler != null) + { + ISynchronizeInvoke syncObj = SynchronizingObject; + if (syncObj != null && syncObj.InvokeRequired) + syncObj.BeginInvoke(handler, new object[] { this, e }); + else + handler(this, e); + } + } + + /// + /// Raises the event. + /// + [SuppressMessage("Microsoft.Security", "CA2109:ReviewVisibleEventHandlers", MessageId = "0#", Justification = "Changing from protected to private would be a breaking change")] + protected void OnRenamed(RenamedEventArgs e) + { + RenamedEventHandler handler = _onRenamedHandler; + if (handler != null) + { + ISynchronizeInvoke syncObj = SynchronizingObject; + if (syncObj != null && syncObj.InvokeRequired) + syncObj.BeginInvoke(handler, new object[] { this, e }); + else + handler(this, e); + } + } + + public WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType) => + WaitForChanged(changeType, Timeout.Infinite); + + public WaitForChangedResult WaitForChanged(WatcherChangeTypes changeType, int timeout) + { + // The full framework implementation doesn't do any argument validation, so + // none is done here, either. + + var tcs = new TaskCompletionSource(); + FileSystemEventHandler fseh = null; + RenamedEventHandler reh = null; + + // Register the event handlers based on what events are desired. The full framework + // doesn't register for the Error event, so this doesn't either. + if ((changeType & (WatcherChangeTypes.Created | WatcherChangeTypes.Deleted | WatcherChangeTypes.Changed)) != 0) + { + fseh = (s, e) => + { + if ((e.ChangeType & changeType) != 0) + { + tcs.TrySetResult(new WaitForChangedResult(e.ChangeType, e.Name, oldName: null, timedOut: false)); + } + }; + if ((changeType & WatcherChangeTypes.Created) != 0) + Created += fseh; + if ((changeType & WatcherChangeTypes.Deleted) != 0) + Deleted += fseh; + if ((changeType & WatcherChangeTypes.Changed) != 0) + Changed += fseh; + } + if ((changeType & WatcherChangeTypes.Renamed) != 0) + { + reh = (s, e) => + { + if ((e.ChangeType & changeType) != 0) + { + tcs.TrySetResult(new WaitForChangedResult(e.ChangeType, e.Name, e.OldName, timedOut: false)); + } + }; + Renamed += reh; + } + try + { + // Enable the FSW if it wasn't already. + bool wasEnabled = EnableRaisingEvents; + if (!wasEnabled) + { + EnableRaisingEvents = true; + } + + // Block until an appropriate event arrives or until we timeout. + Debug.Assert(EnableRaisingEvents, "Expected EnableRaisingEvents to be true"); + tcs.Task.Wait(timeout); + + // Reset the enabled state to what it was. + EnableRaisingEvents = wasEnabled; + } + finally + { + // Unregister the event handlers. + if (reh != null) + { + Renamed -= reh; + } + if (fseh != null) + { + if ((changeType & WatcherChangeTypes.Changed) != 0) + Changed -= fseh; + if ((changeType & WatcherChangeTypes.Deleted) != 0) + Deleted -= fseh; + if ((changeType & WatcherChangeTypes.Created) != 0) + Created -= fseh; + } + } + + // Return the results. +#if MONO + return tcs.Task.Status == TaskStatus.RanToCompletion ? + tcs.Task.Result : + WaitForChangedResult.TimedOutResult; +#else + return tcs.Task.IsCompletedSuccessfully ? + tcs.Task.Result : + WaitForChangedResult.TimedOutResult; +#endif + } + + /// + /// Stops and starts this object. + /// + /// + private void Restart() + { + if ((!IsSuspended()) && _enabled) + { + StopRaisingEvents(); + StartRaisingEventsIfNotDisposed(); + } + } + + private void StartRaisingEventsIfNotDisposed() + { + //Cannot allocate the directoryHandle and the readBuffer if the object has been disposed; finalization has been suppressed. + if (_disposed) + throw new ObjectDisposedException(GetType().Name); + StartRaisingEvents(); + } + + public override ISite Site + { + get + { + return base.Site; + } + set + { + base.Site = value; + + // set EnableRaisingEvents to true at design time so the user + // doesn't have to manually. + if (Site != null && Site.DesignMode) + EnableRaisingEvents = true; + } + } + + public ISynchronizeInvoke SynchronizingObject { get; set; } + + public void BeginInit() + { + bool oldEnabled = _enabled; + StopRaisingEvents(); + _enabled = oldEnabled; + _initializing = true; + } + + public void EndInit() + { + _initializing = false; + // Start listening to events if _enabled was set to true at some point. + if (_directory.Length != 0 && _enabled) + StartRaisingEvents(); + } + + private bool IsSuspended() + { + return _initializing || DesignMode; + } + + private sealed class NormalizedFilterCollection : Collection + { + internal NormalizedFilterCollection() : base(new ImmutableStringList()) + { + } + + protected override void InsertItem(int index, string item) + { + base.InsertItem(index, string.IsNullOrEmpty(item) || item == "*.*" ? "*" : item); + } + + protected override void SetItem(int index, string item) + { + base.SetItem(index, string.IsNullOrEmpty(item) || item == "*.*" ? "*" : item); + } + + internal string[] GetFilters() => ((ImmutableStringList)Items).Items; + + /// + /// List that maintains its underlying data in an immutable array, such that the list + /// will never modify an array returned from its Items property. This is to allow + /// the array to be enumerated safely while another thread might be concurrently mutating + /// the collection. + /// + private sealed class ImmutableStringList : IList + { + public string[] Items = Array.Empty(); + + public string this[int index] + { + get + { + string[] items = Items; + if ((uint)index >= (uint)items.Length) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + return items[index]; + } + set + { + string[] clone = (string[])Items.Clone(); + clone[index] = value; + Items = clone; + } + } + + public int Count => Items.Length; + + public bool IsReadOnly => false; + + public void Add(string item) + { + // Collection doesn't use this method. + throw new NotSupportedException(); + } + + public void Clear() => Items = Array.Empty(); + + public bool Contains(string item) => Array.IndexOf(Items, item) != -1; + + public void CopyTo(string[] array, int arrayIndex) => Items.CopyTo(array, arrayIndex); + + public IEnumerator GetEnumerator() => ((IEnumerable)Items).GetEnumerator(); + + public int IndexOf(string item) => Array.IndexOf(Items, item); + + public void Insert(int index, string item) + { + string[] items = Items; + string[] newItems = new string[items.Length + 1]; + items.AsSpan(0, index).CopyTo(newItems); + items.AsSpan(index).CopyTo(newItems.AsSpan(index + 1)); + newItems[index] = item; + Items = newItems; + } + + public bool Remove(string item) + { + // Collection doesn't use this method. + throw new NotSupportedException(); + } + + public void RemoveAt(int index) + { + string[] items = Items; + string[] newItems = new string[items.Length - 1]; + items.AsSpan(0, index).CopyTo(newItems); + items.AsSpan(index + 1).CopyTo(newItems.AsSpan(index)); + Items = newItems; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + } + } +} diff --git a/mcs/class/System/linux_unityaot_System.dll.exclude.sources b/mcs/class/System/linux_unityaot_System.dll.exclude.sources index 66fbcf6d57d8..69fb97c5daa1 100644 --- a/mcs/class/System/linux_unityaot_System.dll.exclude.sources +++ b/mcs/class/System/linux_unityaot_System.dll.exclude.sources @@ -1,3 +1,6 @@ System.Net/MacProxy.cs Mono/AppleTypes.cs System.Security.Cryptography.X509Certificates/OSX509Certificates.cs +System.IO/FileSystemWatcher.DefaultEventAttribute.cs +../../../external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs +../../../external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs diff --git a/mcs/class/System/linux_unityaot_System.dll.sources b/mcs/class/System/linux_unityaot_System.dll.sources index 32d6defda4e2..98dd9f0cd923 100644 --- a/mcs/class/System/linux_unityaot_System.dll.sources +++ b/mcs/class/System/linux_unityaot_System.dll.sources @@ -3,4 +3,10 @@ ../System.Web/System.Web.Util/Helpers.cs ../System.Web/System.Web.Util/HttpEncoder.cs System.CodeDom/CodeCompileUnit.cs -System.CodeDom/CodeTypeDeclaration.cs \ No newline at end of file +System.CodeDom/CodeTypeDeclaration.cs + +#include mono_fsw.sources + +../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs +../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs + diff --git a/mcs/class/System/macos_unityaot_System.dll.exclude.sources b/mcs/class/System/macos_unityaot_System.dll.exclude.sources index 66fbcf6d57d8..8a295382aca4 100644 --- a/mcs/class/System/macos_unityaot_System.dll.exclude.sources +++ b/mcs/class/System/macos_unityaot_System.dll.exclude.sources @@ -1,3 +1,7 @@ System.Net/MacProxy.cs Mono/AppleTypes.cs System.Security.Cryptography.X509Certificates/OSX509Certificates.cs +System.IO/FileSystemWatcher.DefaultEventAttribute.cs +../../../external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs +../../../external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs + diff --git a/mcs/class/System/macos_unityaot_System.dll.sources b/mcs/class/System/macos_unityaot_System.dll.sources index 32d6defda4e2..79e50a7b5907 100644 --- a/mcs/class/System/macos_unityaot_System.dll.sources +++ b/mcs/class/System/macos_unityaot_System.dll.sources @@ -3,4 +3,9 @@ ../System.Web/System.Web.Util/Helpers.cs ../System.Web/System.Web.Util/HttpEncoder.cs System.CodeDom/CodeCompileUnit.cs -System.CodeDom/CodeTypeDeclaration.cs \ No newline at end of file +System.CodeDom/CodeTypeDeclaration.cs +#include mono_fsw.sources + +../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs +../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs + diff --git a/mcs/class/System/win32_unityaot_System.dll.exclude.sources b/mcs/class/System/win32_unityaot_System.dll.exclude.sources index 7f9dbb36684d..d67236c4acdd 100644 --- a/mcs/class/System/win32_unityaot_System.dll.exclude.sources +++ b/mcs/class/System/win32_unityaot_System.dll.exclude.sources @@ -3,4 +3,7 @@ #include linux_networkinfo.sources #include macos_networkinfo.sources +System.IO/FileSystemWatcher.DefaultEventAttribute.cs ../../../external/corefx/src/Common/src/System/Net/Security/CertificateHelper.Unix.cs +../../../external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs +../../../external/corefx/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs diff --git a/mcs/class/System/win32_unityaot_System.dll.sources b/mcs/class/System/win32_unityaot_System.dll.sources index 984a7857e5fa..95119bfed4db 100644 --- a/mcs/class/System/win32_unityaot_System.dll.sources +++ b/mcs/class/System/win32_unityaot_System.dll.sources @@ -9,4 +9,10 @@ System.Net.NetworkInformation/Win32UnixFactoryPal.cs ../../../external/corefx/src/Common/src/Interop/Windows/kernel32/Interop.CloseHandle.cs System.CodeDom/CodeCompileUnit.cs -System.CodeDom/CodeTypeDeclaration.cs \ No newline at end of file +System.CodeDom/CodeTypeDeclaration.cs + +#include mono_fsw.sources + +../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs +../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs + From d8d5e04b22585fcca30fff3a4ea8e766ba3aa30e Mon Sep 17 00:00:00 2001 From: Jonathan Chambers Date: Mon, 9 Aug 2021 12:55:50 -0400 Subject: [PATCH 2/3] Test commit to try and reduce dependencies. --- mcs/class/System/System.IO/FileSystemWatcher.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mcs/class/System/System.IO/FileSystemWatcher.cs b/mcs/class/System/System.IO/FileSystemWatcher.cs index cbf71e7a9a68..33b1d0c8403e 100644 --- a/mcs/class/System/System.IO/FileSystemWatcher.cs +++ b/mcs/class/System/System.IO/FileSystemWatcher.cs @@ -123,10 +123,11 @@ void InitWatcher () string managed = Environment.GetEnvironmentVariable ("MONO_MANAGED_WATCHER"); int mode = 0; + bool ok = false; +#if !UNITY_AOT if (managed == null) mode = InternalSupportsFSW (); - bool ok = false; switch (mode) { case 1: // windows ok = DefaultWatcher.GetInstance (out watcher); @@ -149,6 +150,7 @@ void InitWatcher () watcher_handle = (watcher as CoreFXFileSystemWatcherProxy).NewWatcher (this); break; } +#endif if (mode == 0 || !ok) { if (String.Compare (managed, "disabled", true) == 0) From 03c3451188bd12abb24711b7b6583b1b211540a9 Mon Sep 17 00:00:00 2001 From: Jonathan Chambers Date: Fri, 13 Aug 2021 15:13:48 -0400 Subject: [PATCH 3/3] Exclude more types from unityaot profile. --- mcs/class/System/System.IO/FileSystemWatcher.cs | 2 ++ mcs/class/System/linux_unityaot_System.dll.sources | 2 +- mcs/class/System/macos_unityaot_System.dll.sources | 2 +- mcs/class/System/unityaot_fsw.sources | 6 ++++++ mcs/class/System/win32_unityaot_System.dll.sources | 2 +- 5 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 mcs/class/System/unityaot_fsw.sources diff --git a/mcs/class/System/System.IO/FileSystemWatcher.cs b/mcs/class/System/System.IO/FileSystemWatcher.cs index 33b1d0c8403e..2f1ae15a5cd2 100644 --- a/mcs/class/System/System.IO/FileSystemWatcher.cs +++ b/mcs/class/System/System.IO/FileSystemWatcher.cs @@ -198,9 +198,11 @@ internal string MangledFilter { internal SearchPattern2 Pattern { get { if (pattern == null) { +#if !UNITY_AOT if (watcher?.GetType () == typeof (KeventWatcher)) pattern = new SearchPattern2 (MangledFilter, true); //assume we want to ignore case (OS X) else +#endif pattern = new SearchPattern2 (MangledFilter); } return pattern; diff --git a/mcs/class/System/linux_unityaot_System.dll.sources b/mcs/class/System/linux_unityaot_System.dll.sources index 98dd9f0cd923..e47af5c8ebe0 100644 --- a/mcs/class/System/linux_unityaot_System.dll.sources +++ b/mcs/class/System/linux_unityaot_System.dll.sources @@ -5,7 +5,7 @@ System.CodeDom/CodeCompileUnit.cs System.CodeDom/CodeTypeDeclaration.cs -#include mono_fsw.sources +#include unityaot_fsw.sources ../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs ../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs diff --git a/mcs/class/System/macos_unityaot_System.dll.sources b/mcs/class/System/macos_unityaot_System.dll.sources index 79e50a7b5907..f0f5fa1c4bcd 100644 --- a/mcs/class/System/macos_unityaot_System.dll.sources +++ b/mcs/class/System/macos_unityaot_System.dll.sources @@ -4,7 +4,7 @@ ../System.Web/System.Web.Util/HttpEncoder.cs System.CodeDom/CodeCompileUnit.cs System.CodeDom/CodeTypeDeclaration.cs -#include mono_fsw.sources +#include unityaot_fsw.sources ../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs ../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs diff --git a/mcs/class/System/unityaot_fsw.sources b/mcs/class/System/unityaot_fsw.sources new file mode 100644 index 000000000000..7b791837da8a --- /dev/null +++ b/mcs/class/System/unityaot_fsw.sources @@ -0,0 +1,6 @@ +System.IO/DefaultWatcher.cs +System.IO/NullFileWatcher.cs +System.IO/FileAction.cs +System.IO/FileSystemWatcher.cs +System.IO/IFileWatcher.cs +System.IO/SearchPattern.cs diff --git a/mcs/class/System/win32_unityaot_System.dll.sources b/mcs/class/System/win32_unityaot_System.dll.sources index 95119bfed4db..4938dbc4db90 100644 --- a/mcs/class/System/win32_unityaot_System.dll.sources +++ b/mcs/class/System/win32_unityaot_System.dll.sources @@ -11,7 +11,7 @@ System.Net.NetworkInformation/Win32UnixFactoryPal.cs System.CodeDom/CodeCompileUnit.cs System.CodeDom/CodeTypeDeclaration.cs -#include mono_fsw.sources +#include unityaot_fsw.sources ../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs ../../../external/corefx-bugfix/src/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.UnknownUnix.cs