the mac file watcher gets a list of changed paths

this change does propagate the complete list of changes
This commit is contained in:
Markus Stoll 2014-10-21 14:21:03 +02:00
parent a11a5a928a
commit b97643c161
3 changed files with 89 additions and 29 deletions

View file

@ -25,6 +25,7 @@ using MonoMac.AppKit;
using Mono.Unix.Native;
using SparkleLib;
using System.Collections.Generic;
namespace SparkleShare {
@ -58,22 +59,50 @@ namespace SparkleShare {
SparkleRepoBase.UseCustomWatcher = true;
this.watcher = new SparkleMacWatcher (Program.Controller.FoldersPath);
this.watcher.Changed += delegate (string path) {
FileSystemEventArgs fse_args = new FileSystemEventArgs (WatcherChangeTypes.Changed, path, "Unknown_File");
FileActivityTask [] tasks = new FileActivityTask [Repositories.Length];
// FIXME: There are cases where the wrong repo is triggered, so
// we trigger all of them for now. Causes only slightly more overhead
int i = 0;
foreach (SparkleRepoBase repo in Repositories) {
tasks [i] = MacActivityTask (repo, fse_args);
tasks [i] ();
i++;
}
};
this.watcher.Changed += OnFilesChanged;
}
private void OnFilesChanged(List<string> changedFilesInBasedir)
{
Dictionary<SparkleRepoBase, List<string>> changeDict = new Dictionary<SparkleRepoBase, List<string>> ();
foreach (string file in changedFilesInBasedir) {
string repo_name;
int pathSepIndex = file.IndexOf (Path.DirectorySeparatorChar);
if (pathSepIndex >= 0)
repo_name = file.Substring (0, pathSepIndex);
else
repo_name = file;
repo_name = Path.GetFileNameWithoutExtension (repo_name);
SparkleRepoBase repo = GetRepositoryByName (repo_name);
if (repo == null)
continue;
List<string> changes;
if (changeDict.ContainsKey (repo))
changes = changeDict [repo];
else {
changes = new List<string> ();
changeDict.Add (repo, changes);
}
changes.Add (Path.Combine (SparkleConfig.DefaultConfig.FoldersPath, file));
}
foreach (SparkleRepoBase repo in changeDict.Keys) {
foreach (string file in changeDict[repo]) {
FileActivityTask task = MacActivityTask (
repo,
new FileSystemEventArgs(WatcherChangeTypes.Changed, file, "unknown")
);
task ();
}
}
}
private delegate void FileActivityTask ();

View file

@ -40,10 +40,10 @@ namespace SparkleShare {
public sealed class SparkleMacWatcher : IDisposable {
public delegate void ChangedEventHandler (string path);
public delegate void ChangedEventHandler (List<string> path);
public event ChangedEventHandler Changed;
public string Path { get; private set; }
public string BasePath { get; private set; }
[Flags]
@ -74,7 +74,7 @@ namespace SparkleShare {
public SparkleMacWatcher (string path)
{
Path = path;
BasePath = path;
m_callback = DoCallback;
NSString [] s = new NSString [1];
@ -151,14 +151,19 @@ namespace SparkleShare {
var handler = Changed;
if (handler != null) {
if (paths [0].Length >= Path.Length) {
string path = paths [0];
path = path.Substring (Path.Length);
path = path.Trim ("/".ToCharArray ());
List<string> filteredPaths = new List<string> ();
foreach (var path in paths) {
if (path.Length > BasePath.Length) {
var t = path.Substring (BasePath.Length);
t = t.Trim ("/".ToCharArray ());
if (!string.IsNullOrWhiteSpace (path))
handler (path);
if (!string.IsNullOrWhiteSpace (t))
filteredPaths.Add(t);
}
}
if(filteredPaths.Count > 0)
handler (filteredPaths);
}
GC.KeepAlive (this);

View file

@ -30,10 +30,36 @@ namespace SparkleShare {
public SparkleRepoBase [] Repositories {
get {
lock (this.repo_lock)
return this.repositories.GetRange (0, this.repositories.Count).ToArray ();
return this.sortedRepositories.GetRange (0, this.sortedRepositories.Count).ToArray ();
}
}
private void AddRepository(SparkleRepoBase repo)
{
lock (this.repo_lock) {
sortedRepositories.Add (repo);
repositoryDict.Add (repo.Name, repo);
sortedRepositories.Sort ((x, y) => string.Compare (x.Name, y.Name));
}
}
private void RemoveRepository(SparkleRepoBase repo)
{
lock (this.repo_lock) {
sortedRepositories.Remove (repo);
repositoryDict.Remove (repo.Name);
}
}
public SparkleRepoBase GetRepositoryByName(string name)
{
lock (this.repo_lock) {
if(repositoryDict.ContainsKey(name))
return repositoryDict [name];
return null;
}
}
public SparkleConfig Config { get; private set; }
public bool RepositoriesLoaded { get; private set; }
@ -155,7 +181,8 @@ namespace SparkleShare {
private FileSystemWatcher watcher;
private Object repo_lock = new Object ();
private Object check_repos_lock = new Object ();
private List<SparkleRepoBase> repositories = new List<SparkleRepoBase> ();
private List<SparkleRepoBase> sortedRepositories = new List<SparkleRepoBase> ();
private Dictionary<string, SparkleRepoBase> repositoryDict = new Dictionary<string, SparkleRepoBase> ();
private bool lost_folders_path = false;
@ -464,17 +491,16 @@ namespace SparkleShare {
"Local and server versions were kept.");
};
this.repositories.Add (repo);
this.repositories.Sort ((x, y) => string.Compare (x.Name, y.Name));
AddRepository (repo);
repo.Initialize ();
}
private void RemoveRepository (string folder_path)
{
foreach (SparkleRepoBase repo in this.repositories) {
foreach (SparkleRepoBase repo in this.sortedRepositories) {
if (repo.LocalPath.Equals (folder_path)) {
this.repositories.Remove (repo);
RemoveRepository (repo);
repo.Dispose ();
return;
}