diff --git a/SparkleLib/Git/SparkleRepoGit.cs b/SparkleLib/Git/SparkleRepoGit.cs
index 9e80cc23..0adff153 100644
--- a/SparkleLib/Git/SparkleRepoGit.cs
+++ b/SparkleLib/Git/SparkleRepoGit.cs
@@ -771,49 +771,6 @@ namespace SparkleLib.Git {
return change_sets;
}
- private string EnsureSpecialCharacters (string file_path)
- {
- if (file_path.StartsWith("\""))
- {
- System.Diagnostics.Debug.Assert(file_path.Length > 2 && file_path.EndsWith("\""), "unexpected path");
- file_path = ResolveSpecialChars(file_path.Substring(1, file_path.Length - 2));
- }
- return file_path;
- }
-
- ///
- /// Resolves special characters like \303\244 (ä) to their real character
- ///
- ///
- ///
- private string ResolveSpecialChars (string file_path)
- {
- var builder = new System.Text.StringBuilder(file_path.Length);
- var codes = new List();
- for (int i = 0; i < file_path.Length; i++)
- {
- while (file_path[i] == '\\'
- && file_path.Length - i > 3
- && char.IsNumber(file_path[i + 1])
- && char.IsNumber(file_path[i + 2])
- && char.IsNumber(file_path[i + 3]))
- {
- codes.Add (Convert.ToByte(file_path.Substring(i + 1, 3), 8));
- i += 4;
- }
-
- if (codes.Count > 0)
- {
- builder.Append(System.Text.Encoding.UTF8.GetString (codes.ToArray ()));
- codes.Clear ();
- }
-
- builder.Append(file_path[i]);
- }
- return builder.ToString();
- //System.Text.Encoding.UTF8.
- }
-
private string EnsureSpecialCharacters (string path)
{
@@ -825,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);
diff --git a/SparkleLib/SparkleConfig.cs b/SparkleLib/SparkleConfig.cs
index 0c441358..6cbcc3f8 100755
--- a/SparkleLib/SparkleConfig.cs
+++ b/SparkleLib/SparkleConfig.cs
@@ -248,6 +248,15 @@ 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");
@@ -266,6 +275,17 @@ namespace SparkleLib {
}
+ 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);
diff --git a/SparkleLib/SparkleFetcherBase.cs b/SparkleLib/SparkleFetcherBase.cs
index 231ce74d..8f1730dd 100755
--- a/SparkleLib/SparkleFetcherBase.cs
+++ b/SparkleLib/SparkleFetcherBase.cs
@@ -50,7 +50,7 @@ namespace SparkleLib {
public readonly bool FetchPriorHistory = false;
public string TargetFolder { get; protected set; }
public bool IsActive { get; private set; }
- public string Identifier = CreateIdentifier ();
+ 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;
@@ -105,7 +126,6 @@ namespace SparkleLib {
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,30 +160,31 @@ 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 ();
}
@@ -174,8 +194,13 @@ namespace SparkleLib {
{
string identifier_path = Path.Combine (TargetFolder, ".sparkleshare");
- if (!File.Exists (identifier_path))
+ if (File.Exists (identifier_path)) {
+ Identifier = File.ReadAllText (identifier_path).Trim ();
+
+ } else {
+ Identifier = CreateIdentifier ();
File.WriteAllText (identifier_path, Identifier);
+ }
if (IsFetchedRepoEmpty)
CreateInitialChangeSet ();
@@ -204,6 +229,32 @@ namespace SparkleLib {
}
+ public static string CreateIdentifier ()
+ {
+ Random random = new Random ();
+ string number = "" + random.Next () + "" + random.Next () + "" + random.Next ();
+
+ return SparkleHelpers.SHA1 (number);
+ }
+
+
+ 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) {
@@ -213,15 +264,6 @@ namespace SparkleLib {
}
- public static string CreateIdentifier ()
- {
- Random random = new Random ();
- string number = "" + random.Next () + "" + random.Next () + "" + random.Next ();
-
- return SparkleHelpers.SHA1 (number);
- }
-
-
protected void OnProgressChanged (double percentage) {
if (ProgressChanged != null)
ProgressChanged (percentage);
@@ -242,7 +284,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 ();
@@ -283,7 +325,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 {
@@ -329,98 +371,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/SparkleShare/SparkleControllerBase.cs b/SparkleShare/SparkleControllerBase.cs
index b79fb370..674a4385 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,110 @@ 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");
+ }
+ }
+
+ 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 +301,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 +375,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 +557,6 @@ namespace SparkleShare {
}
- // Adds a repository to the list of repositories
private void AddRepository (string folder_path)
{
SparkleRepoBase repo = null;
@@ -531,16 +576,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 +602,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 +618,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)
@@ -922,9 +946,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 ();