summaryrefslogtreecommitdiff
path: root/SparkleLib
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2013-05-27 00:57:45 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2013-05-27 00:57:45 +0200
commite45ec00415203c0133be6d18a72326f3506f793b (patch)
treee31a0f4f95f0f5ac674e2837dfc64a4f01204b51 /SparkleLib
parent9b285841b34f54b2ea94db66ce4a229b578a499d (diff)
Imported Upstream version 1.1.0
Diffstat (limited to 'SparkleLib')
-rw-r--r--SparkleLib/Defines.cs4
-rw-r--r--SparkleLib/Git/Makefile.in39
-rwxr-xr-xSparkleLib/Git/SparkleFetcherGit.cs64
-rw-r--r--SparkleLib/Git/SparkleGit.cs6
-rw-r--r--SparkleLib/Git/SparkleRepoGit.cs233
-rwxr-xr-xSparkleLib/Makefile.am1
-rw-r--r--SparkleLib/Makefile.in40
-rwxr-xr-xSparkleLib/SparkleConfig.cs14
-rwxr-xr-xSparkleLib/SparkleExtensions.cs6
-rwxr-xr-xSparkleLib/SparkleFetcherBase.cs167
-rw-r--r--SparkleLib/SparkleFetcherSSH.cs143
-rwxr-xr-xSparkleLib/SparkleRepoBase.cs176
-rw-r--r--SparkleLib/SparkleUser.cs4
-rw-r--r--SparkleLib/SparkleWrappers.cs18
14 files changed, 456 insertions, 459 deletions
diff --git a/SparkleLib/Defines.cs b/SparkleLib/Defines.cs
index 5244628..037291a 100644
--- a/SparkleLib/Defines.cs
+++ b/SparkleLib/Defines.cs
@@ -19,13 +19,13 @@ using System;
using System.Reflection;
[assembly:AssemblyTitle ("SparkleLib")]
-[assembly:AssemblyVersion ("1.0.0")]
+[assembly:AssemblyVersion ("1.1.0")]
[assembly:AssemblyCopyright ("Copyright (c) 2010 Hylke Bons and others")]
[assembly:AssemblyTrademark ("SparkleShare is a trademark of SparkleShare Ltd.")]
namespace SparkleLib {
public class Defines {
- public const string INSTALL_DIR = "/usr/share/sparkleshare";
+ public const string INSTALL_DIR = "/usr/local/share/sparkleshare";
}
}
diff --git a/SparkleLib/Git/Makefile.in b/SparkleLib/Git/Makefile.in
index 3342f18..bcb72cd 100644
--- a/SparkleLib/Git/Makefile.in
+++ b/SparkleLib/Git/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.12.4 from Makefile.am.
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
-
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -15,23 +16,6 @@
@SET_MAKE@
VPATH = @srcdir@
-am__make_dryrun = \
- { \
- am__dry=no; \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
- *) \
- for am__flg in $$MAKEFLAGS; do \
- case $$am__flg in \
- *=*|--*) ;; \
- *n*) am__dry=yes; break;; \
- esac; \
- done;; \
- esac; \
- test $$am__dry = yes; \
- }
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -97,11 +81,6 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(moduledir)"
SCRIPTS = $(module_SCRIPTS)
DIST_SOURCES =
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
@@ -237,6 +216,7 @@ DIR_BIN = $(top_builddir)/bin
# External libraries to link against, generated from configure
LINK_SYSTEM = -r:System
+LINK_SYSTEM_WEB = -r:System.Web
LINK_MONO_POSIX = -r:Mono.Posix
LINK_GLIB = $(GLIBSHARP_LIBS)
LINK_GTK = $(GTKSHARP_LIBS)
@@ -250,7 +230,7 @@ LINK_NOTIFY_SHARP_DEPS = $(REF_NOTIFY_SHARP) $(LINK_NOTIFY_SHARP)
REF_SPARKLELIB = $(LINK_SYSTEM) $(LINK_MONO_POSIX)
LINK_SPARKLELIB = -r:$(DIR_BIN)/SparkleLib.dll
LINK_SPARKLELIB_DEPS = $(REF_SPARKLELIB) $(LINK_SPARKLELIB)
-REF_SPARKLESHARE = $(LINK_DBUS) $(LINK_GTK) $(LINK_SPARKLELIB_DEPS) $(LINK_APP_INDICATOR)
+REF_SPARKLESHARE = $(LINK_SYSTEM_WEB) $(LINK_DBUS) $(LINK_GTK) $(LINK_SPARKLELIB_DEPS) $(LINK_APP_INDICATOR)
# Cute hack to replace a space with something
colon := :
@@ -326,11 +306,8 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
install-moduleSCRIPTS: $(module_SCRIPTS)
@$(NORMAL_INSTALL)
+ test -z "$(moduledir)" || $(MKDIR_P) "$(DESTDIR)$(moduledir)"
@list='$(module_SCRIPTS)'; test -n "$(moduledir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(moduledir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(moduledir)" || exit 1; \
- fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
@@ -371,8 +348,6 @@ TAGS:
ctags: CTAGS
CTAGS:
-cscope cscopelist:
-
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
diff --git a/SparkleLib/Git/SparkleFetcherGit.cs b/SparkleLib/Git/SparkleFetcherGit.cs
index b84e7c9..fc36646 100755
--- a/SparkleLib/Git/SparkleFetcherGit.cs
+++ b/SparkleLib/Git/SparkleFetcherGit.cs
@@ -12,21 +12,20 @@
// 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 <http://www.gnu.org/licenses/>.
-
-
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Text.RegularExpressions;
-using System.Threading;
-
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Threading;
using SparkleLib;
namespace SparkleLib.Git {
- // Sets up a fetcher that can get remote folders
- public class SparkleFetcher : SparkleFetcherBase {
+ public class SparkleFetcher : SparkleFetcherSSH {
private SparkleGit git;
private bool use_git_bin;
@@ -62,10 +61,11 @@ namespace SparkleLib.Git {
}
- 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)
+ public SparkleFetcher (SparkleFetcherInfo info) : base (info)
{
+ if (RemoteUrl.ToString ().StartsWith ("ssh+"))
+ RemoteUrl = new Uri ("ssh" + RemoteUrl.ToString ().Substring (RemoteUrl.ToString ().IndexOf ("://")));
+
Uri uri = RemoteUrl;
if (!uri.Scheme.Equals ("ssh") && !uri.Scheme.Equals ("https") &&
@@ -101,13 +101,15 @@ namespace SparkleLib.Git {
this.use_git_bin = false; // TODO
}
- TargetFolder = target_folder;
- RemoteUrl = uri;
+ RemoteUrl = uri;
}
public override bool Fetch ()
{
+ if (!base.Fetch ())
+ return false;
+
if (FetchPriorHistory) {
this.git = new SparkleGit (SparkleConfig.DefaultConfig.TmpPath,
"clone --progress --no-checkout \"" + RemoteUrl + "\" \"" + TargetFolder + "\"");
@@ -132,7 +134,7 @@ namespace SparkleLib.Git {
double number = 0.0;
if (match.Success) {
- number = double.Parse (match.Groups [1].Value);
+ number = double.Parse (match.Groups [1].Value, new CultureInfo ("en-US"));
// The cloning progress consists of two stages: the "Compressing
// objects" stage which we count as 20% of the total progress, and
@@ -188,8 +190,6 @@ namespace SparkleLib.Git {
InstallExcludeRules ();
InstallAttributeRules ();
- AddWarnings ();
-
return true;
} else {
@@ -309,6 +309,7 @@ namespace SparkleLib.Git {
"core.autocrlf false", // Don't change file line endings
"core.precomposeunicode true", // Use the same Unicode form on all filesystems
"core.safecrlf false",
+ "core.exludesfile \"\"",
"core.packedGitLimit 128m", // Some memory limiting options
"core.packedGitWindowSize 128m",
"pack.deltaCacheSize 128m",
@@ -330,13 +331,9 @@ namespace SparkleLib.Git {
public void InstallGitBinConfiguration ()
{
string [] settings = new string [] {
- "core.bigFileThreshold 8g",
+ "core.bigFileThreshold 1024g",
"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\""
+ "filter.bin.smudge \"git bin smudge\""
};
foreach (string setting in settings) {
@@ -376,7 +373,7 @@ namespace SparkleLib.Git {
"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", "iso" // Archives
+ "zip", "gz", "bz", "bz2", "rpm", "deb", "tgz", "rar", "ace", "7z", "pak", "tc", "iso", ".dmg" // Archives
};
foreach (string extension in extensions) {
@@ -390,20 +387,5 @@ namespace SparkleLib.Git {
writer.Close ();
}
-
-
- private void AddWarnings ()
- {
- if (this.warnings.Count > 0)
- return;
-
- SparkleGit git = new SparkleGit (TargetFolder, "config --global core.excludesfile");
- string output = git.StartAndReadStandardOutput ();
-
- if (string.IsNullOrEmpty (output))
- return;
- else
- this.warnings.Add ("You seem to have a system wide ‘gitignore’ file, this may affect SparkleShare files.");
- }
}
}
diff --git a/SparkleLib/Git/SparkleGit.cs b/SparkleLib/Git/SparkleGit.cs
index 3251091..3ccde01 100644
--- a/SparkleLib/Git/SparkleGit.cs
+++ b/SparkleLib/Git/SparkleGit.cs
@@ -83,6 +83,7 @@ namespace SparkleLib.Git {
protected string LocateCommand (string name)
{
string [] possible_command_paths = new string [] {
+ Defines.INSTALL_DIR + "/bin/" + name,
"/usr/bin/" + name,
"/usr/local/bin/" + name,
"/opt/local/bin/" + name
@@ -116,6 +117,11 @@ namespace SparkleLib.Git {
StartInfo.WorkingDirectory = path;
StartInfo.CreateNoWindow = true;
+ if (StartInfo.EnvironmentVariables.ContainsKey ("LANG"))
+ StartInfo.EnvironmentVariables ["LANG"] = "en_US";
+ else
+ StartInfo.EnvironmentVariables.Add ("LANG", "en_US");
+
if (string.IsNullOrEmpty (ExecPath))
StartInfo.Arguments = args;
else
diff --git a/SparkleLib/Git/SparkleRepoGit.cs b/SparkleLib/Git/SparkleRepoGit.cs
index 66aed8b..28d7ba7 100644
--- a/SparkleLib/Git/SparkleRepoGit.cs
+++ b/SparkleLib/Git/SparkleRepoGit.cs
@@ -12,16 +12,16 @@
// 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 <http://www.gnu.org/licenses/>.
-
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading;
-
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
using SparkleLib;
namespace SparkleLib.Git {
@@ -70,8 +70,6 @@ namespace SparkleLib.Git {
public SparkleRepo (string path, SparkleConfig config) : base (path, config)
{
- // TODO: Set git locale to en-US
-
SparkleGit git = new SparkleGit (LocalPath, "config core.ignorecase false");
git.StartAndWaitForExit ();
@@ -81,6 +79,9 @@ namespace SparkleLib.Git {
this.use_git_bin = (git.ExitCode == 0);
+ if (this.use_git_bin)
+ ConfigureGitBin ();
+
git = new SparkleGit (LocalPath, "config remote.origin.url \"" + RemoteUrl + "\"");
git.StartAndWaitForExit ();
@@ -91,6 +92,22 @@ namespace SparkleLib.Git {
}
+ private void ConfigureGitBin ()
+ {
+ SparkleGit git = new SparkleGit (LocalPath, "config filter.bin.clean \"git bin clean %f\"");
+ git.StartAndWaitForExit ();
+
+ git = new SparkleGit (LocalPath, "config filter.bin.smudge \"git bin smudge\"");
+ git.StartAndWaitForExit ();
+
+ git = new SparkleGit (LocalPath, "config git-bin.sftpUrl \"" + RemoteUrl + "\"");
+ git.StartAndWaitForExit ();
+
+ git = new SparkleGit (LocalPath, "config git-bin.sftpPrivateKeyFile \"" + base.local_config.User.PrivateKeyFilePath + "\"");
+ git.StartAndWaitForExit ();
+ }
+
+
public override List<string> ExcludePaths {
get {
List<string> rules = new List<string> ();
@@ -142,30 +159,6 @@ namespace SparkleLib.Git {
File.WriteAllText (size_file_path, size.ToString ());
File.WriteAllText (history_size_file_path, history_size.ToString ());
}
-
-
- public override string [] UnsyncedFilePaths {
- get {
- List<string> file_paths = new List<string> ();
- SparkleGit git = new SparkleGit (LocalPath, "status --porcelain");
- string output = git.StartAndReadStandardOutput ();
- string [] lines = output.Split ("\n".ToCharArray ());
-
- foreach (string line in lines) {
- if (line [1].ToString ().Equals ("M") ||
- line [1].ToString ().Equals ("?") ||
- line [1].ToString ().Equals ("A")) {
-
- string path = line.Substring (3);
- path = path.Trim ("\"".ToCharArray ());
-
- file_paths.Add (path);
- }
- }
-
- return file_paths.ToArray ();
- }
- }
public override string CurrentRevision {
@@ -192,34 +185,43 @@ namespace SparkleLib.Git {
if (git.ExitCode != 0)
return false;
- string remote_revision = output.Substring (0, 40);
+ string remote_revision = "" + output.Substring (0, 40);
- if (!string.IsNullOrEmpty (remote_revision) && !remote_revision.StartsWith (current_revision)) {
- SparkleLogger.LogInfo ("Git", Name + " | Remote changes found, local: " +
- current_revision + ", remote: " + remote_revision);
+ if (!remote_revision.Equals (current_revision)) {
+ git = new SparkleGit (LocalPath, "merge-base " + remote_revision + " master");
+ git.StartAndWaitForExit ();
- Error = ErrorStatus.None;
- return true;
+ if (git.ExitCode != 0) {
+ SparkleLogger.LogInfo ("Git", Name + " | Remote changes found, local: " +
+ current_revision + ", remote: " + remote_revision);
- } else {
- SparkleLogger.LogInfo ("Git", Name + " | No remote changes, local+remote: " + current_revision);
- return false;
- }
+ Error = ErrorStatus.None;
+ return true;
+
+ } else {
+ SparkleLogger.LogInfo ("Git", Name + " | Remote " + remote_revision + " is already in our history");
+ return false;
+ }
+ }
+
+ SparkleLogger.LogInfo ("Git", Name + " | No remote changes, local+remote: " + current_revision);
+ return false;
}
}
public override bool SyncUp ()
{
- if (HasLocalChanges) {
- Add ();
-
- string message = FormatCommitMessage ();
- Commit (message);
+ if (!Add ()) {
+ Error = ErrorStatus.UnreadableFiles;
+ return false;
}
- SparkleGit git;
+ string message = FormatCommitMessage ();
+ if (message != null)
+ Commit (message);
+
if (this.use_git_bin) {
SparkleGitBin git_bin = new SparkleGitBin (LocalPath, "push");
git_bin.StartAndWaitForExit ();
@@ -227,8 +229,7 @@ namespace SparkleLib.Git {
// TODO: Progress
}
- git = new SparkleGit (LocalPath, "push --progress \"" + RemoteUrl + "\" " + this.branch);
-
+ SparkleGit git = new SparkleGit (LocalPath, "push --progress \"" + RemoteUrl + "\" " + this.branch);
git.StartInfo.RedirectStandardError = true;
git.Start ();
@@ -241,7 +242,12 @@ namespace SparkleLib.Git {
double number = 0.0;
if (match.Success) {
- number = double.Parse (match.Groups [1].Value);
+ try {
+ number = double.Parse (match.Groups [1].Value, new CultureInfo ("en-US"));
+
+ } catch (FormatException) {
+ SparkleLogger.LogInfo ("Git", "Error parsing progress: \"" + match.Groups [1] + "\"");
+ }
// The pushing progress consists of two stages: the "Compressing
// objects" stage which we count as 20% of the total progress, and
@@ -256,7 +262,12 @@ namespace SparkleLib.Git {
Match speed_match = this.speed_regex.Match (line);
if (speed_match.Success) {
- speed = double.Parse (speed_match.Groups [1].Value) * 1024;
+ try {
+ speed = double.Parse (speed_match.Groups [1].Value, new CultureInfo ("en-US")) * 1024;
+
+ } catch (FormatException) {
+ SparkleLogger.LogInfo ("Git", "Error parsing speed: \"" + speed_match.Groups [1] + "\"");
+ }
if (speed_match.Groups [2].Value.Equals ("M"))
speed = speed * 1024;
@@ -323,7 +334,12 @@ namespace SparkleLib.Git {
double number = 0.0;
if (match.Success) {
- number = double.Parse (match.Groups [1].Value);
+ try {
+ number = double.Parse (match.Groups [1].Value, new CultureInfo ("en-US"));
+
+ } catch (FormatException) {
+ SparkleLogger.LogInfo ("Git", "Error parsing progress: \"" + match.Groups [1] + "\"");
+ }
// The fetching progress consists of two stages: the "Compressing
// objects" stage which we count as 20% of the total progress, and
@@ -338,7 +354,12 @@ namespace SparkleLib.Git {
Match speed_match = this.speed_regex.Match (line);
if (speed_match.Success) {
- speed = double.Parse (speed_match.Groups [1].Value) * 1024;
+ try {
+ speed = double.Parse (speed_match.Groups [1].Value, new CultureInfo ("en-US")) * 1024;
+
+ } catch (FormatException) {
+ SparkleLogger.LogInfo ("Git", "Error parsing speed: \"" + speed_match.Groups [1] + "\"");
+ }
if (speed_match.Groups [2].Value.Equals ("M"))
speed = speed * 1024;
@@ -408,10 +429,12 @@ namespace SparkleLib.Git {
// Stages the made changes
- private void Add ()
+ private bool Add ()
{
SparkleGit git = new SparkleGit (LocalPath, "add --all");
git.StartAndWaitForExit ();
+
+ return (git.ExitCode == 0);
}
@@ -440,16 +463,27 @@ namespace SparkleLib.Git {
// Merges the fetched changes
private bool Rebase ()
{
- if (HasLocalChanges) {
+ string message = FormatCommitMessage ();
+
+ if (message != null) {
Add ();
+ Commit (message);
+ }
- string commit_message = FormatCommitMessage ();
- Commit (commit_message);
+ SparkleGit git;
+ string rebase_apply_path = new string [] { LocalPath, ".git", "rebase-apply" }.Combine ();
+
+ // Stop if we're already in a rebase because something went wrong
+ if (Directory.Exists (rebase_apply_path)) {
+ git = new SparkleGit (LocalPath, "rebase --abort");
+ git.StartAndWaitForExit ();
+
+ return false;
}
// Temporarily change the ignorecase setting to true to avoid
- // conflicts in file names due to case changes
- SparkleGit git = new SparkleGit (LocalPath, "config core.ignorecase true");
+ // conflicts in file names due to letter case changes
+ git = new SparkleGit (LocalPath, "config core.ignorecase true");
git.StartAndWaitForExit ();
git = new SparkleGit (LocalPath, "rebase FETCH_HEAD");
@@ -461,7 +495,7 @@ namespace SparkleLib.Git {
// Stop when we can't rebase due to locked local files
// error: cannot stat 'filename': Permission denied
if (error_output.Contains ("error: cannot stat")) {
- Error = ErrorStatus.LockedFiles;
+ Error = ErrorStatus.UnreadableFiles;
SparkleLogger.LogInfo ("Git", Name + " | Error status changed to " + Error);
git = new SparkleGit (LocalPath, "rebase --abort");
@@ -474,7 +508,6 @@ namespace SparkleLib.Git {
} else {
SparkleLogger.LogInfo ("Git", Name + " | Conflict detected, trying to get out...");
- string rebase_apply_path = new string [] { LocalPath, ".git", "rebase-apply" }.Combine ();
while (Directory.Exists (rebase_apply_path) && HasLocalChanges) {
try {
@@ -705,6 +738,13 @@ namespace SparkleLib.Git {
string output = git.StartAndReadStandardOutput ();
+ if (path == null && string.IsNullOrWhiteSpace (output)) {
+ git = new SparkleGit (LocalPath, "log -n 75 --raw --find-renames --date=iso " +
+ "--format=medium --no-color --no-merges");
+
+ output = git.StartAndReadStandardOutput ();
+ }
+
string [] lines = output.Split ("\n".ToCharArray ());
List<string> entries = new List <string> ();
@@ -759,6 +799,9 @@ namespace SparkleLib.Git {
foreach (string entry_line in entry_lines) {
if (entry_line.StartsWith (":")) {
+ if (entry_line.Contains ("\\177"))
+ continue;
+
string type_letter = entry_line [37].ToString ();
string file_path = entry_line.Substring (39);
bool change_is_folder = false;
@@ -852,18 +895,18 @@ namespace SparkleLib.Git {
} else {
if (path != null) {
- bool skip_change_set = false;;
+ List<SparkleChange> changes_to_skip = new List<SparkleChange> ();
foreach (SparkleChange change in change_set.Changes) {
- if ((change.Type == SparkleChangeType.Deleted ||
- change.Type == SparkleChangeType.Moved) && change.Path.Equals (path)) {
+ if ((change.Type == SparkleChangeType.Deleted || change.Type == SparkleChangeType.Moved)
+ && change.Path.Equals (path)) {
- skip_change_set = true;
+ changes_to_skip.Add (change);
}
}
- if (skip_change_set)
- continue;
+ foreach (SparkleChange change_to_skip in changes_to_skip)
+ change_set.Changes.Remove (change_to_skip);
}
change_sets.Add (change_set);
@@ -984,6 +1027,7 @@ namespace SparkleLib.Git {
while (!git_status.StandardOutput.EndOfStream) {
string line = git_status.StandardOutput.ReadLine ();
+ line = line.Trim ();
if (line.EndsWith (".empty") || line.EndsWith (".empty\""))
line = line.Replace (".empty", "");
@@ -1020,42 +1064,47 @@ namespace SparkleLib.Git {
git_status.StandardOutput.ReadToEnd ();
git_status.WaitForExit ();
- return message;
+ if (string.IsNullOrWhiteSpace (message))
+ return null;
+ else
+ return message;
}
// Recursively gets a folder's size in bytes
- private double CalculateSizes (DirectoryInfo parent)
+ private long CalculateSizes (DirectoryInfo parent)
{
- if (!Directory.Exists (parent.FullName) || parent.Name.Equals ("rebase-apply"))
- return 0;
-
- double size = 0;
+ long size = 0;
try {
- foreach (FileInfo file in parent.GetFiles ()) {
- if (!file.Exists)
- return 0;
+ foreach (DirectoryInfo directory in parent.GetDirectories ()) {
+ if (directory.IsSymlink () ||
+ directory.Name.Equals (".git") ||
+ directory.Name.Equals ("rebase-apply")) {
- if (file.Name.Equals (".empty"))
- File.SetAttributes (file.FullName, FileAttributes.Hidden);
+ continue;
+ }
- size += file.Length;
+ size += CalculateSizes (directory);
}
} catch (Exception e) {
- SparkleLogger.LogInfo ("Local", "Error calculating size", e);
- return 0;
+ SparkleLogger.LogInfo ("Local", "Error calculating directory size", e);
}
-
try {
- foreach (DirectoryInfo directory in parent.GetDirectories ())
- size += CalculateSizes (directory);
-
+ foreach (FileInfo file in parent.GetFiles ()) {
+ if (file.IsSymlink ())
+ continue;
+
+ if (file.Name.Equals (".empty"))
+ File.SetAttributes (file.FullName, FileAttributes.Hidden);
+ else
+ size += file.Length;
+ }
+
} catch (Exception e) {
- SparkleLogger.LogInfo ("Local", "Error calculating size", e);
- return 0;
+ SparkleLogger.LogInfo ("Local", "Error calculating file size", e);
}
return size;
diff --git a/SparkleLib/Makefile.am b/SparkleLib/Makefile.am
index da03327..55fad6c 100755
--- a/SparkleLib/Makefile.am
+++ b/SparkleLib/Makefile.am
@@ -9,6 +9,7 @@ SOURCES = \
SparkleConfig.cs \
SparkleExtensions.cs \
SparkleFetcherBase.cs \
+ SparkleFetcherSSH.cs \
SparkleListenerBase.cs \
SparkleListenerFactory.cs \
SparkleListenerTcp.cs \
diff --git a/SparkleLib/Makefile.in b/SparkleLib/Makefile.in
index e6e6afc..e5b5c6c 100644
--- a/SparkleLib/Makefile.in
+++ b/SparkleLib/Makefile.in
@@ -1,8 +1,9 @@
-# Makefile.in generated by automake 1.12.4 from Makefile.am.
+# Makefile.in generated by automake 1.11.3 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2012 Free Software Foundation, Inc.
-
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -15,23 +16,6 @@
@SET_MAKE@
VPATH = @srcdir@
-am__make_dryrun = \
- { \
- am__dry=no; \
- case $$MAKEFLAGS in \
- *\\[\ \ ]*) \
- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
- *) \
- for am__flg in $$MAKEFLAGS; do \
- case $$am__flg in \
- *=*|--*) ;; \
- *n*) am__dry=yes; break;; \
- esac; \
- done;; \
- esac; \
- test $$am__dry = yes; \
- }
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
@@ -97,11 +81,6 @@ am__uninstall_files_from_dir = { \
am__installdirs = "$(DESTDIR)$(moduledir)"
SCRIPTS = $(module_SCRIPTS)
DIST_SOURCES =
-am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
- n|no|NO) false;; \
- *) (install-info --version) >/dev/null 2>&1;; \
- esac
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
@@ -226,6 +205,7 @@ SOURCES = \
SparkleConfig.cs \
SparkleExtensions.cs \
SparkleFetcherBase.cs \
+ SparkleFetcherSSH.cs \
SparkleListenerBase.cs \
SparkleListenerFactory.cs \
SparkleListenerTcp.cs \
@@ -245,6 +225,7 @@ DIR_BIN = $(top_builddir)/bin
# External libraries to link against, generated from configure
LINK_SYSTEM = -r:System
+LINK_SYSTEM_WEB = -r:System.Web
LINK_MONO_POSIX = -r:Mono.Posix
LINK_GLIB = $(GLIBSHARP_LIBS)
LINK_GTK = $(GTKSHARP_LIBS)
@@ -258,7 +239,7 @@ LINK_NOTIFY_SHARP_DEPS = $(REF_NOTIFY_SHARP) $(LINK_NOTIFY_SHARP)
REF_SPARKLELIB = $(LINK_SYSTEM) $(LINK_MONO_POSIX)
LINK_SPARKLELIB = -r:$(DIR_BIN)/SparkleLib.dll
LINK_SPARKLELIB_DEPS = $(REF_SPARKLELIB) $(LINK_SPARKLELIB)
-REF_SPARKLESHARE = $(LINK_DBUS) $(LINK_GTK) $(LINK_SPARKLELIB_DEPS) $(LINK_APP_INDICATOR)
+REF_SPARKLESHARE = $(LINK_SYSTEM_WEB) $(LINK_DBUS) $(LINK_GTK) $(LINK_SPARKLELIB_DEPS) $(LINK_APP_INDICATOR)
# Cute hack to replace a space with something
colon := :
@@ -337,11 +318,8 @@ Defines.cs: $(top_builddir)/config.status $(srcdir)/Defines.cs.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
install-moduleSCRIPTS: $(module_SCRIPTS)
@$(NORMAL_INSTALL)
+ test -z "$(moduledir)" || $(MKDIR_P) "$(DESTDIR)$(moduledir)"
@list='$(module_SCRIPTS)'; test -n "$(moduledir)" || list=; \
- if test -n "$$list"; then \
- echo " $(MKDIR_P) '$(DESTDIR)$(moduledir)'"; \
- $(MKDIR_P) "$(DESTDIR)$(moduledir)" || exit 1; \
- fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
@@ -382,8 +360,6 @@ TAGS:
ctags: CTAGS
CTAGS:
-cscope cscopelist:
-
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
diff --git a/SparkleLib/SparkleConfig.cs b/SparkleLib/SparkleConfig.cs
index fdc34b9..03404a2 100755
--- a/SparkleLib/SparkleConfig.cs
+++ b/SparkleLib/SparkleConfig.cs
@@ -136,11 +136,17 @@ namespace SparkleLib {
string user_name = name_node.Value;
string user_email = email_node.Value;
- SparkleUser user = new SparkleUser (user_name, user_email);
- string [] pubkey_file_paths = Directory.GetFiles (Path.GetDirectoryName (FullPath), "*.pub");
+ SparkleUser user = new SparkleUser (user_name, user_email);
- if (pubkey_file_paths.Length > 0)
- user.PublicKey = File.ReadAllText (pubkey_file_paths [0]);
+ string [] private_key_file_paths = Directory.GetFiles (Path.GetDirectoryName (FullPath), "*.key");
+
+ if (private_key_file_paths.Length > 0) {
+ user.PrivateKey = File.ReadAllText (private_key_file_paths [0]);
+ user.PrivateKeyFilePath = private_key_file_paths [0];
+
+ user.PublicKey = File.ReadAllText (private_key_file_paths [0] + ".pub");
+ user.PublicKeyFilePath = private_key_file_paths [0] + ".pub";
+ }
return user;
}
diff --git a/SparkleLib/SparkleExtensions.cs b/SparkleLib/SparkleExtensions.cs
index fb39aa7..ef6dd97 100755
--- a/SparkleLib/SparkleExtensions.cs
+++ b/SparkleLib/SparkleExtensions.cs
@@ -70,5 +70,11 @@ namespace SparkleLib {
else
return byte_count.ToString () + " ʙ";
}
+
+
+ public static bool IsSymlink (this FileSystemInfo file)
+ {
+ return ((file.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint);
+ }
}
}
diff --git a/SparkleLib/SparkleFetcherBase.cs b/SparkleLib/SparkleFetcherBase.cs
index 3f08c3b..6c57599 100755
--- a/SparkleLib/SparkleFetcherBase.cs
+++ b/SparkleLib/SparkleFetcherBase.cs
@@ -24,7 +24,16 @@ using System.Threading;
namespace SparkleLib {
- // Sets up a fetcher that can get remote folders
+ public class SparkleFetcherInfo {
+ public string Address;
+ public string Fingerprint;
+ public string RemotePath;
+ public string TargetDirectory;
+ public string AnnouncementsUrl;
+ public bool FetchPriorHistory;
+ }
+
+
public abstract class SparkleFetcherBase {
public event Action Started = delegate { };
@@ -49,6 +58,7 @@ namespace SparkleLib {
public string TargetFolder { get; protected set; }
public bool IsActive { get; private set; }
public string Identifier;
+ public SparkleFetcherInfo OriginalFetcherInfo;
public string [] Warnings {
get {
@@ -73,7 +83,7 @@ namespace SparkleLib {
"*.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
+ ".DS_Store", "Icon\r", "._*", ".Spotlight-V100", ".Trashes", // Mac OS X
"*(Autosaved).graffle", // Omnigraffle
"Thumbs.db", "Desktop.ini", // Windows
"~*.tmp", "~*.TMP", "*~*.tmp", "*~*.TMP", // MS Office
@@ -83,32 +93,36 @@ namespace SparkleLib {
"*/CVS/*", ".cvsignore", "*/.cvsignore", // CVS
"/.svn/*", "*/.svn/*", // Subversion
"/.hg/*", "*/.hg/*", "*/.hgignore", // Mercurial
- "/.bzr/*", "*/.bzr/*", "*/.bzrignore" // Bazaar
+ "/.bzr/*", "*/.bzr/*", "*/.bzrignore", // Bazaar
+ "*<*", "*>*", "*:*", "*\"*", "*|*", "*\\?*", "*\\**", "*\\\\*" // Not allowed on Windows systems,
+ // see (http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx)
};
private Thread thread;
- public SparkleFetcherBase (string server, string required_fingerprint,
- string remote_path, string target_folder, bool fetch_prior_history)
+ public SparkleFetcherBase (SparkleFetcherInfo info)
{
- RequiredFingerprint = required_fingerprint;
- FetchPriorHistory = fetch_prior_history;
- remote_path = remote_path.Trim ("/".ToCharArray ());
+ OriginalFetcherInfo = info;
+ RequiredFingerprint = info.Fingerprint;
+ FetchPriorHistory = info.FetchPriorHistory;
+ string remote_path = info.RemotePath.Trim ("/".ToCharArray ());
+ string address = info.Address;
- if (server.EndsWith ("/"))
- server = server.Substring (0, server.Length - 1);
+ if (address.EndsWith ("/"))
+ address = address.Substring (0, address.Length - 1);
if (!remote_path.StartsWith ("/"))
remote_path = "/" + remote_path;
- if (!server.Contains ("://"))
- server = "ssh://" + server;
+ if (!address.Contains ("://"))
+ address = "ssh://" + address;
- TargetFolder = target_folder;
- RemoteUrl = new Uri (server + remote_path);
- IsActive = false;
+ TargetFolder = info.TargetDirectory;
+
+ RemoteUrl = new Uri (address + remote_path);
+ IsActive = false;
}
@@ -119,44 +133,9 @@ namespace SparkleLib {
SparkleLogger.LogInfo ("Fetcher", TargetFolder + " | Fetching folder: " + RemoteUrl);
- if (Directory.Exists (TargetFolder))
+ if (Directory.Exists (TargetFolder))
Directory.Delete (TargetFolder, true);
- string host_key = "";
-
- if (!RemoteUrl.Scheme.StartsWith ("http")) {
- host_key = FetchHostKey ();
-
- if (string.IsNullOrEmpty (RemoteUrl.Host) || host_key == null) {
- SparkleLogger.LogInfo ("Auth", "Could not fetch host key");
- Failed ();
-
- return;
- }
-
- bool warn = true;
- if (RequiredFingerprint != null) {
- string host_fingerprint = DeriveFingerprint (host_key);
-
- if (host_fingerprint == null || !RequiredFingerprint.Equals (host_fingerprint)) {
- SparkleLogger.LogInfo ("Auth", "Fingerprint doesn't match");
-
- this.errors.Add ("error: Host fingerprint doesn't match");
- Failed ();
-
- return;
- }
-
- warn = false;
- SparkleLogger.LogInfo ("Auth", "Fingerprint matches");
-
- } else {
- SparkleLogger.LogInfo ("Auth", "Skipping fingerprint check");
- }
-
- AcceptHostKey (host_key, warn);
- }
-
this.thread = new Thread (() => {
if (Fetch ()) {
Thread.Sleep (500);
@@ -209,7 +188,7 @@ namespace SparkleLib {
UriBuilder uri_builder = new UriBuilder (RemoteUrl);
- if (RemoteUrl.Scheme.StartsWith ("http")) {
+ if (RemoteUrl.Scheme.Contains ("http")) {
uri_builder.UserName = "";
uri_builder.Password = "";
}
@@ -233,8 +212,7 @@ namespace SparkleLib {
public static string CreateIdentifier ()
{
- string random = Path.GetRandomFileName ();
- return random.SHA1 ();
+ return Path.GetRandomFileName ().SHA1 ();
}
@@ -257,87 +235,6 @@ namespace SparkleLib {
}
- private string FetchHostKey ()
- {
- SparkleLogger.LogInfo ("Auth", "Fetching host key for " + RemoteUrl.Host);
-
- Process process = new Process ();
- process.StartInfo.FileName = "ssh-keyscan";
- process.StartInfo.WorkingDirectory = SparkleConfig.DefaultConfig.TmpPath;
- process.StartInfo.UseShellExecute = false;
- process.StartInfo.RedirectStandardOutput = true;
- process.StartInfo.CreateNoWindow = true;
- process.EnableRaisingEvents = true;
-
- if (RemoteUrl.Port < 1)
- process.StartInfo.Arguments = "-t rsa -p 22 " + RemoteUrl.Host;
- else
- process.StartInfo.Arguments = "-t rsa -p " + RemoteUrl.Port + " " + RemoteUrl.Host;
-
- SparkleLogger.LogInfo ("Cmd", process.StartInfo.FileName + " " + process.StartInfo.Arguments);
-
- process.Start ();
- string host_key = process.StandardOutput.ReadToEnd ().Trim ();
- process.WaitForExit ();
-
- if (process.ExitCode == 0 && !string.IsNullOrEmpty (host_key))
- return host_key;
- else
- return null;
- }
-
-
- private string DeriveFingerprint (string public_key)
- {
- try {
- MD5 md5 = new MD5CryptoServiceProvider ();
- string key = public_key.Split (" ".ToCharArray ()) [2];
- byte [] b64_bytes = Convert.FromBase64String (key);
- byte [] md5_bytes = md5.ComputeHash (b64_bytes);
- string fingerprint = BitConverter.ToString (md5_bytes);
-
- return fingerprint.ToLower ().Replace ("-", ":");
-
- } catch (Exception e) {
- SparkleLogger.LogInfo ("Fetcher", "Failed creating fingerprint: " + e.Message + " " + e.StackTrace);
- return null;
- }
- }
-
-
- private void AcceptHostKey (string host_key, bool warn)
- {
- string ssh_config_path = Path.Combine (SparkleConfig.DefaultConfig.HomePath, ".ssh");
- string known_hosts_file_path = Path.Combine (ssh_config_path, "known_hosts");
-
- if (!File.Exists (known_hosts_file_path)) {
- if (!Directory.Exists (ssh_config_path))
- Directory.CreateDirectory (ssh_config_path);
-
- File.Create (known_hosts_file_path).Close ();
- }
-
- string host = RemoteUrl.Host;
- string known_hosts = File.ReadAllText (known_hosts_file_path);
- string [] known_hosts_lines = File.ReadAllLines (known_hosts_file_path);
-
- foreach (string line in known_hosts_lines) {
- if (line.StartsWith (host + " "))
- return;
- }
-
- if (known_hosts.EndsWith ("\n"))
- File.AppendAllText (known_hosts_file_path, host_key + "\n");
- else
- File.AppendAllText (known_hosts_file_path, "\n" + host_key + "\n");
-
- SparkleLogger.LogInfo ("Auth", "Accepted host key for " + host);
-
- if (warn)
- this.warnings.Add ("The following host key has been accepted:\n" + DeriveFingerprint (host_key));
- }
-
-
public static string GetBackend (string address)
{
if (address.StartsWith ("ssh+")) {
diff --git a/SparkleLib/SparkleFetcherSSH.cs b/SparkleLib/SparkleFetcherSSH.cs
new file mode 100644
index 0000000..d55a9de
--- /dev/null
+++ b/SparkleLib/SparkleFetcherSSH.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Security.Cryptography;
+using System.Threading;
+
+namespace SparkleLib {
+
+ public abstract class SparkleFetcherSSH : SparkleFetcherBase {
+
+ public SparkleFetcherSSH (SparkleFetcherInfo info) : base (info)
+ {
+ }
+
+
+ public override bool Fetch ()
+ {
+ if (RemoteUrl.Host.EndsWith(".onion")) {
+ // Tor has special domain names called ".onion addresses". They can only be
+ // resolved by using a proxy via tor. While the rest of the openssh suite
+ // fully supports proxying, ssh-keyscan does not, so we can't use it for .onion
+ SparkleLogger.LogInfo ("Auth", "using tor .onion address skipping ssh-keyscan");
+ } else if (!RemoteUrl.Scheme.StartsWith ("http")) {
+ string host_key = FetchHostKey ();
+
+ if (string.IsNullOrEmpty (RemoteUrl.Host) || host_key == null) {
+ SparkleLogger.LogInfo ("Auth", "Could not fetch host key");
+ this.errors.Add ("error: Could not fetch host key");
+
+ return false;
+ }
+
+ bool warn = true;
+ if (RequiredFingerprint != null) {
+ string host_fingerprint = DeriveFingerprint (host_key);
+
+ if (host_fingerprint == null || !RequiredFingerprint.Equals (host_fingerprint)) {
+ SparkleLogger.LogInfo ("Auth", "Fingerprint doesn't match");
+ this.errors.Add ("error: Host fingerprint doesn't match");
+
+ return false;
+ }
+
+ warn = false;
+ SparkleLogger.LogInfo ("Auth", "Fingerprint matches");
+
+ } else {
+ SparkleLogger.LogInfo ("Auth", "Skipping fingerprint check");
+ }
+
+ AcceptHostKey (host_key, warn);
+ }
+
+ return true;
+ }
+
+
+ private string FetchHostKey ()
+ {
+ SparkleLogger.LogInfo ("Auth", "Fetching host key for " + RemoteUrl.Host);
+
+ Process process = new Process ();
+ process.StartInfo.FileName = "ssh-keyscan";
+ process.StartInfo.WorkingDirectory = SparkleConfig.DefaultConfig.TmpPath;
+ process.StartInfo.UseShellExecute = false;
+ process.StartInfo.RedirectStandardOutput = true;
+ process.StartInfo.CreateNoWindow = true;
+ process.EnableRaisingEvents = true;
+
+ string [] key_types = {"rsa", "dsa", "ecdsa"};
+
+ foreach (string key_type in key_types) {
+ if (RemoteUrl.Port < 1)
+ process.StartInfo.Arguments = "-t " + key_type + " -p 22 " + RemoteUrl.Host;
+ else
+ process.StartInfo.Arguments = "-t " + key_type + " -p " + RemoteUrl.Port + " " + RemoteUrl.Host;
+
+ SparkleLogger.LogInfo ("Cmd", process.StartInfo.FileName + " " + process.StartInfo.Arguments);
+
+ process.Start ();
+ string host_key = process.StandardOutput.ReadToEnd ().Trim ();
+ process.WaitForExit ();
+
+ if (process.ExitCode == 0 && !string.IsNullOrWhiteSpace (host_key))
+ return host_key;
+ }
+
+ return null;
+ }
+
+
+ private string DeriveFingerprint (string public_key)
+ {
+ try {
+ MD5 md5 = new MD5CryptoServiceProvider ();
+ string key = public_key.Split (" ".ToCharArray ()) [2];
+ byte [] b64_bytes = Convert.FromBase64String (key);
+ byte [] md5_bytes = md5.ComputeHash (b64_bytes);
+ string fingerprint = BitConverter.ToString (md5_bytes);
+
+ return fingerprint.ToLower ().Replace ("-", ":");
+
+ } catch (Exception e) {
+ SparkleLogger.LogInfo ("Fetcher", "Failed creating fingerprint: " + e.Message + " " + e.StackTrace);
+ return null;
+ }
+ }
+
+
+ private void AcceptHostKey (string host_key, bool warn)
+ {
+ string ssh_config_path = Path.Combine (SparkleConfig.DefaultConfig.HomePath, ".ssh");
+ string known_hosts_file_path = Path.Combine (ssh_config_path, "known_hosts");
+
+ if (!File.Exists (known_hosts_file_path)) {
+ if (!Directory.Exists (ssh_config_path))
+ Directory.CreateDirectory (ssh_config_path);
+
+ File.Create (known_hosts_file_path).Close ();
+ }
+
+ string host = RemoteUrl.Host;
+ string known_hosts = File.ReadAllText (known_hosts_file_path);
+ string [] known_hosts_lines = File.ReadAllLines (known_hosts_file_path);
+
+ foreach (string line in known_hosts_lines) {
+ if (line.StartsWith (host + " "))
+ return;
+ }
+
+ if (known_hosts.EndsWith ("\n"))
+ File.AppendAllText (known_hosts_file_path, host_key + "\n");
+ else
+ File.AppendAllText (known_hosts_file_path, "\n" + host_key + "\n");
+
+ SparkleLogger.LogInfo ("Auth", "Accepted host key for " + host);
+
+ if (warn)
+ this.warnings.Add ("The following host key has been accepted:\n" + DeriveFingerprint (host_key));
+ }
+ }
+}
diff --git a/SparkleLib/SparkleRepoBase.cs b/SparkleLib/SparkleRepoBase.cs
index 1a87d37..9a7b91d 100755
--- a/SparkleLib/SparkleRepoBase.cs
+++ b/SparkleLib/SparkleRepoBase.cs
@@ -38,27 +38,32 @@ namespace SparkleLib {
HostIdentityChanged,
AuthenticationFailed,
DiskSpaceExceeded,
- LockedFiles,
+ UnreadableFiles,
NotFound
}
public abstract class SparkleRepoBase {
- public static bool UseCustomWatcher = false;
+
+ public abstract bool SyncUp ();
+ public abstract bool SyncDown ();
+ public abstract void RestoreFile (string path, string revision, string target_file_path);
+ public abstract bool HasUnsyncedChanges { get; set; }
+ public abstract bool HasLocalChanges { get; }
+ public abstract bool HasRemoteChanges { get; }
public abstract string CurrentRevision { get; }
public abstract double Size { get; }
public abstract double HistorySize { get; }
+
public abstract List<string> ExcludePaths { get; }
- public abstract bool HasUnsyncedChanges { get; set; }
- public abstract bool HasLocalChanges { get; }
- public abstract bool HasRemoteChanges { get; }
- public abstract bool SyncUp ();
- public abstract bool SyncDown ();
public abstract List<SparkleChangeSet> GetChangeSets ();
public abstract List<SparkleChangeSet> GetChangeSets (string path);
- public abstract void RestoreFile (string path, string revision, string target_file_path);
+
+
+ public static bool UseCustomWatcher = false;
+
public event SyncStatusChangedEventHandler SyncStatusChanged = delegate { };
public delegate void SyncStatusChangedEventHandler (SyncStatus new_status);
@@ -83,7 +88,7 @@ namespace SparkleLib {
public double ProgressPercentage { get; private set; }
public double ProgressSpeed { get; private set; }
- public string Identifier {
+ public virtual string Identifier {
get {
if (this.identifier != null)
return this.identifier;
@@ -114,12 +119,6 @@ namespace SparkleLib {
}
}
- public virtual string [] UnsyncedFilePaths {
- get {
- return new string [0];
- }
- }
-
protected SparkleConfig local_config;
@@ -127,16 +126,13 @@ namespace SparkleLib {
private string identifier;
private SparkleListenerBase listener;
private SparkleWatcher watcher;
- private TimeSpan poll_interval = PollInterval.Short;
- private DateTime last_poll = DateTime.Now;
- private DateTime progress_last_change = DateTime.Now;
- private TimeSpan progress_change_interval = new TimeSpan (0, 0, 0, 1);
- private Timers.Timer remote_timer = new Timers.Timer () { Interval = 5000 };
+ private TimeSpan poll_interval = PollInterval.Short;
+ private DateTime last_poll = DateTime.Now;
+ private DateTime progress_last_change = DateTime.Now;
+ private Timers.Timer remote_timer = new Timers.Timer () { Interval = 5000 };
private bool is_syncing {
- get {
- return (Status == SyncStatus.SyncUp || Status == SyncStatus.SyncDown || IsBuffering);
- }
+ get { return (Status == SyncStatus.SyncUp || Status == SyncStatus.SyncDown || IsBuffering); }
}
private static class PollInterval {
@@ -162,9 +158,7 @@ namespace SparkleLib {
string identifier_file_path = Path.Combine (LocalPath, ".sparkleshare");
File.SetAttributes (identifier_file_path, FileAttributes.Hidden);
- SyncStatusChanged += delegate (SyncStatus status) {
- Status = status;
- };
+ SyncStatusChanged += delegate (SyncStatus status) { Status = status; };
if (!UseCustomWatcher)
this.watcher = new SparkleWatcher (LocalPath);
@@ -176,20 +170,23 @@ namespace SparkleLib {
return;
int time_comparison = DateTime.Compare (this.last_poll, DateTime.Now.Subtract (this.poll_interval));
- bool time_to_poll = (time_comparison < 0);
- if (time_to_poll && !is_syncing) {
+ if (time_comparison < 0) {
+ if (HasUnsyncedChanges && !this.is_syncing)
+ SyncUpBase ();
+
this.last_poll = DateTime.Now;
- if (HasRemoteChanges) {
- this.poll_interval = PollInterval.Long;
+ if (HasRemoteChanges && !this.is_syncing)
SyncDownBase ();
- }
+
+ if (this.listener.IsConnected)
+ this.poll_interval = PollInterval.Long;
}
// In the unlikely case that we haven't synced up our
// changes or the server was down, sync up again
- if (HasUnsyncedChanges && !is_syncing && Error == ErrorStatus.None)
+ if (HasUnsyncedChanges && !this.is_syncing && Error == ErrorStatus.None)
SyncUpBase ();
};
}
@@ -197,18 +194,20 @@ namespace SparkleLib {
public void Initialize ()
{
- if (!UseCustomWatcher)
- this.watcher.ChangeEvent += OnFileActivity;
-
- // Sync up everything that changed
- // since we've been offline
+ // Sync up everything that changed since we've been offline
new Thread (() => {
- if (!this.is_syncing && (HasLocalChanges || HasUnsyncedChanges)) {
- SyncUpBase ();
+ if (HasRemoteChanges)
+ SyncDownBase ();
- while (HasLocalChanges && !this.is_syncing)
+ if (HasUnsyncedChanges || HasLocalChanges) {
+ do {
SyncUpBase ();
+
+ } while (HasLocalChanges);
}
+
+ if (!UseCustomWatcher)
+ this.watcher.ChangeEvent += OnFileActivity;
this.remote_timer.Start ();
@@ -245,12 +244,12 @@ namespace SparkleLib {
SparkleLogger.LogInfo ("Local", Name + " | Activity detected, waiting for it to settle...");
List<double> size_buffer = new List<double> ();
+ DirectoryInfo info = new DirectoryInfo (LocalPath);
do {
if (size_buffer.Count >= 4)
size_buffer.RemoveAt (0);
- DirectoryInfo info = new DirectoryInfo (LocalPath);
size_buffer.Add (CalculateSize (info));
if (size_buffer.Count >= 4 &&
@@ -265,6 +264,9 @@ namespace SparkleLib {
do {
SyncUpBase ();
+ if (Error == ErrorStatus.UnreadableFiles)
+ return;
+
} while (HasLocalChanges);
} else {
@@ -286,11 +288,8 @@ namespace SparkleLib {
{
if (Error == ErrorStatus.None || this.is_syncing)
return;
-
- if (Error == ErrorStatus.LockedFiles)
- SyncDownBase ();
- else
- SyncUpBase ();
+
+ SyncUpBase ();
}
@@ -306,7 +305,7 @@ namespace SparkleLib {
return;
// Only trigger the ProgressChanged event once per second
- if (DateTime.Compare (this.progress_last_change, DateTime.Now.Subtract (this.progress_change_interval)) >= 0)
+ if (DateTime.Compare (this.progress_last_change, DateTime.Now.Subtract (new TimeSpan (0, 0, 0, 1))) >= 0)
return;
if (progress_percentage == 100.0)
@@ -350,8 +349,8 @@ namespace SparkleLib {
if (Error == ErrorStatus.None && SyncUp ()) {
HasUnsyncedChanges = false;
- SyncStatusChanged (SyncStatus.Idle);
this.listener.Announce (new SparkleAnnouncement (Identifier, CurrentRevision));
+ SyncStatusChanged (SyncStatus.Idle);
} else {
this.poll_interval = PollInterval.Short;
@@ -386,7 +385,10 @@ namespace SparkleLib {
ChangeSets = GetChangeSets ();
- if (!pre_sync_revision.Equals (CurrentRevision) && ChangeSets != null && ChangeSets.Count > 0) {
+ if (!pre_sync_revision.Equals (CurrentRevision) &&
+ ChangeSets != null && ChangeSets.Count > 0 &&
+ !ChangeSets [0].User.Name.Equals (this.local_config.User.Name)) {
+
bool emit_change_event = true;
foreach (SparkleChange change in ChangeSets [0].Changes) {
@@ -406,8 +408,8 @@ namespace SparkleLib {
if (HasUnsyncedChanges) {
SyncStatusChanged (SyncStatus.SyncUp);
- SyncUp ();
- HasUnsyncedChanges = false;
+ if (SyncUp ())
+ HasUnsyncedChanges = false;
}
SyncStatusChanged (SyncStatus.Idle);
@@ -422,10 +424,10 @@ namespace SparkleLib {
ProgressPercentage = 0.0;
ProgressSpeed = 0.0;
+ SyncStatusChanged (SyncStatus.Idle);
+
if (!UseCustomWatcher)
this.watcher.Enable ();
-
- SyncStatusChanged (SyncStatus.Idle);
}
@@ -433,97 +435,58 @@ namespace SparkleLib {
{
this.listener = SparkleListenerFactory.CreateListener (Name, Identifier);
- if (this.listener.IsConnected) {
+ if (this.listener.IsConnected)
this.poll_interval = PollInterval.Long;
- new Thread (() => {
- if (!this.is_syncing && !HasLocalChanges && HasRemoteChanges)
- SyncDownBase ();
-
- }).Start ();
- }
-
- this.listener.Connected += ListenerConnectedDelegate;
this.listener.Disconnected += ListenerDisconnectedDelegate;
this.listener.AnnouncementReceived += ListenerAnnouncementReceivedDelegate;
- // Start listening
if (!this.listener.IsConnected && !this.listener.IsConnecting)
this.listener.Connect ();
}
- // 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 (!this.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;
- SparkleLogger.LogInfo (Name, "Falling back to polling");
+ SparkleLogger.LogInfo (Name, "Falling back to regular 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)) {
-
+ if (!announcement.FolderIdentifier.Equals (identifier))
+ return;
+
+ if (!announcement.Message.Equals (CurrentRevision)) {
while (this.is_syncing)
Thread.Sleep (100);
SparkleLogger.LogInfo (Name, "Syncing due to announcement");
SyncDownBase ();
-
- } else {
- if (announcement.FolderIdentifier.Equals (identifier))
- SparkleLogger.LogInfo (Name, "Not syncing, message is for current revision");
}
}
// Recursively gets a folder's size in bytes
- private double CalculateSize (DirectoryInfo parent)
+ private long CalculateSize (DirectoryInfo parent)
{
- if (!Directory.Exists (parent.ToString ()))
- return 0;
-
- double size = 0;
-
if (ExcludePaths.Contains (parent.Name))
return 0;
- try {
- foreach (FileInfo file in parent.GetFiles ()) {
- if (!file.Exists)
- return 0;
-
- size += file.Length;
- }
+ long size = 0;
+ try {
foreach (DirectoryInfo directory in parent.GetDirectories ())
size += CalculateSize (directory);
- } catch (Exception) {
- return 0;
+ foreach (FileInfo file in parent.GetFiles ())
+ size += file.Length;
+
+ } catch (Exception e) {
+ SparkleLogger.LogInfo ("Local", "Error calculating directory size", e);
}
return size;
@@ -535,7 +498,6 @@ namespace SparkleLib {
this.remote_timer.Stop ();
this.remote_timer.Dispose ();
- this.listener.Connected -= ListenerConnectedDelegate;
this.listener.Disconnected -= ListenerDisconnectedDelegate;
this.listener.AnnouncementReceived -= ListenerAnnouncementReceivedDelegate;
diff --git a/SparkleLib/SparkleUser.cs b/SparkleLib/SparkleUser.cs
index ef44bc4..f15234a 100644
--- a/SparkleLib/SparkleUser.cs
+++ b/SparkleLib/SparkleUser.cs
@@ -24,7 +24,11 @@ namespace SparkleLib {
public readonly string Name;
public readonly string Email;
+ public string PrivateKey;
+ public string PrivateKeyFilePath;
+
public string PublicKey;
+ public string PublicKeyFilePath;
public SparkleUser (string name, string email)
diff --git a/SparkleLib/SparkleWrappers.cs b/SparkleLib/SparkleWrappers.cs
index ca10851..15cc250 100644
--- a/SparkleLib/SparkleWrappers.cs
+++ b/SparkleLib/SparkleWrappers.cs
@@ -50,21 +50,11 @@ namespace SparkleLib {
case SparkleChangeType.Deleted: message = "deleted ‘{0}’"; break;
case SparkleChangeType.Moved: message = "moved ‘{0}’"; break;
}
-
- if (Changes.Count == 1) {
- return message = string.Format (message, Changes [0].Path);
-
- } else if (Changes.Count > 1) {
- message = string.Format (message, Changes [0].Path);
-
- if ((Changes.Count - 1) == 1)
- return string.Format (message + " and one other event", Changes.Count - 1);
- else
- return string.Format (message + " and {0} other events", Changes.Count - 1);
-
- } else {
+
+ if (Changes.Count > 0)
+ return string.Format (message, Changes [0].Path);
+ else
return "did something magical";
- }
}
}