public static IEnumerable <NPath> Move(this IEnumerable <NPath> self, NPath dest) { if (dest.IsRelative) { throw new ArgumentException("When moving multiple files, the destination cannot be a relative path"); } dest.EnsureDirectoryExists(); return(self.Select(p => p.Move(dest.Combine(p.FileName))).ToArray()); }
public static NPath ToFile(ResourceType resourceType, string resource, NPath destinationPath, IEnvironment environment) { /* * This function attempts to get files embedded in the callers assembly. * GitHub.Unity which tends to contain logos * GitHub.Api which tends to contain application resources * * Each file's name is their physical path in the project. * * When running tests, we assume the tests are looking for application resources, and default to returning GitHub.Api * * First check for the resource in the calling assembly. * If the resource cannot be found, fallback to looking in GitHub.Api's assembly. * If the resource is still not found, it attempts to find it in the file system */ var target = destinationPath.Combine(resource); var os = ""; if (resourceType == ResourceType.Platform) { os = DefaultEnvironment.OnWindows ? "windows" : DefaultEnvironment.OnLinux ? "linux" : "mac"; } var type = resourceType == ResourceType.Icon ? "IconsAndLogos" : resourceType == ResourceType.Platform ? "PlatformResources" : "Resources"; // all the resources are embedded in GitHub.Api var asm = Assembly.GetCallingAssembly(); if (resourceType != ResourceType.Icon) { asm = typeof(AssemblyResources).Assembly; } var stream = asm.GetManifestResourceStream( String.Format("GitHub.Unity.{0}{1}.{2}", type, !string.IsNullOrEmpty(os) ? "." + os : os, resource)); if (stream != null) { target.DeleteIfExists(); return(target.WriteAllBytes(stream.ToByteArray())); } // if we're not in the test runner, we might be running in a Unity-compiled GitHub.Unity assembly, which doesn't // embed the resources in the assembly // check the filesystem NPath possiblePath = environment.ExtensionInstallPath.Combine(type, os, resource); if (possiblePath.FileExists()) { target.DeleteIfExists(); return(possiblePath.Copy(target)); } return(NPath.Default); }
public static NPath CreateTempDirectory(this NPath baseDir, string myprefix = "") { var random = new Random(); while (true) { var candidate = baseDir.Combine(myprefix + "_" + random.Next()); if (!candidate.Exists()) { return(candidate.CreateDirectory()); } } }
public static NPath GetAssetPath(this IEnvironment environment, NPath path) { Guard.ArgumentNotNull(path, nameof(path)); NPath projectPath = environment.UnityProjectPath; NPath repositoryPath = environment.RepositoryPath; if (projectPath == repositoryPath) { return(path); } if (repositoryPath.IsChildOf(projectPath)) { throw new InvalidOperationException($"RepositoryPath:\"{repositoryPath}\" should not be child of ProjectPath:\"{projectPath}\""); } return(repositoryPath.Combine(path).MakeAbsolute().RelativeTo(projectPath)); }
public RepositoryPathConfiguration(NPath repositoryPath) { RepositoryPath = repositoryPath; WorktreeDotGitPath = NPath.Default; DotGitPath = repositoryPath.Combine(".git"); NPath commonPath; if (DotGitPath.FileExists()) { DotGitPath = DotGitPath.ReadAllLines() .Where(x => x.StartsWith("gitdir:")) .Select(x => x.Substring(7).Trim().ToNPath()) .First(); if (DotGitPath.Combine("commondir").FileExists()) { commonPath = DotGitPath.Combine("commondir").ReadAllLines() .Select(x => x.Trim().ToNPath()) .First(); commonPath = DotGitPath.Combine(commonPath); IsWorktree = true; WorktreeDotGitPath = commonPath; } else { commonPath = DotGitPath; } } else { commonPath = DotGitPath; } BranchesPath = commonPath.Combine("refs", "heads"); RemotesPath = commonPath.Combine("refs", "remotes"); DotGitIndex = DotGitPath.Combine("index"); DotGitHead = DotGitPath.Combine("HEAD"); DotGitConfig = commonPath.Combine("config"); DotGitCommitEditMsg = DotGitPath.Combine("COMMIT_EDITMSG"); }
public RepositoryPathConfiguration(NPath repositoryPath) { RepositoryPath = repositoryPath; DotGitPath = repositoryPath.Combine(".git"); if (DotGitPath.FileExists()) { DotGitPath = DotGitPath.ReadAllLines() .Where(x => x.StartsWith("gitdir:")) .Select(x => x.Substring(7).Trim().ToNPath()) .First(); } BranchesPath = DotGitPath.Combine("refs", "heads"); RemotesPath = DotGitPath.Combine("refs", "remotes"); DotGitIndex = DotGitPath.Combine("index"); DotGitHead = DotGitPath.Combine("HEAD"); DotGitConfig = DotGitPath.Combine("config"); }
private NPath MoveGitAndLfs(NPath gitExtractPath, NPath gitLfsExtractPath, NPath tempZipExtractPath) { var targetGitLfsExecPath = installDetails.GetGitLfsExecutablePath(gitExtractPath); var extractGitLfsExePath = gitLfsExtractPath.Combine(installDetails.GitLfsExecutable); Logger.Trace($"Moving Git LFS Exe:'{extractGitLfsExePath}' to target in tempDirectory:'{targetGitLfsExecPath}'"); extractGitLfsExePath.Move(targetGitLfsExecPath); Logger.Trace($"Moving tempDirectory:'{gitExtractPath}' to extractTarget:'{installDetails.GitInstallationPath}'"); installDetails.GitInstallationPath.EnsureParentDirectoryExists(); gitExtractPath.Move(installDetails.GitInstallationPath); Logger.Trace($"Deleting targetGitLfsExecPath:'{targetGitLfsExecPath}'"); targetGitLfsExecPath.DeleteIfExists(); Logger.Trace($"Deleting tempZipPath:'{tempZipExtractPath}'"); tempZipExtractPath.DeleteIfExists(); return(installDetails.GitExecutablePath); }
public static NPath ToFile(ResourceType resourceType, string resource, NPath destinationPath, IEnvironment environment) { var os = ""; if (resourceType == ResourceType.Platform) { os = DefaultEnvironment.OnWindows ? "windows" : DefaultEnvironment.OnLinux ? "linux" : "mac"; } var type = resourceType == ResourceType.Icon ? "IconsAndLogos" : resourceType == ResourceType.Platform ? "PlatformResources" : "Resources"; var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream( String.Format("GitHub.Unity.{0}{1}.{2}", type, os != "" ? "." + os : os, resource)); if (stream != null) { return(destinationPath.Combine(resource).WriteAllBytes(stream.ToByteArray())); } return(environment.ExtensionInstallPath.Combine(type, os, resource)); }
public NPath FindRoot(NPath path) { if (path == null) { return(null); } if (path.FileExists()) { path = path.Parent; } if (path.Combine(".git").DirectoryExists()) { return(path); } if (path.IsEmpty) { return(null); } return(FindRoot(path.Parent)); }
public GitInstallDetails(NPath targetInstallPath, bool onWindows) { this.onWindows = onWindows; var gitInstallPath = targetInstallPath.Combine(ApplicationInfo.ApplicationName, PackageNameWithVersion); GitInstallationPath = gitInstallPath; if (onWindows) { GitExecutable += "git.exe"; GitLfsExecutable += "git-lfs.exe"; GitExecutablePath = gitInstallPath.Combine("cmd", GitExecutable); } else { GitExecutable = "git"; GitLfsExecutable = "git-lfs"; GitExecutablePath = gitInstallPath.Combine("bin", GitExecutable); } GitLfsExecutablePath = GetGitLfsExecutablePath(gitInstallPath); }
public Task <DownloadData> QueueDownload(UriString url, UriString md5Url, NPath targetDirectory) { var destinationFile = targetDirectory.Combine(url.Filename); var destinationMd5 = targetDirectory.Combine(md5Url.Filename); var result = new DownloadData(url, destinationFile); Action <ITask <NPath>, NPath, bool, Exception> verifyDownload = (t, res, success, ex) => { var count = Interlocked.Increment(ref finishedTaskCount); isSuccessful &= success; if (!success) { exception = ex; } if (count == queuedTasks.Count) { if (!isSuccessful) { DownloadFailed(result, exception); } else { if (!Utils.VerifyFileIntegrity(destinationFile, destinationMd5)) { destinationMd5.Delete(); destinationFile.Delete(); DownloadFailed(result, new DownloadException($"Verification of {url} failed")); } else { DownloadComplete(result); } } } }; var md5Exists = destinationMd5.FileExists(); var fileExists = destinationFile.FileExists(); if (!md5Exists) { destinationMd5.DeleteIfExists(); var md5Download = new DownloadTask(cancellationToken, fs, md5Url, targetDirectory) .Catch(e => DownloadFailed(result, e)); md5Download.OnEnd += verifyDownload; queuedTasks.Add(md5Download); } if (!fileExists) { var fileDownload = new DownloadTask(cancellationToken, fs, url, targetDirectory) .Catch(e => DownloadFailed(result, e)); fileDownload.OnStart += _ => DownloadStart?.Invoke(result); fileDownload.OnEnd += verifyDownload; queuedTasks.Add(fileDownload); } if (fileExists && md5Exists) { var verification = new FuncTask <NPath>(cancellationToken, () => destinationFile); verification.OnEnd += verifyDownload; queuedTasks.Add(verification); } return(aggregateDownloads.Task); }
private int ProcessEvents(Event[] fileEvents) { var events = new HashSet <EventType>(); foreach (var fileEvent in fileEvents) { if (!running) { break; } if (cancellationToken.IsCancellationRequested) { Stop(); break; } //Logger.Trace(fileEvent.Describe()); var eventDirectory = new NPath(fileEvent.Directory); var fileA = eventDirectory.Combine(fileEvent.FileA); NPath fileB = null; if (fileEvent.FileB != null) { fileB = eventDirectory.Combine(fileEvent.FileB); } // handling events in .git/* if (fileA.IsChildOf(paths.DotGitPath)) { if (!events.Contains(EventType.ConfigChanged) && fileA.Equals(paths.DotGitConfig)) { events.Add(EventType.ConfigChanged); } else if (!events.Contains(EventType.HeadChanged) && fileA.Equals(paths.DotGitHead)) { events.Add(EventType.HeadChanged); } else if (!events.Contains(EventType.IndexChanged) && fileA.Equals(paths.DotGitIndex)) { events.Add(EventType.IndexChanged); } else if (!events.Contains(EventType.RemoteBranchesChanged) && fileA.IsChildOf(paths.RemotesPath)) { events.Add(EventType.RemoteBranchesChanged); } else if (!events.Contains(EventType.LocalBranchesChanged) && fileA.IsChildOf(paths.BranchesPath)) { events.Add(EventType.LocalBranchesChanged); } else if (!events.Contains(EventType.RepositoryCommitted) && fileA.IsChildOf(paths.DotGitCommitEditMsg)) { events.Add(EventType.RepositoryCommitted); } } else { if (events.Contains(EventType.RepositoryChanged) || ignoredPaths.Any(ignoredPath => fileA.IsChildOf(ignoredPath))) { continue; } events.Add(EventType.RepositoryChanged); } } return(FireEvents(events)); }
public Task <bool> SetupGitLfsIfNeeded(NPath tempPath, IProgress <float> zipFileProgress = null, IProgress <long> estimatedDurationProgress = null) { logger.Trace("SetupGitLfsIfNeeded"); cancellationToken.ThrowIfCancellationRequested(); if (IsGitLfsExtracted()) { logger.Trace("Already extracted {0}, returning", GitLfsExecutablePath); return(TaskEx.FromResult(false)); } cancellationToken.ThrowIfCancellationRequested(); var archiveFilePath = AssemblyResources.ToFile(ResourceType.Platform, GitLfsZipFile, tempPath, environment); if (!archiveFilePath.FileExists()) { logger.Warning("Archive \"{0}\" missing", archiveFilePath.ToString()); archiveFilePath = environment.ExtensionInstallPath.Combine(archiveFilePath); if (!archiveFilePath.FileExists()) { logger.Warning("Archive \"{0}\" missing, returning", archiveFilePath.ToString()); return(TaskEx.FromResult(false)); } } cancellationToken.ThrowIfCancellationRequested(); var unzipPath = tempPath.Combine("git-lfs"); try { logger.Trace("Extracting \"{0}\" to \"{1}\"", archiveFilePath, unzipPath); extractCallback(archiveFilePath, unzipPath, cancellationToken, zipFileProgress, estimatedDurationProgress); } catch (Exception ex) { logger.Error(ex, "Error Extracting Archive:\"{0}\" OutDir:\"{1}\"", archiveFilePath, tempPath); return(TaskEx.FromResult(false)); } cancellationToken.ThrowIfCancellationRequested(); try { var unzippedGitLfsExecutablePath = unzipPath.Combine(GitLfsExecutable); logger.Trace("Copying \"{0}\" to \"{1}\"", unzippedGitLfsExecutablePath, GitLfsExecutablePath); unzippedGitLfsExecutablePath.Copy(GitLfsExecutablePath); } catch (Exception ex) { logger.Error(ex, "Error Copying git-lfs Source:\"{0}\" Destination:\"{1}\"", unzipPath, GitLfsExecutablePath); return(TaskEx.FromResult(false)); } unzipPath.DeleteIfExists(); return(TaskEx.FromResult(true)); }
public NPath GetGitLfsExecutablePath(NPath gitInstallRoot) { return(onWindows ? gitInstallRoot.Combine("mingw32", "libexec", "git-core", GitLfsExecutable) : gitInstallRoot.Combine("libexec", "git-core", GitLfsExecutable)); }
private int ProcessEvents(Event[] fileEvents) { var eventsProcessed = 0; var configChanged = false; var headChanged = false; var repositoryChanged = false; var indexChanged = false; string headContent = null; foreach (var fileEvent in fileEvents) { if (!running) { break; } if (cancellationToken.IsCancellationRequested) { Stop(); break; } //Logger.Trace(fileEvent.Describe()); var eventDirectory = new NPath(fileEvent.Directory); var fileA = eventDirectory.Combine(fileEvent.FileA); NPath fileB = null; if (fileEvent.FileB != null) { fileB = eventDirectory.Combine(fileEvent.FileB); } // handling events in .git/* if (fileA.IsChildOf(paths.DotGitPath)) { if (!configChanged && fileA.Equals(paths.DotGitConfig)) { configChanged = true; } else if (!headChanged && fileA.Equals(paths.DotGitHead)) { if (fileEvent.Type != EventType.DELETED) { headContent = paths.DotGitHead.ReadAllLines().FirstOrDefault(); } headChanged = true; } else if (!indexChanged && fileA.Equals(paths.DotGitIndex)) { indexChanged = true; } else if (fileA.IsChildOf(paths.RemotesPath)) { var relativePath = fileA.RelativeTo(paths.RemotesPath); var relativePathElements = relativePath.Elements.ToArray(); if (!relativePathElements.Any()) { continue; } var origin = relativePathElements[0]; if (fileEvent.Type == EventType.DELETED) { if (fileA.ExtensionWithDot == ".lock") { continue; } var branch = string.Join(@"/", relativePathElements.Skip(1).ToArray()); Logger.Trace("RemoteBranchDeleted: {0}/{1}", origin, branch); RemoteBranchDeleted?.Invoke(origin, branch); eventsProcessed++; } else if (fileEvent.Type == EventType.RENAMED) { if (fileA.ExtensionWithDot != ".lock") { continue; } if (fileB != null && fileB.FileExists()) { if (fileA.FileNameWithoutExtension == fileB.FileNameWithoutExtension) { var branchPathElement = relativePathElements .Skip(1).Take(relativePathElements.Length - 2) .Union(new[] { fileA.FileNameWithoutExtension }).ToArray(); var branch = string.Join(@"/", branchPathElement); Logger.Trace("RemoteBranchCreated: {0}/{1}", origin, branch); RemoteBranchCreated?.Invoke(origin, branch); eventsProcessed++; } } } } else if (fileA.IsChildOf(paths.BranchesPath)) { if (fileEvent.Type == EventType.MODIFIED) { if (fileA.DirectoryExists()) { continue; } if (fileA.ExtensionWithDot == ".lock") { continue; } var relativePath = fileA.RelativeTo(paths.BranchesPath); var relativePathElements = relativePath.Elements.ToArray(); if (!relativePathElements.Any()) { continue; } var branch = string.Join(@"/", relativePathElements.ToArray()); Logger.Trace("LocalBranchChanged: {0}", branch); LocalBranchChanged?.Invoke(branch); eventsProcessed++; } else if (fileEvent.Type == EventType.DELETED) { if (fileA.ExtensionWithDot == ".lock") { continue; } var relativePath = fileA.RelativeTo(paths.BranchesPath); var relativePathElements = relativePath.Elements.ToArray(); if (!relativePathElements.Any()) { continue; } var branch = string.Join(@"/", relativePathElements.ToArray()); Logger.Trace("LocalBranchDeleted: {0}", branch); LocalBranchDeleted?.Invoke(branch); eventsProcessed++; } else if (fileEvent.Type == EventType.RENAMED) { if (fileA.ExtensionWithDot != ".lock") { continue; } if (fileB != null && fileB.FileExists()) { if (fileA.FileNameWithoutExtension == fileB.FileNameWithoutExtension) { var relativePath = fileB.RelativeTo(paths.BranchesPath); var relativePathElements = relativePath.Elements.ToArray(); if (!relativePathElements.Any()) { continue; } var branch = string.Join(@"/", relativePathElements.ToArray()); Logger.Trace("LocalBranchCreated: {0}", branch); LocalBranchCreated?.Invoke(branch); eventsProcessed++; } } } } } else { if (repositoryChanged || ignoredPaths.Any(ignoredPath => fileA.IsChildOf(ignoredPath))) { continue; } repositoryChanged = true; } } if (configChanged) { Logger.Trace("ConfigChanged"); ConfigChanged?.Invoke(); eventsProcessed++; } if (headChanged) { Logger.Trace("HeadChanged: {0}", headContent ?? "[null]"); HeadChanged?.Invoke(headContent); eventsProcessed++; } if (indexChanged) { Logger.Trace("IndexChanged"); IndexChanged?.Invoke(); eventsProcessed++; } if (repositoryChanged) { Logger.Trace("RepositoryChanged"); RepositoryChanged?.Invoke(); eventsProcessed++; } return(eventsProcessed); }
private int ProcessEvents(Event[] fileEvents) { Dictionary <EventType, List <EventData> > events = new Dictionary <EventType, List <EventData> >(); foreach (var fileEvent in fileEvents) { if (!running) { break; } if (cancellationToken.IsCancellationRequested) { Stop(); break; } //Logger.Trace(fileEvent.Describe()); var eventDirectory = new NPath(fileEvent.Directory); var fileA = eventDirectory.Combine(fileEvent.FileA); NPath fileB = null; if (fileEvent.FileB != null) { fileB = eventDirectory.Combine(fileEvent.FileB); } // handling events in .git/* if (fileA.IsChildOf(paths.DotGitPath)) { if (!events.ContainsKey(EventType.ConfigChanged) && fileA.Equals(paths.DotGitConfig)) { events.Add(EventType.ConfigChanged, null); } else if (!events.ContainsKey(EventType.HeadChanged) && fileA.Equals(paths.DotGitHead)) { events.Add(EventType.HeadChanged, null); } else if (!events.ContainsKey(EventType.IndexChanged) && fileA.Equals(paths.DotGitIndex)) { events.Add(EventType.IndexChanged, null); } else if (fileA.IsChildOf(paths.RemotesPath)) { var relativePath = fileA.RelativeTo(paths.RemotesPath); var relativePathElements = relativePath.Elements.ToArray(); if (!relativePathElements.Any()) { continue; } var origin = relativePathElements[0]; if (fileEvent.Type == sfw.net.EventType.DELETED) { if (fileA.ExtensionWithDot == ".lock") { continue; } var branch = string.Join(@"/", relativePathElements.Skip(1).ToArray()); AddOrUpdateEventData(events, EventType.RemoteBranchDeleted, new EventData { Origin = origin, Branch = branch }); } else if (fileEvent.Type == sfw.net.EventType.RENAMED) { if (fileA.ExtensionWithDot != ".lock") { continue; } if (fileB != null && fileB.FileExists()) { if (fileA.FileNameWithoutExtension == fileB.FileNameWithoutExtension) { var branchPathElement = relativePathElements .Skip(1).Take(relativePathElements.Length - 2) .Union(new[] { fileA.FileNameWithoutExtension }).ToArray(); var branch = string.Join(@"/", branchPathElement); AddOrUpdateEventData(events, EventType.RemoteBranchCreated, new EventData { Origin = origin, Branch = branch }); } } } } else if (fileA.IsChildOf(paths.BranchesPath)) { if (fileEvent.Type == sfw.net.EventType.MODIFIED) { if (fileA.DirectoryExists()) { continue; } if (fileA.ExtensionWithDot == ".lock") { continue; } var relativePath = fileA.RelativeTo(paths.BranchesPath); var relativePathElements = relativePath.Elements.ToArray(); if (!relativePathElements.Any()) { continue; } var branch = string.Join(@"/", relativePathElements.ToArray()); AddOrUpdateEventData(events, EventType.LocalBranchChanged, new EventData { Branch = branch }); } else if (fileEvent.Type == sfw.net.EventType.DELETED) { if (fileA.ExtensionWithDot == ".lock") { continue; } var relativePath = fileA.RelativeTo(paths.BranchesPath); var relativePathElements = relativePath.Elements.ToArray(); if (!relativePathElements.Any()) { continue; } var branch = string.Join(@"/", relativePathElements.ToArray()); AddOrUpdateEventData(events, EventType.LocalBranchDeleted, new EventData { Branch = branch }); } else if (fileEvent.Type == sfw.net.EventType.RENAMED) { if (fileA.ExtensionWithDot != ".lock") { continue; } if (fileB != null && fileB.FileExists()) { if (fileA.FileNameWithoutExtension == fileB.FileNameWithoutExtension) { var relativePath = fileB.RelativeTo(paths.BranchesPath); var relativePathElements = relativePath.Elements.ToArray(); if (!relativePathElements.Any()) { continue; } var branch = string.Join(@"/", relativePathElements.ToArray()); AddOrUpdateEventData(events, EventType.LocalBranchCreated, new EventData { Branch = branch }); } } } } } else { if (events.ContainsKey(EventType.RepositoryChanged) || ignoredPaths.Any(ignoredPath => fileA.IsChildOf(ignoredPath))) { continue; } events.Add(EventType.RepositoryChanged, null); } } return(FireEvents(events)); }
public int CheckAndProcessEvents() { if (processingEvents) { signalProcessingEventsDone.Wait(cancellationToken); return(lastCountOfProcessedEvents); } signalProcessingEventsDone.Reset(); processingEvents = true; lastCountOfProcessedEvents = 0; var fileEvents = nativeInterface.GetEvents(); if (fileEvents.Length > 0) { Logger.Trace("Processing {0} Events", fileEvents.Length); } var repositoryChanged = false; foreach (var fileEvent in fileEvents) { if (!running) { break; } if (cancellationToken.IsCancellationRequested) { Stop(); break; } //Logger.Trace(fileEvent.Describe()); var eventDirectory = new NPath(fileEvent.Directory); var fileA = eventDirectory.Combine(fileEvent.FileA); NPath fileB = null; if (fileEvent.FileB != null) { fileB = eventDirectory.Combine(fileEvent.FileB); } // handling events in .git/* if (fileA.IsChildOf(paths.DotGitPath)) { HandleEventInDotGit(fileEvent, fileA, fileB); } else { if (repositoryChanged || ignoredPaths.Any(ignoredPath => fileA.IsChildOf(ignoredPath))) { continue; } repositoryChanged = true; } lastCountOfProcessedEvents++; } if (repositoryChanged) { Logger.Trace("RepositoryChanged"); RepositoryChanged?.Invoke(); } processingEvents = false; signalProcessingEventsDone.Set(); return(lastCountOfProcessedEvents); }
private void WatcherLoop() { Logger.Trace("Starting watcher"); while (running) { if (cancellationToken.IsCancellationRequested) { Stop(); break; } var fileEvents = nativeInterface.GetEvents(); if (fileEvents.Any()) { Logger.Trace("Processing {0} Events", fileEvents.Length); } var repositoryChanged = false; foreach (var fileEvent in fileEvents) { if (!running) { break; } if (cancellationToken.IsCancellationRequested) { Stop(); break; } //Logger.Trace(fileEvent.Describe()); var eventDirectory = new NPath(fileEvent.Directory); var fileA = eventDirectory.Combine(fileEvent.FileA); NPath fileB = null; if (fileEvent.FileB != null) { fileB = eventDirectory.Combine(fileEvent.FileB); } // handling events in .git/* if (fileA.IsChildOf(paths.DotGitPath)) { HandleEventInDotGit(fileEvent, fileA, fileB); } else { if (repositoryChanged || ignoredPaths.Any(ignoredPath => fileA.IsChildOf(ignoredPath))) { continue; } repositoryChanged = true; } } if (repositoryChanged) { Logger.Trace("RepositoryChanged"); RepositoryChanged?.Invoke(); } if (pauseEvent.Wait(200)) { break; } } }