diff --git a/SparkleLib/Git/SparkleFetcherGit.cs b/SparkleLib/Git/SparkleFetcherGit.cs
index 889937c8..5f3d0a10 100755
--- a/SparkleLib/Git/SparkleFetcherGit.cs
+++ b/SparkleLib/Git/SparkleFetcherGit.cs
@@ -30,12 +30,13 @@ namespace SparkleLib.Git {
public class SparkleFetcher : SparkleFetcherBase {
private SparkleGit git;
+ private bool use_git_bin;
private string crypto_salt = "e0d592768d7cf99a"; // TODO: Make unique per repo
public SparkleFetcher (string server, string required_fingerprint, string remote_path,
- string target_folder, bool fetch_prior_history) : base (server, required_fingerprint, remote_path,
- target_folder, fetch_prior_history)
+ string target_folder, bool fetch_prior_history) : base (server, required_fingerprint,
+ remote_path, target_folder, fetch_prior_history)
{
Uri uri = RemoteUrl;
@@ -60,6 +61,9 @@ namespace SparkleLib.Git {
} else if (uri.Host.Equals ("github.com")) {
uri = new Uri ("ssh://git@github.com" + uri.AbsolutePath);
+ } else if (uri.Host.Equals ("bitbucket.org")) {
+ // Nothing really
+
} else if (uri.Host.Equals ("gnome.org")) {
uri = new Uri ("ssh://git@gnome.org/git" + uri.AbsolutePath);
@@ -73,6 +77,8 @@ namespace SparkleLib.Git {
else
uri = new Uri (uri.Scheme + "://git@" + uri.Host + ":" + uri.Port + uri.AbsolutePath);
}
+
+ this.use_git_bin = true;
}
TargetFolder = target_folder;
@@ -128,14 +134,21 @@ namespace SparkleLib.Git {
} else {
SparkleHelpers.DebugInfo ("Fetcher", line);
- if (line.StartsWith ("fatal:", true, null) ||
- line.StartsWith ("error:", true, null)) {
+ line = line.Trim (new char [] {' ', '@'});
+
+ if (line.StartsWith ("fatal:", StringComparison.InvariantCultureIgnoreCase) ||
+ line.StartsWith ("error:", StringComparison.InvariantCultureIgnoreCase)) {
base.errors.Add (line);
+
+ } else if (line.StartsWith ("WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!")) {
+ base.errors.Add ("warning: Remote host identification has changed!");
+
+ } else if (line.StartsWith ("WARNING: POSSIBLE DNS SPOOFING DETECTED!")) {
+ base.errors.Add ("warning: Possible DNS spoofing detected!");
}
}
-
if (number >= percentage) {
percentage = number;
@@ -148,8 +161,6 @@ namespace SparkleLib.Git {
this.git.WaitForExit ();
- SparkleHelpers.DebugInfo ("Git", "Exit code: " + this.git.ExitCode);
-
if (this.git.ExitCode == 0) {
while (percentage < 100) {
percentage += 25;
@@ -165,6 +176,7 @@ namespace SparkleLib.Git {
InstallConfiguration ();
InstallExcludeRules ();
+ InstallAttributeRules ();
AddWarnings ();
@@ -179,11 +191,13 @@ namespace SparkleLib.Git {
public override bool IsFetchedRepoEmpty {
get {
SparkleGit git = new SparkleGit (TargetFolder, "rev-parse HEAD");
+ git.StartInfo.RedirectStandardError = true;
git.Start ();
// Reading the standard output HAS to go before
// WaitForExit, or it will hang forever on output > 4096 bytes
git.StandardOutput.ReadToEnd ();
+ git.StandardError.ReadToEnd ();
git.WaitForExit ();
return (git.ExitCode != 0);
@@ -210,7 +224,7 @@ namespace SparkleLib.Git {
string git_attributes_file_path = SparkleHelpers.CombineMore (
TargetFolder, ".git", "info", "attributes");
- File.WriteAllText (git_attributes_file_path, "* filter=crypto");
+ File.AppendAllText (git_attributes_file_path, "\n* filter=crypto");
// Store the password
@@ -285,158 +299,99 @@ namespace SparkleLib.Git {
public override void Complete ()
{
- if (IsFetchedRepoEmpty)
- return;
+ if (!IsFetchedRepoEmpty) {
+ SparkleGit git = new SparkleGit (TargetFolder, "checkout --quiet HEAD");
+ git.Start ();
+ git.WaitForExit ();
+ }
- SparkleGit git = new SparkleGit (TargetFolder, "checkout --quiet HEAD");
- git.Start ();
- git.WaitForExit ();
+ base.Complete ();
}
- // Install the user's name and email and some config into
- // the newly cloned repository
private void InstallConfiguration ()
{
- string repo_config_file_path = SparkleHelpers.CombineMore (TargetFolder, ".git", "config");
- string config = File.ReadAllText (repo_config_file_path);
+ string [] settings = new string [] {
+ "core.quotepath false", // Don't quote "unusual" characters in path names
+ "core.ignorecase false", // Be case sensitive explicitly to work on Mac
+ "core.filemode false", // Ignore permission changes
+ "core.autocrlf false", // Don't change file line endings
+ "core.safecrlf false",
+ "core.packedGitLimit 128m", // Some memory limiting options
+ "core.packedGitWindowSize 128m",
+ "pack.deltaCacheSize 128m",
+ "pack.packSizeLimit 128m",
+ "pack.windowMemory 128m"
+ };
- string n = Environment.NewLine;
+ foreach (string setting in settings) {
+ SparkleGit git_config = new SparkleGit (TargetFolder, "config " + setting);
+ git_config.Start ();
+ git_config.WaitForExit ();
+ }
- config = config.Replace ("[core]" + n,
- "[core]" + n +
- "\tquotepath = false" + n + // Show special characters in the logs
- "\tpackedGitLimit = 128m" + n +
- "\tautocrlf = false" + n +
- "\tsafecrlf = false" + n +
- "\tpackedGitWindowSize = 128m" + n);
+ if (this.use_git_bin)
+ InstallGitBinConfiguration ();
+ }
- config = config.Replace ("[remote \"origin\"]" + n,
- "[pack]" + n +
- "\tdeltaCacheSize = 128m" + n +
- "\tpackSizeLimit = 128m" + n +
- "\twindowMemory = 128m" + n +
- "[remote \"origin\"]" + n);
- // Be case sensitive explicitly to work on Mac
- config = config.Replace ("ignorecase = true", "ignorecase = false");
+ public void InstallGitBinConfiguration ()
+ {
+ string [] settings = new string [] {
+ "core.bigFileThreshold 8g",
+ "filter.bin.clean \"git bin clean %f\"",
+ "filter.bin.smudge \"git bin smudge\"",
+ "git-bin.chunkSize 1m",
+ "git-bin.s3bucket \"your bucket name\"",
+ "git-bin.s3key \"your key\"",
+ "git-bin.s3secretKey \"your secret key\""
+ };
- // Ignore permission changes
- config = config.Replace ("filemode = true", "filemode = false");
-
- // Write the config to the file
- File.WriteAllText (repo_config_file_path, config);
- SparkleHelpers.DebugInfo ("Fetcher", "Added configuration to '" + repo_config_file_path + "'");
+ foreach (string setting in settings) {
+ SparkleGit git_config = new SparkleGit (TargetFolder, "config " + setting);
+ git_config.Start ();
+ git_config.WaitForExit ();
+ }
}
// Add a .gitignore file to the repo
private void InstallExcludeRules ()
{
- DirectoryInfo info = Directory.CreateDirectory (
- SparkleHelpers.CombineMore (TargetFolder, ".git", "info"));
-
- // File that lists the files we want git to ignore
- string exclude_rules_file_path = Path.Combine (info.FullName, "exclude");
+ // Compile a list of files we want Git to ignore
+ string exclude_rules_file_path = SparkleHelpers.CombineMore (TargetFolder, ".git", "info", "exclude");
TextWriter writer = new StreamWriter (exclude_rules_file_path);
foreach (string exclude_rule in ExcludeRules)
writer.WriteLine (exclude_rule);
writer.Close ();
+ }
- // File that lists the files we want don't want git to compress.
- // Not compressing the already compressed files saves us memory
- // usage and increases speed
- string no_compression_rules_file_path = Path.Combine (info.FullName, "attributes");
- writer = new StreamWriter (no_compression_rules_file_path);
+ private void InstallAttributeRules ()
+ {
+ string attribute_rules_file_path = SparkleHelpers.CombineMore (TargetFolder, ".git", "info", "attributes");
+ TextWriter writer = new StreamWriter (attribute_rules_file_path);
- // Images
- writer.WriteLine ("*.jpg -delta");
- writer.WriteLine ("*.jpeg -delta");
- writer.WriteLine ("*.JPG -delta");
- writer.WriteLine ("*.JPEG -delta");
+ if (this.use_git_bin) {
+ writer.WriteLine ("* filter=bin binary");
- writer.WriteLine ("*.png -delta");
- writer.WriteLine ("*.PNG -delta");
+ } else {
+ // Compile a list of files we don't want Git to compress.
+ // Not compressing already compressed files decreases memory usage and increases speed
+ string [] extensions = new string [] {
+ "jpg", "jpeg", "png", "tiff", "gif", // Images
+ "flac", "mp3", "ogg", "oga", // Audio
+ "avi", "mov", "mpg", "mpeg", "mkv", "ogv", "ogx", "webm", // Video
+ "zip", "gz", "bz", "bz2", "rpm", "deb", "tgz", "rar", "ace", "7z", "pak", "tar" // Archives
+ };
- writer.WriteLine ("*.tiff -delta");
- writer.WriteLine ("*.TIFF -delta");
-
- // Audio
- writer.WriteLine ("*.flac -delta");
- writer.WriteLine ("*.FLAC -delta");
-
- writer.WriteLine ("*.mp3 -delta");
- writer.WriteLine ("*.MP3 -delta");
-
- writer.WriteLine ("*.ogg -delta");
- writer.WriteLine ("*.OGG -delta");
-
- writer.WriteLine ("*.oga -delta");
- writer.WriteLine ("*.OGA -delta");
-
- // Video
- writer.WriteLine ("*.avi -delta");
- writer.WriteLine ("*.AVI -delta");
-
- writer.WriteLine ("*.mov -delta");
- writer.WriteLine ("*.MOV -delta");
-
- writer.WriteLine ("*.mpg -delta");
- writer.WriteLine ("*.MPG -delta");
- writer.WriteLine ("*.mpeg -delta");
- writer.WriteLine ("*.MPEG -delta");
-
- writer.WriteLine ("*.mkv -delta");
- writer.WriteLine ("*.MKV -delta");
-
- writer.WriteLine ("*.ogv -delta");
- writer.WriteLine ("*.OGV -delta");
-
- writer.WriteLine ("*.ogx -delta");
- writer.WriteLine ("*.OGX -delta");
-
- writer.WriteLine ("*.webm -delta");
- writer.WriteLine ("*.WEBM -delta");
-
- // Archives
- writer.WriteLine ("*.zip -delta");
- writer.WriteLine ("*.ZIP -delta");
-
- writer.WriteLine ("*.gz -delta");
- writer.WriteLine ("*.GZ -delta");
-
- writer.WriteLine ("*.bz -delta");
- writer.WriteLine ("*.BZ -delta");
-
- writer.WriteLine ("*.bz2 -delta");
- writer.WriteLine ("*.BZ2 -delta");
-
- writer.WriteLine ("*.rpm -delta");
- writer.WriteLine ("*.RPM -delta");
-
- writer.WriteLine ("*.deb -delta");
- writer.WriteLine ("*.DEB -delta");
-
- writer.WriteLine ("*.tgz -delta");
- writer.WriteLine ("*.TGZ -delta");
-
- writer.WriteLine ("*.rar -delta");
- writer.WriteLine ("*.RAR -delta");
-
- writer.WriteLine ("*.ace -delta");
- writer.WriteLine ("*.ACE -delta");
-
- writer.WriteLine ("*.7z -delta");
- writer.WriteLine ("*.7Z -delta");
-
- writer.WriteLine ("*.pak -delta");
- writer.WriteLine ("*.PAK -delta");
-
- writer.WriteLine ("*.tar -delta");
- writer.WriteLine ("*.TAR -delta");
+ foreach (string extension in extensions) {
+ writer.WriteLine ("*." + extension + " -delta");
+ writer.WriteLine ("*." + extension.ToUpper () + " -delta");
+ }
+ }
writer.Close ();
}
diff --git a/SparkleLib/Git/SparkleGit.cs b/SparkleLib/Git/SparkleGit.cs
index 7e13a46e..a95972a9 100644
--- a/SparkleLib/Git/SparkleGit.cs
+++ b/SparkleLib/Git/SparkleGit.cs
@@ -22,18 +22,61 @@ using SparkleLib;
namespace SparkleLib.Git {
- public class SparkleGit : Process {
+ public abstract class SparkleProcess : Process {
- public static string ExecPath = null;
- public static string Path = null;
-
-
- public SparkleGit (string path, string args) : base ()
+ public SparkleProcess (string path, string args) : base ()
{
- Path = LocateGit ();
+ StartInfo.FileName = path;
+ StartInfo.Arguments = args;
+ }
+
+
+ new public void Start ()
+ {
+ SparkleHelpers.DebugInfo ("Cmd | " + System.IO.Path.GetFileName (StartInfo.WorkingDirectory),
+ System.IO.Path.GetFileName (StartInfo.FileName) + " " + StartInfo.Arguments);
+
+ try {
+ base.Start ();
+
+ } catch (Exception e) {
+ SparkleHelpers.DebugInfo ("Cmd", "Couldn't execute command: " + e.Message);
+ Environment.Exit (-1);
+ }
+ }
+
+
+ protected string LocateCommand (string name)
+ {
+ string [] possible_command_paths = new string [] {
+ "/usr/bin/" + name,
+ "/usr/local/bin/" + name,
+ "/opt/local/bin/" + name
+ };
+
+ foreach (string path in possible_command_paths) {
+ if (File.Exists (path))
+ return path;
+ }
+
+ return name;
+ }
+ }
+
+
+ public class SparkleGit : SparkleProcess {
+
+ public static string ExecPath;
+ public static string GitPath;
+
+
+ public SparkleGit (string path, string args) : base (path, args)
+ {
+ if (string.IsNullOrEmpty (GitPath))
+ GitPath = LocateCommand ("git");
EnableRaisingEvents = true;
- StartInfo.FileName = Path;
+ StartInfo.FileName = GitPath;
StartInfo.RedirectStandardOutput = true;
StartInfo.UseShellExecute = false;
StartInfo.WorkingDirectory = path;
@@ -44,40 +87,26 @@ namespace SparkleLib.Git {
else
StartInfo.Arguments = "--exec-path=\"" + ExecPath + "\" " + args;
}
+ }
- new public void Start ()
+ public class SparkleGitBin : SparkleProcess {
+
+ public static string GitBinPath;
+
+
+ public SparkleGitBin (string path, string args) : base (path, args)
{
- SparkleHelpers.DebugInfo ("Cmd | " + System.IO.Path.GetFileName (StartInfo.WorkingDirectory),
- "git " + StartInfo.Arguments);
+ if (string.IsNullOrEmpty (GitBinPath))
+ GitBinPath = LocateCommand ("git-bin");
- try {
- base.Start ();
-
- } catch (Exception e) {
- SparkleHelpers.DebugInfo ("Cmd", "There's a problem running Git: " + e.Message);
- Environment.Exit (-1);
- }
- }
-
-
- private string LocateGit ()
- {
- if (!string.IsNullOrEmpty (Path))
- return Path;
-
- string [] possible_git_paths = new string [] {
- "/usr/bin/git",
- "/usr/local/bin/git",
- "/opt/local/bin/git",
- "/usr/local/git/bin/git"
- };
-
- foreach (string path in possible_git_paths)
- if (File.Exists (path))
- return path;
-
- return "git";
+ EnableRaisingEvents = true;
+ StartInfo.FileName = GitBinPath;
+ StartInfo.RedirectStandardOutput = true;
+ StartInfo.UseShellExecute = false;
+ StartInfo.WorkingDirectory = path;
+ StartInfo.CreateNoWindow = true;
+ StartInfo.Arguments = args;
}
}
}
diff --git a/SparkleLib/Git/SparkleRepoGit.cs b/SparkleLib/Git/SparkleRepoGit.cs
index a4fe379c..0adff153 100644
--- a/SparkleLib/Git/SparkleRepoGit.cs
+++ b/SparkleLib/Git/SparkleRepoGit.cs
@@ -27,11 +27,18 @@ namespace SparkleLib.Git {
public class SparkleRepo : SparkleRepoBase {
- private bool author_set = false;
+ private bool user_is_set;
+ private bool remote_url_is_set;
+ private bool use_git_bin;
public SparkleRepo (string path) : base (path)
{
+ SparkleGit git = new SparkleGit (LocalPath, "config --get filter.bin.clean");
+ git.Start ();
+ git.WaitForExit ();
+
+ this.use_git_bin = (git.ExitCode == 0);
}
@@ -84,14 +91,7 @@ namespace SparkleLib.Git {
File.WriteAllText (size_file_path, size.ToString ());
File.WriteAllText (history_size_file_path, history_size.ToString ());
}
-
-
- public override void CreateInitialChangeSet ()
- {
- base.CreateInitialChangeSet ();
- SyncUp (); // FIXME: Weird freeze happens when base class handles this
- }
-
+
public override string [] UnsyncedFilePaths {
get {
@@ -152,7 +152,7 @@ namespace SparkleLib.Git {
SparkleHelpers.DebugInfo ("Git", Name + " | Checking for remote changes...");
string current_revision = CurrentRevision;
- SparkleGit git = new SparkleGit (LocalPath, "ls-remote --exit-code \"" + RemoteUrl + "\" master");
+ SparkleGit git = new SparkleGit (LocalPath, "ls-remote --heads --exit-code \"" + RemoteUrl + "\" master");
git.Start ();
git.WaitForExit ();
@@ -189,7 +189,25 @@ namespace SparkleLib.Git {
Commit (message);
}
- SparkleGit git = new SparkleGit (LocalPath,
+ SparkleGit git;
+
+ if (this.use_git_bin) {
+ if (this.remote_url_is_set) {
+ git = new SparkleGit (LocalPath, "config remote.origin.url \"" + RemoteUrl + "\"");
+ git.Start ();
+ git.WaitForExit ();
+
+ this.remote_url_is_set = true;
+ }
+
+ SparkleGitBin git_bin = new SparkleGitBin (LocalPath, "push");
+ git_bin.Start ();
+ git_bin.WaitForExit ();
+
+ // TODO: Progress
+ }
+
+ git = new SparkleGit (LocalPath,
"push --progress " + // Redirects progress stats to standarderror
"\"" + RemoteUrl + "\" master");
@@ -249,10 +267,13 @@ namespace SparkleLib.Git {
UpdateSizes ();
ChangeSets = GetChangeSets ();
- if (git.ExitCode == 0)
+ if (git.ExitCode == 0) {
+ ClearCache ();
return true;
- else
+
+ } else {
return false;
+ }
}
@@ -319,6 +340,7 @@ namespace SparkleLib.Git {
);
ChangeSets = GetChangeSets ();
+ ClearCache ();
return true;
@@ -383,7 +405,7 @@ namespace SparkleLib.Git {
{
SparkleGit git;
- if (!this.author_set) {
+ if (!this.user_is_set) {
git = new SparkleGit (LocalPath,
"config user.name \"" + SparkleConfig.DefaultConfig.User.Name + "\"");
@@ -396,7 +418,7 @@ namespace SparkleLib.Git {
git.Start ();
git.WaitForExit ();
- this.author_set = true;
+ this.user_is_set = true;
}
git = new SparkleGit (LocalPath,
@@ -760,11 +782,6 @@ namespace SparkleLib.Git {
}
- ///
- /// Resolves special characters like \303\244 (รค) to their real character
- ///
- ///
- ///
private string ResolveSpecialChars (string s)
{
StringBuilder builder = new StringBuilder (s.Length);
@@ -793,6 +810,17 @@ namespace SparkleLib.Git {
}
+ private void ClearCache ()
+ {
+ if (!this.use_git_bin)
+ return;
+
+ SparkleGitBin git_bin = new SparkleGitBin (LocalPath, "clear -f");
+ git_bin.Start ();
+ git_bin.WaitForExit ();
+ }
+
+
// Git doesn't track empty directories, so this method
// fills them all with a hidden empty file.
//
diff --git a/SparkleLib/SparkleConfig.cs b/SparkleLib/SparkleConfig.cs
index 71bc275c..6cbcc3f8 100755
--- a/SparkleLib/SparkleConfig.cs
+++ b/SparkleLib/SparkleConfig.cs
@@ -210,11 +210,14 @@ namespace SparkleLib {
}
- public void AddFolder (string name, string url, string backend)
+ public void AddFolder (string name, string identifier, string url, string backend)
{
XmlNode node_name = CreateElement ("name");
node_name.InnerText = name;
+ XmlNode node_identifier = CreateElement ("identifier");
+ node_identifier.InnerText = identifier;
+
XmlNode node_url = CreateElement ("url");
node_url.InnerText = url;
@@ -223,6 +226,7 @@ namespace SparkleLib {
XmlNode node_folder = CreateNode (XmlNodeType.Element, "folder", null);
node_folder.AppendChild (node_name);
+ node_folder.AppendChild (node_identifier);
node_folder.AppendChild (node_url);
node_folder.AppendChild (node_backend);
@@ -244,18 +248,44 @@ namespace SparkleLib {
}
+ public void RenameFolder (string identifier, string name)
+ {
+ XmlNode node_folder = SelectSingleNode (string.Format ("/sparkleshare/folder[identifier=\"{0}\"]", identifier));
+ node_folder ["name"].InnerText = name;
+
+ Save ();
+ }
+
+
public string GetBackendForFolder (string name)
{
return GetFolderValue (name, "backend");
}
+ public string GetIdentifierForFolder (string name)
+ {
+ return GetFolderValue (name, "identifier");
+ }
+
+
public string GetUrlForFolder (string name)
{
return GetFolderValue (name, "url");
}
+ public bool IdentifierExists (string identifier)
+ {
+ foreach (XmlNode node_folder in SelectNodes ("/sparkleshare/folder")) {
+ if (node_folder ["identifier"].InnerText.Equals (identifier))
+ return true;
+ }
+
+ return false;
+ }
+
+
public bool SetFolderOptionalAttribute (string folder_name, string key, string value)
{
XmlNode folder = GetFolder (folder_name);
@@ -304,11 +334,10 @@ namespace SparkleLib {
{
XmlNode folder = GetFolder(name);
- if ((folder != null) && (folder [key] != null)) {
+ if ((folder != null) && (folder [key] != null))
return folder [key].InnerText;
- }
-
- return null;
+ else
+ return null;
}
diff --git a/SparkleLib/SparkleFetcherBase.cs b/SparkleLib/SparkleFetcherBase.cs
index 440c0e44..1d436f00 100755
--- a/SparkleLib/SparkleFetcherBase.cs
+++ b/SparkleLib/SparkleFetcherBase.cs
@@ -41,7 +41,6 @@ namespace SparkleLib {
public abstract bool Fetch ();
public abstract void Stop ();
- public abstract void Complete ();
public abstract bool IsFetchedRepoEmpty { get; }
public abstract bool IsFetchedRepoPasswordCorrect (string password);
public abstract void EnableFetchedRepoCrypto (string password);
@@ -51,6 +50,7 @@ namespace SparkleLib {
public readonly bool FetchPriorHistory = false;
public string TargetFolder { get; protected set; }
public bool IsActive { get; private set; }
+ public string Identifier;
public string [] Warnings {
get {
@@ -66,13 +66,34 @@ namespace SparkleLib {
protected List warnings = new List ();
- protected List errors = new List ();
+ protected List errors = new List ();
+
+ protected string [] ExcludeRules = new string [] {
+ "*.autosave", // Various autosaving apps
+ "*~", // gedit and emacs
+ ".~lock.*", // LibreOffice
+ "*.part", "*.crdownload", // Firefox and Chromium temporary download files
+ ".*.sw[a-z]", "*.un~", "*.swp", "*.swo", // vi(m)
+ ".directory", // KDE
+ ".DS_Store", "Icon\r\r", "._*", ".Spotlight-V100", ".Trashes", // Mac OS X
+ "*(Autosaved).graffle", // Omnigraffle
+ "Thumbs.db", "Desktop.ini", // Windows
+ "~*.tmp", "~*.TMP", "*~*.tmp", "*~*.TMP", // MS Office
+ "~*.ppt", "~*.PPT", "~*.pptx", "~*.PPTX",
+ "~*.xls", "~*.XLS", "~*.xlsx", "~*.XLSX",
+ "~*.doc", "~*.DOC", "~*.docx", "~*.DOCX",
+ "*/CVS/*", ".cvsignore", "*/.cvsignore", // CVS
+ "/.svn/*", "*/.svn/*", // Subversion
+ "/.hg/*", "*/.hg/*", "*/.hgignore", // Mercurial
+ "/.bzr/*", "*/.bzr/*", "*/.bzrignore" // Bazaar
+ };
+
private Thread thread;
- public SparkleFetcherBase (string server, string required_fingerprint, string remote_path,
- string target_folder, bool fetch_prior_history)
+ public SparkleFetcherBase (string server, string required_fingerprint,
+ string remote_path, string target_folder, bool fetch_prior_history)
{
RequiredFingerprint = required_fingerprint;
FetchPriorHistory = fetch_prior_history;
@@ -100,12 +121,11 @@ namespace SparkleLib {
if (Started != null)
Started ();
- SparkleHelpers.DebugInfo ("Fetcher", "[" + TargetFolder + "] Fetching folder: " + RemoteUrl);
+ SparkleHelpers.DebugInfo ("Fetcher", TargetFolder + " | Fetching folder: " + RemoteUrl);
if (Directory.Exists (TargetFolder))
Directory.Delete (TargetFolder, true);
-
string host = RemoteUrl.Host;
string host_key = GetHostKey ();
@@ -116,7 +136,6 @@ namespace SparkleLib {
return;
}
-
bool warn = true;
if (RequiredFingerprint != null) {
string host_fingerprint = GetFingerprint (host_key);
@@ -141,35 +160,99 @@ namespace SparkleLib {
AcceptHostKey (host_key, warn);
+ this.thread = new Thread (
+ new ThreadStart (delegate {
+ if (Fetch ()) {
+ Thread.Sleep (500);
+ SparkleHelpers.DebugInfo ("Fetcher", "Finished");
- this.thread = new Thread (new ThreadStart (delegate {
- if (Fetch ()) {
- Thread.Sleep (500);
- SparkleHelpers.DebugInfo ("Fetcher", "Finished");
+ IsActive = false;
- IsActive = false;
+ // TODO: Find better way to determine if folder should have crypto setup
+ bool repo_is_encrypted = RemoteUrl.ToString ().Contains ("crypto");
- // TODO: Find better way to determine if folder should have crypto setup
- bool repo_is_encrypted = RemoteUrl.ToString ().Contains ("crypto");
+ if (Finished != null)
+ Finished (repo_is_encrypted, IsFetchedRepoEmpty, Warnings);
- if (Finished != null)
- Finished (repo_is_encrypted, IsFetchedRepoEmpty, Warnings);
+ } else {
+ Thread.Sleep (500);
+ SparkleHelpers.DebugInfo ("Fetcher", "Failed");
- } else {
- Thread.Sleep (500);
- SparkleHelpers.DebugInfo ("Fetcher", "Failed");
+ IsActive = false;
- IsActive = false;
-
- if (Failed != null)
- Failed ();
- }
- }));
+ if (Failed != null)
+ Failed ();
+ }
+ })
+ );
this.thread.Start ();
}
+ public virtual void Complete ()
+ {
+ string identifier_path = Path.Combine (TargetFolder, ".sparkleshare");
+
+ if (File.Exists (identifier_path)) {
+ Identifier = File.ReadAllText (identifier_path).Trim ();
+
+ } else {
+ Identifier = CreateIdentifier ();
+ File.WriteAllText (identifier_path, Identifier);
+ }
+
+ if (IsFetchedRepoEmpty)
+ CreateInitialChangeSet ();
+ }
+
+
+ // Create an initial change set when the
+ // user has fetched an empty remote folder
+ public void CreateInitialChangeSet ()
+ {
+ string file_path = Path.Combine (TargetFolder, "SparkleShare.txt");
+ string n = Environment.NewLine;
+
+ string text = "Congratulations, you've successfully created a SparkleShare repository!" + n +
+ n +
+ "Any files you add or change in this folder will be automatically synced to " + n +
+ RemoteUrl + " and everyone connected to it." + n +
+ n +
+ "SparkleShare is an Open Source software program that helps people " + n +
+ "collaborate and share files. If you like what we do, please consider a small " + n +
+ "donation to support the project: http://sparkleshare.org/support-us/" + n +
+ n +
+ "Have fun! :)" + n;
+
+ File.WriteAllText (file_path, text);
+ }
+
+
+ public static string CreateIdentifier ()
+ {
+ string random = Path.GetRandomFileName ();
+ return SparkleHelpers.SHA1 (random);
+ }
+
+
+ public static string GetBackend (string path)
+ {
+ string extension = Path.GetExtension (path);
+
+ if (!string.IsNullOrEmpty (extension)) {
+ extension = extension.Substring (1);
+ char [] letters = extension.ToCharArray ();
+ letters [0] = char.ToUpper (letters [0]);
+
+ return new string (letters);
+
+ } else {
+ return "Git";
+ }
+ }
+
+
public void Dispose ()
{
if (this.thread != null) {
@@ -178,7 +261,7 @@ namespace SparkleLib {
}
}
-
+
protected void OnProgressChanged (double percentage) {
if (ProgressChanged != null)
ProgressChanged (percentage);
@@ -199,7 +282,7 @@ namespace SparkleLib {
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
- process.StartInfo.FileName = "ssh-keyscan";
+ process.StartInfo.FileName = "ssh-keyscan";
process.StartInfo.Arguments = "-t rsa " + host;
process.Start ();
@@ -240,7 +323,7 @@ namespace SparkleLib {
// WaitForExit, or it will hang forever on output > 4096 bytes
string fingerprint = process.StandardOutput.ReadToEnd ().Trim ();
process.WaitForExit ();
-
+
File.Delete (tmp_file_path);
try {
@@ -286,98 +369,5 @@ namespace SparkleLib {
if (warn)
this.warnings.Add ("The following host key has been accepted:\n" + GetFingerprint (host_key));
}
-
-
- public static string GetBackend (string path)
- {
- string extension = Path.GetExtension (path);
-
- if (!string.IsNullOrEmpty (extension)) {
- extension = extension.Substring (1);
- char [] letters = extension.ToCharArray ();
- letters [0] = char.ToUpper (letters [0]);
-
- return new string (letters);
-
- } else {
- return "Git";
- }
- }
-
-
- protected string [] ExcludeRules = new string [] {
- // Various autosaving apps
- "*.autosave",
-
- // gedit and emacs
- "*~",
-
- // LibreOffice
- ".~lock.*",
-
- // Firefox and Chromium temporary download files
- "*.part",
- "*.crdownload",
-
- // vi(m)
- ".*.sw[a-z]",
- "*.un~",
- "*.swp",
- "*.swo",
-
- // KDE
- ".directory",
-
- // Mac OS X
- ".DS_Store",
- "Icon\r\r",
- "._*",
- ".Spotlight-V100",
- ".Trashes",
-
- // Omnigraffle
- "*(Autosaved).graffle",
-
- // Windows
- "Thumbs.db",
- "Desktop.ini",
-
- // MS Office
- "~*.tmp",
- "~*.TMP",
- "*~*.tmp",
- "*~*.TMP",
- "~*.ppt",
- "~*.PPT",
- "~*.pptx",
- "~*.PPTX",
- "~*.xls",
- "~*.XLS",
- "~*.xlsx",
- "~*.XLSX",
- "~*.doc",
- "~*.DOC",
- "~*.docx",
- "~*.DOCX",
-
- // CVS
- "*/CVS/*",
- ".cvsignore",
- "*/.cvsignore",
-
- // Subversion
- "/.svn/*",
- "*/.svn/*",
-
- // Mercurial
- "/.hg/*",
- "*/.hg/*",
- "*/.hgignore",
-
- // Bazaar
- "/.bzr/*",
- "*/.bzr/*",
- "*/.bzrignore"
- };
}
}
diff --git a/SparkleLib/SparkleListenerBase.cs b/SparkleLib/SparkleListenerBase.cs
index c7e16b4b..ac7408b4 100755
--- a/SparkleLib/SparkleListenerBase.cs
+++ b/SparkleLib/SparkleListenerBase.cs
@@ -31,8 +31,8 @@ namespace SparkleLib {
public event DisconnectedEventHandler Disconnected;
public delegate void DisconnectedEventHandler ();
- public event ReceivedEventHandler Received;
- public delegate void ReceivedEventHandler (SparkleAnnouncement announcement);
+ public event AnnouncementReceivedEventHandler AnnouncementReceived;
+ public delegate void AnnouncementReceivedEventHandler (SparkleAnnouncement announcement);
public readonly Uri Server;
@@ -175,8 +175,8 @@ namespace SparkleLib {
AddRecentAnnouncement (announcement);
this.queue_down [announcement.FolderIdentifier] = announcement;
- if (Received != null)
- Received (announcement);
+ if (AnnouncementReceived != null)
+ AnnouncementReceived (announcement);
}
diff --git a/SparkleLib/SparkleRepoBase.cs b/SparkleLib/SparkleRepoBase.cs
index fe5d2aa0..42c5ac50 100755
--- a/SparkleLib/SparkleRepoBase.cs
+++ b/SparkleLib/SparkleRepoBase.cs
@@ -83,13 +83,16 @@ namespace SparkleLib {
if (File.Exists (id_path))
this.identifier = File.ReadAllText (id_path).Trim ();
- if (this.identifier != null && this.identifier.Length > 0) {
+ if (!string.IsNullOrEmpty (this.identifier)) {
return this.identifier;
} else {
- Random random = new Random ();
- string number = "" + random.Next () + "" + random.Next () + "" + random.Next ();
- this.identifier = SparkleHelpers.SHA1 (number);
+ string config_identifier = SparkleConfig.DefaultConfig.GetIdentifierForFolder (Name);
+
+ if (!string.IsNullOrEmpty (config_identifier))
+ this.identifier = config_identifier;
+ else
+ this.identifier = SparkleFetcherBase.CreateIdentifier ();
File.WriteAllText (id_path, this.identifier);
File.SetAttributes (id_path, FileAttributes.Hidden);
@@ -148,9 +151,6 @@ namespace SparkleLib {
this.identifier = Identifier;
- if (CurrentRevision == null)
- CreateInitialChangeSet ();
-
ChangeSets = GetChangeSets ();
this.watcher = CreateWatcher ();
@@ -194,28 +194,6 @@ namespace SparkleLib {
}
- // Create an initial change set when the
- // user has fetched an empty remote folder
- public virtual void CreateInitialChangeSet ()
- {
- string file_path = Path.Combine (LocalPath, "SparkleShare.txt");
- string n = Environment.NewLine;
-
- File.WriteAllText (file_path,
- "Congratulations, you've successfully created a SparkleShare repository!" + n +
- "" + n +
- "Any files you add or change in this folder will be automatically synced to " + n +
- RemoteUrl + " and everyone connected to it." + n +
- "" + n +
- "SparkleShare is an Open Source software program that helps people " + n +
- "collaborate and share files. If you like what we do, please consider a small " + n +
- "donation to support the project: http://sparkleshare.org/support-us/" + n +
- "" + n +
- "Have fun! :)" + n
- );
- }
-
-
public List GetChangeSets () {
return GetChangeSets (30);
}
@@ -427,52 +405,15 @@ namespace SparkleLib {
new Thread (
new ThreadStart (delegate {
- if (!is_syncing && HasRemoteChanges)
+ if (!is_syncing && !HasLocalChanges && HasRemoteChanges)
SyncDownBase ();
})
).Start ();
}
- // Stop polling when the connection to the irc channel is succesful
- this.listener.Connected += delegate {
- this.poll_interval = PollInterval.Long;
- this.last_poll = DateTime.Now;
-
- if (!is_syncing) {
- // Check for changes manually one more time
- if (HasRemoteChanges)
- SyncDownBase ();
-
- // Push changes that were made since the last disconnect
- if (HasUnsyncedChanges)
- SyncUpBase ();
- }
- };
-
- // Start polling when the connection to the channel is lost
- this.listener.Disconnected += delegate {
- this.poll_interval = PollInterval.Short;
- SparkleHelpers.DebugInfo (Name, "Falling back to polling");
- };
-
- // Fetch changes when there is a message in the irc channel
- this.listener.Received += delegate (SparkleAnnouncement announcement) {
- string identifier = Identifier;
-
- if (announcement.FolderIdentifier.Equals (identifier) &&
- !announcement.Message.Equals (CurrentRevision)) {
-
- while (this.is_syncing)
- System.Threading.Thread.Sleep (100);
-
- SparkleHelpers.DebugInfo ("Listener", "Syncing due to announcement");
- SyncDownBase ();
-
- } else {
- if (announcement.FolderIdentifier.Equals (identifier))
- SparkleHelpers.DebugInfo ("Listener", "Not syncing, message is for current revision");
- }
- };
+ this.listener.Connected += ListenerConnectedDelegate;
+ this.listener.Disconnected += ListenerDisconnectedDelegate;
+ this.listener.AnnouncementReceived += ListenerAnnouncementReceivedDelegate;
// Start listening
if (!this.listener.IsConnected && !this.listener.IsConnecting)
@@ -480,6 +421,53 @@ namespace SparkleLib {
}
+ // Stop polling when the connection to the irc channel is succesful
+ private void ListenerConnectedDelegate ()
+ {
+ this.poll_interval = PollInterval.Long;
+ this.last_poll = DateTime.Now;
+
+ if (!is_syncing) {
+ // Check for changes manually one more time
+ if (HasRemoteChanges)
+ SyncDownBase ();
+
+ // Push changes that were made since the last disconnect
+ if (HasUnsyncedChanges)
+ SyncUpBase ();
+ }
+ }
+
+
+ // Start polling when the connection to the channel is lost
+ private void ListenerDisconnectedDelegate ()
+ {
+ this.poll_interval = PollInterval.Short;
+ SparkleHelpers.DebugInfo (Name, "Falling back to polling");
+ }
+
+
+ // Fetch changes when there is an announcement
+ private void ListenerAnnouncementReceivedDelegate (SparkleAnnouncement announcement)
+ {
+ string identifier = Identifier;
+
+ if (announcement.FolderIdentifier.Equals (identifier) &&
+ !announcement.Message.Equals (CurrentRevision)) {
+
+ while (this.is_syncing)
+ System.Threading.Thread.Sleep (100);
+
+ SparkleHelpers.DebugInfo ("Listener", "Syncing due to announcement");
+ SyncDownBase ();
+
+ } else {
+ if (announcement.FolderIdentifier.Equals (identifier))
+ SparkleHelpers.DebugInfo ("Listener", "Not syncing, message is for current revision");
+ }
+ }
+
+
private DateTime progress_last_change = DateTime.Now;
private TimeSpan progress_change_interval = new TimeSpan (0, 0, 0, 1);
@@ -535,8 +523,15 @@ namespace SparkleLib {
public void Dispose ()
{
+ this.remote_timer.Stop ();
this.remote_timer.Dispose ();
+
+ this.listener.Connected -= ListenerConnectedDelegate;
+ this.listener.Disconnected -= ListenerDisconnectedDelegate;
+ this.listener.AnnouncementReceived -= ListenerAnnouncementReceivedDelegate;
+
this.listener.Dispose ();
+ this.watcher.Dispose ();
}
}
}
diff --git a/SparkleLib/SparkleWatcherFactory.cs b/SparkleLib/SparkleWatcherFactory.cs
new file mode 100644
index 00000000..94606363
--- /dev/null
+++ b/SparkleLib/SparkleWatcherFactory.cs
@@ -0,0 +1,50 @@
+// SparkleShare, a collaboration and sharing tool.
+// Copyright (C) 2010 Hylke Bons
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace SparkleLib {
+
+ public static class SparkleListenerFactory {
+
+ private static List watchers = new List ();
+
+
+ public static SparkleWatcher CreateWatcher (string path_to_watch)
+ {
+ path_to_watch = Path.GetDirectoryName (path_to_watch);
+
+ foreach (SparkleWatcher watcher in watchers) {
+ if (watcher.Path.Equals (path_to_watch)) {
+ SparkleHelpers.DebugInfo ("WatcherFactory",
+ "Refered to existing watcher for " + path_to_watch);
+
+ return watcher;
+ }
+ }
+
+ watchers.Add (new SparkleWatcher (path_to_watch));
+
+ SparkleHelpers.DebugInfo ("WatcherFactory",
+ "Issued new watcher for " + path_to_watch);
+
+ return watchers [watchers.Count - 1];
+ }
+ }
+}
diff --git a/SparkleShare/Mac/SparkleController.cs b/SparkleShare/Mac/SparkleController.cs
index de0d5fec..2a3ffc79 100755
--- a/SparkleShare/Mac/SparkleController.cs
+++ b/SparkleShare/Mac/SparkleController.cs
@@ -56,7 +56,7 @@ namespace SparkleShare {
// Let's use the bundled git first
- SparkleLib.Git.SparkleGit.Path =
+ SparkleLib.Git.SparkleGit.GitPath =
Path.Combine (NSBundle.MainBundle.ResourcePath,
"git", "libexec", "git-core", "git");
diff --git a/SparkleShare/SparkleControllerBase.cs b/SparkleShare/SparkleControllerBase.cs
index e02bf021..19985933 100644
--- a/SparkleShare/SparkleControllerBase.cs
+++ b/SparkleShare/SparkleControllerBase.cs
@@ -34,12 +34,8 @@ namespace SparkleShare {
public SparkleRepoBase [] Repositories {
get {
- lock (this.repo_lock) {
- SparkleRepoBase [] repositories =
- this.repositories.GetRange (0, this.repositories.Count).ToArray ();
-
- return repositories;
- }
+ lock (this.repo_lock)
+ return this.repositories.GetRange (0, this.repositories.Count).ToArray ();
}
}
@@ -170,8 +166,8 @@ namespace SparkleShare {
private SparkleFetcherBase fetcher;
- private Object repo_lock = new Object ();
- private Object delete_watcher_lock = new Object ();
+ private Object repo_lock = new Object ();
+ private Object check_repos_lock = new Object ();
// Short alias for the translations
@@ -186,6 +182,113 @@ namespace SparkleShare {
}
+ public void HandleInvite (FileSystemEventArgs args)
+ {
+ if (this.fetcher != null &&
+ this.fetcher.IsActive) {
+
+ if (AlertNotificationRaised != null)
+ AlertNotificationRaised ("SparkleShare Setup seems busy",
+ "Please wait for it to finish");
+
+ } else {
+ if (InviteReceived != null) {
+ SparkleInvite invite = new SparkleInvite (args.FullPath);
+
+ // It may be that the invite we received a path to isn't
+ // fully downloaded yet, so we try to read it several times
+ int tries = 0;
+ while (!invite.IsValid) {
+ Thread.Sleep (1 * 250);
+ invite = new SparkleInvite (args.FullPath);
+ tries++;
+ if (tries > 20)
+ break;
+ }
+
+ if (invite.IsValid) {
+ InviteReceived (invite);
+
+ } else {
+ if (AlertNotificationRaised != null)
+ AlertNotificationRaised ("Oh noes!",
+ "This invite seems screwed up...");
+ }
+
+ File.Delete (args.FullPath);
+ }
+ }
+ }
+
+
+ public void CheckRepositories ()
+ {
+ lock (this.check_repos_lock) {
+ string path = SparkleConfig.DefaultConfig.FoldersPath;
+
+ foreach (string folder_path in Directory.GetDirectories (path)) {
+ string folder_name = Path.GetFileName (folder_path);
+
+ if (folder_name.Equals (".tmp"))
+ continue;
+
+ if (SparkleConfig.DefaultConfig.GetIdentifierForFolder (folder_name) == null) {
+ string identifier_file_path = Path.Combine (folder_path, ".sparkleshare");
+
+ if (!File.Exists (identifier_file_path))
+ continue;
+
+ string identifier = File.ReadAllText (identifier_file_path).Trim ();
+
+ if (SparkleConfig.DefaultConfig.IdentifierExists (identifier)) {
+ RemoveRepository (folder_path);
+ SparkleConfig.DefaultConfig.RenameFolder (identifier, folder_name);
+
+ string new_folder_path = Path.Combine (path, folder_name);
+ AddRepository (new_folder_path);
+
+ SparkleHelpers.DebugInfo ("Controller",
+ "Renamed folder with identifier " + identifier + " to '" + folder_name + "'");
+ }
+ }
+ }
+
+ foreach (string folder_name in SparkleConfig.DefaultConfig.Folders) {
+ string folder_path = new SparkleFolder (folder_name).FullPath;
+
+ if (!Directory.Exists (folder_path)) {
+ SparkleConfig.DefaultConfig.RemoveFolder (folder_name);
+ RemoveRepository (folder_path);
+
+ SparkleHelpers.DebugInfo ("Controller",
+ "Removed folder '" + folder_name + "' from config");
+
+ } else {
+ AddRepository (folder_path);
+ }
+ }
+
+ if (FolderListChanged != null)
+ FolderListChanged ();
+ }
+ }
+
+
+ public void OnFolderActivity (object o, FileSystemEventArgs args)
+ {
+ if (args != null &&
+ args.ChangeType == WatcherChangeTypes.Created &&
+ args.FullPath.EndsWith (".xml")) {
+
+ HandleInvite (args);
+ return;
+
+ } else {
+ CheckRepositories ();
+ }
+ }
+
+
public virtual void Initialize ()
{
SparklePlugin.PluginsPath = PluginsPath;
@@ -201,69 +304,17 @@ namespace SparkleShare {
ImportPrivateKey ();
// Watch the SparkleShare folder
- FileSystemWatcher watcher = new FileSystemWatcher (SparkleConfig.DefaultConfig.FoldersPath) {
+ FileSystemWatcher watcher = new FileSystemWatcher () {
+ Filter = "*",
IncludeSubdirectories = false,
- EnableRaisingEvents = true,
- Filter = "*"
+ Path = SparkleConfig.DefaultConfig.FoldersPath
};
- watcher.Deleted += delegate (object o, FileSystemEventArgs args) {
- lock (this.delete_watcher_lock) {
- foreach (string folder_name in SparkleConfig.DefaultConfig.Folders) {
- string folder_path = new SparkleFolder (folder_name).FullPath;
+ watcher.Deleted += OnFolderActivity;
+ watcher.Created += OnFolderActivity;
+ watcher.Renamed += OnFolderActivity;
- if (!Directory.Exists (folder_path)) {
- SparkleConfig.DefaultConfig.RemoveFolder (folder_name);
- RemoveRepository (folder_path);
- }
- }
-
- if (FolderListChanged != null)
- FolderListChanged ();
- }
- };
-
- watcher.Created += delegate (object o, FileSystemEventArgs args) {
- if (!args.FullPath.EndsWith (".xml"))
- return;
-
- if (this.fetcher != null &&
- this.fetcher.IsActive) {
-
- if (AlertNotificationRaised != null)
- AlertNotificationRaised ("SparkleShare Setup seems busy",
- "Please wait for it to finish");
-
- } else {
- if (InviteReceived != null) {
- SparkleInvite invite = new SparkleInvite (args.FullPath);
-
- // It may be that the invite we received a path to isn't
- // fully downloaded yet, so we try to read it several times
- int tries = 0;
- while (!invite.IsValid) {
- Thread.Sleep (1 * 250);
- invite = new SparkleInvite (args.FullPath);
- tries++;
- if (tries > 20)
- break;
- }
-
- if (invite.IsValid) {
- InviteReceived (invite);
-
- } else {
- invite = null;
-
- if (AlertNotificationRaised != null)
- AlertNotificationRaised ("Oh noes!",
- "This invite seems screwed up...");
- }
-
- File.Delete (args.FullPath);
- }
- }
- };
+ watcher.EnableRaisingEvents = true;
}
@@ -327,11 +378,9 @@ namespace SparkleShare {
string path = new SparkleFolder (name).FullPath;
- lock (this.repo_lock) {
- foreach (SparkleRepoBase repo in Repositories) {
- if (repo.LocalPath.Equals (path))
- return repo.ChangeSets;
- }
+ foreach (SparkleRepoBase repo in Repositories) {
+ if (repo.LocalPath.Equals (path))
+ return repo.ChangeSets;
}
return null;
@@ -511,7 +560,6 @@ namespace SparkleShare {
}
- // Adds a repository to the list of repositories
private void AddRepository (string folder_path)
{
SparkleRepoBase repo = null;
@@ -531,16 +579,8 @@ namespace SparkleShare {
return;
}
-
- repo.NewChangeSet += delegate (SparkleChangeSet change_set) {
- if (NotificationRaised != null)
- NotificationRaised (change_set);
- };
-
- repo.ConflictResolved += delegate {
- if (AlertNotificationRaised != null)
- AlertNotificationRaised ("Conflict detected",
- "Don't worry, SparkleShare made a copy of each conflicting file.");
+ repo.ChangesDetected += delegate {
+ UpdateState ();
};
repo.SyncStatusChanged += delegate (SyncStatus status) {
@@ -565,8 +605,15 @@ namespace SparkleShare {
UpdateState ();
};
- repo.ChangesDetected += delegate {
- UpdateState ();
+ repo.NewChangeSet += delegate (SparkleChangeSet change_set) {
+ if (NotificationRaised != null)
+ NotificationRaised (change_set);
+ };
+
+ repo.ConflictResolved += delegate {
+ if (AlertNotificationRaised != null)
+ AlertNotificationRaised ("Conflict detected",
+ "Don't worry, SparkleShare made a copy of each conflicting file.");
};
this.repositories.Add (repo);
@@ -574,45 +621,25 @@ namespace SparkleShare {
}
- // Removes a repository from the list of repositories and
- // updates the statusicon menu
private void RemoveRepository (string folder_path)
{
- string folder_name = Path.GetFileName (folder_path);
+ for (int i = 0; i < this.repositories.Count; i++) {
+ SparkleRepoBase repo = this.repositories [i];
- for (int i = 0; i < Repositories.Length; i++) {
- SparkleRepoBase repo = Repositories [i];
-
- if (repo.Name.Equals (folder_name)) {
+ if (repo.LocalPath.Equals (folder_path)) {
repo.Dispose ();
-
- lock (this.repo_lock) {
- this.repositories.Remove (repo);
- }
+ this.repositories.Remove (repo);
repo = null;
- break;
+ return;
}
}
-
}
- // Updates the list of repositories with all the
- // folders in the SparkleShare folder
private void PopulateRepositories ()
{
- lock (this.repo_lock) {
- foreach (string folder_name in SparkleConfig.DefaultConfig.Folders) {
- string folder_path = new SparkleFolder (folder_name).FullPath;
-
- if (Directory.Exists (folder_path))
- AddRepository (folder_path);
- else
- SparkleConfig.DefaultConfig.RemoveFolder (folder_name);
- }
- }
-
+ CheckRepositories ();
RepositoriesLoaded = true;
if (FolderListChanged != null)
@@ -910,7 +937,8 @@ namespace SparkleShare {
Directory.Move (this.fetcher.TargetFolder, target_folder_path);
string backend = SparkleFetcherBase.GetBackend (this.fetcher.RemoteUrl.AbsolutePath);
- SparkleConfig.DefaultConfig.AddFolder (target_folder_name, this.fetcher.RemoteUrl.ToString (), backend);
+ SparkleConfig.DefaultConfig.AddFolder (target_folder_name, this.fetcher.Identifier,
+ this.fetcher.RemoteUrl.ToString (), backend);
if (FolderFetched != null)
FolderFetched (this.fetcher.RemoteUrl.ToString (), this.fetcher.Warnings.ToArray ());
@@ -921,9 +949,7 @@ namespace SparkleShare {
target_folder_name, "announcements_url", announcements_url);
*/
- lock (this.repo_lock) {
- AddRepository (target_folder_path);
- }
+ AddRepository (target_folder_path);
if (FolderListChanged != null)
FolderListChanged ();