Merge branch 'git-bin'
Conflicts: SparkleLib/Git/SparkleRepoGit.cs
This commit is contained in:
commit
e20dcd55ea
|
@ -30,12 +30,13 @@ namespace SparkleLib.Git {
|
||||||
public class SparkleFetcher : SparkleFetcherBase {
|
public class SparkleFetcher : SparkleFetcherBase {
|
||||||
|
|
||||||
private SparkleGit git;
|
private SparkleGit git;
|
||||||
|
private bool use_git_bin;
|
||||||
private string crypto_salt = "e0d592768d7cf99a"; // TODO: Make unique per repo
|
private string crypto_salt = "e0d592768d7cf99a"; // TODO: Make unique per repo
|
||||||
|
|
||||||
|
|
||||||
public SparkleFetcher (string server, string required_fingerprint, string remote_path,
|
public SparkleFetcher (string server, string required_fingerprint, string remote_path,
|
||||||
string target_folder, bool fetch_prior_history) : base (server, required_fingerprint, remote_path,
|
string target_folder, bool fetch_prior_history) : base (server, required_fingerprint,
|
||||||
target_folder, fetch_prior_history)
|
remote_path, target_folder, fetch_prior_history)
|
||||||
{
|
{
|
||||||
Uri uri = RemoteUrl;
|
Uri uri = RemoteUrl;
|
||||||
|
|
||||||
|
@ -60,6 +61,9 @@ namespace SparkleLib.Git {
|
||||||
} else if (uri.Host.Equals ("github.com")) {
|
} else if (uri.Host.Equals ("github.com")) {
|
||||||
uri = new Uri ("ssh://git@github.com" + uri.AbsolutePath);
|
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")) {
|
} else if (uri.Host.Equals ("gnome.org")) {
|
||||||
uri = new Uri ("ssh://git@gnome.org/git" + uri.AbsolutePath);
|
uri = new Uri ("ssh://git@gnome.org/git" + uri.AbsolutePath);
|
||||||
|
|
||||||
|
@ -73,6 +77,8 @@ namespace SparkleLib.Git {
|
||||||
else
|
else
|
||||||
uri = new Uri (uri.Scheme + "://git@" + uri.Host + ":" + uri.Port + uri.AbsolutePath);
|
uri = new Uri (uri.Scheme + "://git@" + uri.Host + ":" + uri.Port + uri.AbsolutePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.use_git_bin = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetFolder = target_folder;
|
TargetFolder = target_folder;
|
||||||
|
@ -128,14 +134,21 @@ namespace SparkleLib.Git {
|
||||||
} else {
|
} else {
|
||||||
SparkleHelpers.DebugInfo ("Fetcher", line);
|
SparkleHelpers.DebugInfo ("Fetcher", line);
|
||||||
|
|
||||||
if (line.StartsWith ("fatal:", true, null) ||
|
line = line.Trim (new char [] {' ', '@'});
|
||||||
line.StartsWith ("error:", true, null)) {
|
|
||||||
|
if (line.StartsWith ("fatal:", StringComparison.InvariantCultureIgnoreCase) ||
|
||||||
|
line.StartsWith ("error:", StringComparison.InvariantCultureIgnoreCase)) {
|
||||||
|
|
||||||
base.errors.Add (line);
|
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) {
|
if (number >= percentage) {
|
||||||
percentage = number;
|
percentage = number;
|
||||||
|
|
||||||
|
@ -148,8 +161,6 @@ namespace SparkleLib.Git {
|
||||||
|
|
||||||
this.git.WaitForExit ();
|
this.git.WaitForExit ();
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("Git", "Exit code: " + this.git.ExitCode);
|
|
||||||
|
|
||||||
if (this.git.ExitCode == 0) {
|
if (this.git.ExitCode == 0) {
|
||||||
while (percentage < 100) {
|
while (percentage < 100) {
|
||||||
percentage += 25;
|
percentage += 25;
|
||||||
|
@ -165,6 +176,7 @@ namespace SparkleLib.Git {
|
||||||
|
|
||||||
InstallConfiguration ();
|
InstallConfiguration ();
|
||||||
InstallExcludeRules ();
|
InstallExcludeRules ();
|
||||||
|
InstallAttributeRules ();
|
||||||
|
|
||||||
AddWarnings ();
|
AddWarnings ();
|
||||||
|
|
||||||
|
@ -179,11 +191,13 @@ namespace SparkleLib.Git {
|
||||||
public override bool IsFetchedRepoEmpty {
|
public override bool IsFetchedRepoEmpty {
|
||||||
get {
|
get {
|
||||||
SparkleGit git = new SparkleGit (TargetFolder, "rev-parse HEAD");
|
SparkleGit git = new SparkleGit (TargetFolder, "rev-parse HEAD");
|
||||||
|
git.StartInfo.RedirectStandardError = true;
|
||||||
git.Start ();
|
git.Start ();
|
||||||
|
|
||||||
// Reading the standard output HAS to go before
|
// Reading the standard output HAS to go before
|
||||||
// WaitForExit, or it will hang forever on output > 4096 bytes
|
// WaitForExit, or it will hang forever on output > 4096 bytes
|
||||||
git.StandardOutput.ReadToEnd ();
|
git.StandardOutput.ReadToEnd ();
|
||||||
|
git.StandardError.ReadToEnd ();
|
||||||
git.WaitForExit ();
|
git.WaitForExit ();
|
||||||
|
|
||||||
return (git.ExitCode != 0);
|
return (git.ExitCode != 0);
|
||||||
|
@ -210,7 +224,7 @@ namespace SparkleLib.Git {
|
||||||
string git_attributes_file_path = SparkleHelpers.CombineMore (
|
string git_attributes_file_path = SparkleHelpers.CombineMore (
|
||||||
TargetFolder, ".git", "info", "attributes");
|
TargetFolder, ".git", "info", "attributes");
|
||||||
|
|
||||||
File.WriteAllText (git_attributes_file_path, "* filter=crypto");
|
File.AppendAllText (git_attributes_file_path, "\n* filter=crypto");
|
||||||
|
|
||||||
|
|
||||||
// Store the password
|
// Store the password
|
||||||
|
@ -285,158 +299,99 @@ namespace SparkleLib.Git {
|
||||||
|
|
||||||
public override void Complete ()
|
public override void Complete ()
|
||||||
{
|
{
|
||||||
if (IsFetchedRepoEmpty)
|
if (!IsFetchedRepoEmpty) {
|
||||||
return;
|
SparkleGit git = new SparkleGit (TargetFolder, "checkout --quiet HEAD");
|
||||||
|
git.Start ();
|
||||||
|
git.WaitForExit ();
|
||||||
|
}
|
||||||
|
|
||||||
SparkleGit git = new SparkleGit (TargetFolder, "checkout --quiet HEAD");
|
base.Complete ();
|
||||||
git.Start ();
|
|
||||||
git.WaitForExit ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Install the user's name and email and some config into
|
|
||||||
// the newly cloned repository
|
|
||||||
private void InstallConfiguration ()
|
private void InstallConfiguration ()
|
||||||
{
|
{
|
||||||
string repo_config_file_path = SparkleHelpers.CombineMore (TargetFolder, ".git", "config");
|
string [] settings = new string [] {
|
||||||
string config = File.ReadAllText (repo_config_file_path);
|
"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,
|
if (this.use_git_bin)
|
||||||
"[core]" + n +
|
InstallGitBinConfiguration ();
|
||||||
"\tquotepath = false" + n + // Show special characters in the logs
|
}
|
||||||
"\tpackedGitLimit = 128m" + n +
|
|
||||||
"\tautocrlf = false" + n +
|
|
||||||
"\tsafecrlf = false" + n +
|
|
||||||
"\tpackedGitWindowSize = 128m" + n);
|
|
||||||
|
|
||||||
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
|
public void InstallGitBinConfiguration ()
|
||||||
config = config.Replace ("ignorecase = true", "ignorecase = false");
|
{
|
||||||
|
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
|
foreach (string setting in settings) {
|
||||||
config = config.Replace ("filemode = true", "filemode = false");
|
SparkleGit git_config = new SparkleGit (TargetFolder, "config " + setting);
|
||||||
|
git_config.Start ();
|
||||||
// Write the config to the file
|
git_config.WaitForExit ();
|
||||||
File.WriteAllText (repo_config_file_path, config);
|
}
|
||||||
SparkleHelpers.DebugInfo ("Fetcher", "Added configuration to '" + repo_config_file_path + "'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Add a .gitignore file to the repo
|
// Add a .gitignore file to the repo
|
||||||
private void InstallExcludeRules ()
|
private void InstallExcludeRules ()
|
||||||
{
|
{
|
||||||
DirectoryInfo info = Directory.CreateDirectory (
|
// Compile a list of files we want Git to ignore
|
||||||
SparkleHelpers.CombineMore (TargetFolder, ".git", "info"));
|
string exclude_rules_file_path = SparkleHelpers.CombineMore (TargetFolder, ".git", "info", "exclude");
|
||||||
|
|
||||||
// File that lists the files we want git to ignore
|
|
||||||
string exclude_rules_file_path = Path.Combine (info.FullName, "exclude");
|
|
||||||
TextWriter writer = new StreamWriter (exclude_rules_file_path);
|
TextWriter writer = new StreamWriter (exclude_rules_file_path);
|
||||||
|
|
||||||
foreach (string exclude_rule in ExcludeRules)
|
foreach (string exclude_rule in ExcludeRules)
|
||||||
writer.WriteLine (exclude_rule);
|
writer.WriteLine (exclude_rule);
|
||||||
|
|
||||||
writer.Close ();
|
writer.Close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// File that lists the files we want don't want git to compress.
|
private void InstallAttributeRules ()
|
||||||
// Not compressing the already compressed files saves us memory
|
{
|
||||||
// usage and increases speed
|
string attribute_rules_file_path = SparkleHelpers.CombineMore (TargetFolder, ".git", "info", "attributes");
|
||||||
string no_compression_rules_file_path = Path.Combine (info.FullName, "attributes");
|
TextWriter writer = new StreamWriter (attribute_rules_file_path);
|
||||||
writer = new StreamWriter (no_compression_rules_file_path);
|
|
||||||
|
|
||||||
// Images
|
if (this.use_git_bin) {
|
||||||
writer.WriteLine ("*.jpg -delta");
|
writer.WriteLine ("* filter=bin binary");
|
||||||
writer.WriteLine ("*.jpeg -delta");
|
|
||||||
writer.WriteLine ("*.JPG -delta");
|
|
||||||
writer.WriteLine ("*.JPEG -delta");
|
|
||||||
|
|
||||||
writer.WriteLine ("*.png -delta");
|
} else {
|
||||||
writer.WriteLine ("*.PNG -delta");
|
// 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");
|
foreach (string extension in extensions) {
|
||||||
writer.WriteLine ("*.TIFF -delta");
|
writer.WriteLine ("*." + extension + " -delta");
|
||||||
|
writer.WriteLine ("*." + extension.ToUpper () + " -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");
|
|
||||||
|
|
||||||
writer.Close ();
|
writer.Close ();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,18 +22,61 @@ using SparkleLib;
|
||||||
|
|
||||||
namespace SparkleLib.Git {
|
namespace SparkleLib.Git {
|
||||||
|
|
||||||
public class SparkleGit : Process {
|
public abstract class SparkleProcess : Process {
|
||||||
|
|
||||||
public static string ExecPath = null;
|
public SparkleProcess (string path, string args) : base ()
|
||||||
public static string Path = null;
|
|
||||||
|
|
||||||
|
|
||||||
public SparkleGit (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;
|
EnableRaisingEvents = true;
|
||||||
StartInfo.FileName = Path;
|
StartInfo.FileName = GitPath;
|
||||||
StartInfo.RedirectStandardOutput = true;
|
StartInfo.RedirectStandardOutput = true;
|
||||||
StartInfo.UseShellExecute = false;
|
StartInfo.UseShellExecute = false;
|
||||||
StartInfo.WorkingDirectory = path;
|
StartInfo.WorkingDirectory = path;
|
||||||
|
@ -44,40 +87,26 @@ namespace SparkleLib.Git {
|
||||||
else
|
else
|
||||||
StartInfo.Arguments = "--exec-path=\"" + ExecPath + "\" " + args;
|
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),
|
if (string.IsNullOrEmpty (GitBinPath))
|
||||||
"git " + StartInfo.Arguments);
|
GitBinPath = LocateCommand ("git-bin");
|
||||||
|
|
||||||
try {
|
EnableRaisingEvents = true;
|
||||||
base.Start ();
|
StartInfo.FileName = GitBinPath;
|
||||||
|
StartInfo.RedirectStandardOutput = true;
|
||||||
} catch (Exception e) {
|
StartInfo.UseShellExecute = false;
|
||||||
SparkleHelpers.DebugInfo ("Cmd", "There's a problem running Git: " + e.Message);
|
StartInfo.WorkingDirectory = path;
|
||||||
Environment.Exit (-1);
|
StartInfo.CreateNoWindow = true;
|
||||||
}
|
StartInfo.Arguments = args;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,18 @@ namespace SparkleLib.Git {
|
||||||
|
|
||||||
public class SparkleRepo : SparkleRepoBase {
|
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)
|
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 (size_file_path, size.ToString ());
|
||||||
File.WriteAllText (history_size_file_path, history_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 {
|
public override string [] UnsyncedFilePaths {
|
||||||
get {
|
get {
|
||||||
|
@ -152,7 +152,7 @@ namespace SparkleLib.Git {
|
||||||
SparkleHelpers.DebugInfo ("Git", Name + " | Checking for remote changes...");
|
SparkleHelpers.DebugInfo ("Git", Name + " | Checking for remote changes...");
|
||||||
|
|
||||||
string current_revision = CurrentRevision;
|
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.Start ();
|
||||||
git.WaitForExit ();
|
git.WaitForExit ();
|
||||||
|
@ -189,7 +189,25 @@ namespace SparkleLib.Git {
|
||||||
Commit (message);
|
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
|
"push --progress " + // Redirects progress stats to standarderror
|
||||||
"\"" + RemoteUrl + "\" master");
|
"\"" + RemoteUrl + "\" master");
|
||||||
|
|
||||||
|
@ -249,10 +267,13 @@ namespace SparkleLib.Git {
|
||||||
UpdateSizes ();
|
UpdateSizes ();
|
||||||
ChangeSets = GetChangeSets ();
|
ChangeSets = GetChangeSets ();
|
||||||
|
|
||||||
if (git.ExitCode == 0)
|
if (git.ExitCode == 0) {
|
||||||
|
ClearCache ();
|
||||||
return true;
|
return true;
|
||||||
else
|
|
||||||
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,6 +340,7 @@ namespace SparkleLib.Git {
|
||||||
);
|
);
|
||||||
|
|
||||||
ChangeSets = GetChangeSets ();
|
ChangeSets = GetChangeSets ();
|
||||||
|
ClearCache ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -383,7 +405,7 @@ namespace SparkleLib.Git {
|
||||||
{
|
{
|
||||||
SparkleGit git;
|
SparkleGit git;
|
||||||
|
|
||||||
if (!this.author_set) {
|
if (!this.user_is_set) {
|
||||||
git = new SparkleGit (LocalPath,
|
git = new SparkleGit (LocalPath,
|
||||||
"config user.name \"" + SparkleConfig.DefaultConfig.User.Name + "\"");
|
"config user.name \"" + SparkleConfig.DefaultConfig.User.Name + "\"");
|
||||||
|
|
||||||
|
@ -396,7 +418,7 @@ namespace SparkleLib.Git {
|
||||||
git.Start ();
|
git.Start ();
|
||||||
git.WaitForExit ();
|
git.WaitForExit ();
|
||||||
|
|
||||||
this.author_set = true;
|
this.user_is_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
git = new SparkleGit (LocalPath,
|
git = new SparkleGit (LocalPath,
|
||||||
|
@ -760,11 +782,6 @@ namespace SparkleLib.Git {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resolves special characters like \303\244 (ä) to their real character
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="file_path"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private string ResolveSpecialChars (string s)
|
private string ResolveSpecialChars (string s)
|
||||||
{
|
{
|
||||||
StringBuilder builder = new StringBuilder (s.Length);
|
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
|
// Git doesn't track empty directories, so this method
|
||||||
// fills them all with a hidden empty file.
|
// fills them all with a hidden empty file.
|
||||||
//
|
//
|
||||||
|
|
|
@ -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");
|
XmlNode node_name = CreateElement ("name");
|
||||||
node_name.InnerText = name;
|
node_name.InnerText = name;
|
||||||
|
|
||||||
|
XmlNode node_identifier = CreateElement ("identifier");
|
||||||
|
node_identifier.InnerText = identifier;
|
||||||
|
|
||||||
XmlNode node_url = CreateElement ("url");
|
XmlNode node_url = CreateElement ("url");
|
||||||
node_url.InnerText = url;
|
node_url.InnerText = url;
|
||||||
|
|
||||||
|
@ -223,6 +226,7 @@ namespace SparkleLib {
|
||||||
|
|
||||||
XmlNode node_folder = CreateNode (XmlNodeType.Element, "folder", null);
|
XmlNode node_folder = CreateNode (XmlNodeType.Element, "folder", null);
|
||||||
node_folder.AppendChild (node_name);
|
node_folder.AppendChild (node_name);
|
||||||
|
node_folder.AppendChild (node_identifier);
|
||||||
node_folder.AppendChild (node_url);
|
node_folder.AppendChild (node_url);
|
||||||
node_folder.AppendChild (node_backend);
|
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)
|
public string GetBackendForFolder (string name)
|
||||||
{
|
{
|
||||||
return GetFolderValue (name, "backend");
|
return GetFolderValue (name, "backend");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public string GetIdentifierForFolder (string name)
|
||||||
|
{
|
||||||
|
return GetFolderValue (name, "identifier");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public string GetUrlForFolder (string name)
|
public string GetUrlForFolder (string name)
|
||||||
{
|
{
|
||||||
return GetFolderValue (name, "url");
|
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)
|
public bool SetFolderOptionalAttribute (string folder_name, string key, string value)
|
||||||
{
|
{
|
||||||
XmlNode folder = GetFolder (folder_name);
|
XmlNode folder = GetFolder (folder_name);
|
||||||
|
@ -304,11 +334,10 @@ namespace SparkleLib {
|
||||||
{
|
{
|
||||||
XmlNode folder = GetFolder(name);
|
XmlNode folder = GetFolder(name);
|
||||||
|
|
||||||
if ((folder != null) && (folder [key] != null)) {
|
if ((folder != null) && (folder [key] != null))
|
||||||
return folder [key].InnerText;
|
return folder [key].InnerText;
|
||||||
}
|
else
|
||||||
|
return null;
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,6 @@ namespace SparkleLib {
|
||||||
|
|
||||||
public abstract bool Fetch ();
|
public abstract bool Fetch ();
|
||||||
public abstract void Stop ();
|
public abstract void Stop ();
|
||||||
public abstract void Complete ();
|
|
||||||
public abstract bool IsFetchedRepoEmpty { get; }
|
public abstract bool IsFetchedRepoEmpty { get; }
|
||||||
public abstract bool IsFetchedRepoPasswordCorrect (string password);
|
public abstract bool IsFetchedRepoPasswordCorrect (string password);
|
||||||
public abstract void EnableFetchedRepoCrypto (string password);
|
public abstract void EnableFetchedRepoCrypto (string password);
|
||||||
|
@ -51,6 +50,7 @@ namespace SparkleLib {
|
||||||
public readonly bool FetchPriorHistory = false;
|
public readonly bool FetchPriorHistory = false;
|
||||||
public string TargetFolder { get; protected set; }
|
public string TargetFolder { get; protected set; }
|
||||||
public bool IsActive { get; private set; }
|
public bool IsActive { get; private set; }
|
||||||
|
public string Identifier;
|
||||||
|
|
||||||
public string [] Warnings {
|
public string [] Warnings {
|
||||||
get {
|
get {
|
||||||
|
@ -66,13 +66,34 @@ namespace SparkleLib {
|
||||||
|
|
||||||
|
|
||||||
protected List<string> warnings = new List<string> ();
|
protected List<string> warnings = new List<string> ();
|
||||||
protected List<string> errors = new List<string> ();
|
protected List<string> errors = new List<string> ();
|
||||||
|
|
||||||
|
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;
|
private Thread thread;
|
||||||
|
|
||||||
|
|
||||||
public SparkleFetcherBase (string server, string required_fingerprint, string remote_path,
|
public SparkleFetcherBase (string server, string required_fingerprint,
|
||||||
string target_folder, bool fetch_prior_history)
|
string remote_path, string target_folder, bool fetch_prior_history)
|
||||||
{
|
{
|
||||||
RequiredFingerprint = required_fingerprint;
|
RequiredFingerprint = required_fingerprint;
|
||||||
FetchPriorHistory = fetch_prior_history;
|
FetchPriorHistory = fetch_prior_history;
|
||||||
|
@ -100,12 +121,11 @@ namespace SparkleLib {
|
||||||
if (Started != null)
|
if (Started != null)
|
||||||
Started ();
|
Started ();
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("Fetcher", "[" + TargetFolder + "] Fetching folder: " + RemoteUrl);
|
SparkleHelpers.DebugInfo ("Fetcher", TargetFolder + " | Fetching folder: " + RemoteUrl);
|
||||||
|
|
||||||
if (Directory.Exists (TargetFolder))
|
if (Directory.Exists (TargetFolder))
|
||||||
Directory.Delete (TargetFolder, true);
|
Directory.Delete (TargetFolder, true);
|
||||||
|
|
||||||
|
|
||||||
string host = RemoteUrl.Host;
|
string host = RemoteUrl.Host;
|
||||||
string host_key = GetHostKey ();
|
string host_key = GetHostKey ();
|
||||||
|
|
||||||
|
@ -116,7 +136,6 @@ namespace SparkleLib {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool warn = true;
|
bool warn = true;
|
||||||
if (RequiredFingerprint != null) {
|
if (RequiredFingerprint != null) {
|
||||||
string host_fingerprint = GetFingerprint (host_key);
|
string host_fingerprint = GetFingerprint (host_key);
|
||||||
|
@ -141,35 +160,99 @@ namespace SparkleLib {
|
||||||
|
|
||||||
AcceptHostKey (host_key, warn);
|
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 {
|
IsActive = false;
|
||||||
if (Fetch ()) {
|
|
||||||
Thread.Sleep (500);
|
|
||||||
SparkleHelpers.DebugInfo ("Fetcher", "Finished");
|
|
||||||
|
|
||||||
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
|
if (Finished != null)
|
||||||
bool repo_is_encrypted = RemoteUrl.ToString ().Contains ("crypto");
|
Finished (repo_is_encrypted, IsFetchedRepoEmpty, Warnings);
|
||||||
|
|
||||||
if (Finished != null)
|
} else {
|
||||||
Finished (repo_is_encrypted, IsFetchedRepoEmpty, Warnings);
|
Thread.Sleep (500);
|
||||||
|
SparkleHelpers.DebugInfo ("Fetcher", "Failed");
|
||||||
|
|
||||||
} else {
|
IsActive = false;
|
||||||
Thread.Sleep (500);
|
|
||||||
SparkleHelpers.DebugInfo ("Fetcher", "Failed");
|
|
||||||
|
|
||||||
IsActive = false;
|
if (Failed != null)
|
||||||
|
Failed ();
|
||||||
if (Failed != null)
|
}
|
||||||
Failed ();
|
})
|
||||||
}
|
);
|
||||||
}));
|
|
||||||
|
|
||||||
this.thread.Start ();
|
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 ()
|
public void Dispose ()
|
||||||
{
|
{
|
||||||
if (this.thread != null) {
|
if (this.thread != null) {
|
||||||
|
@ -178,7 +261,7 @@ namespace SparkleLib {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void OnProgressChanged (double percentage) {
|
protected void OnProgressChanged (double percentage) {
|
||||||
if (ProgressChanged != null)
|
if (ProgressChanged != null)
|
||||||
ProgressChanged (percentage);
|
ProgressChanged (percentage);
|
||||||
|
@ -199,7 +282,7 @@ namespace SparkleLib {
|
||||||
process.StartInfo.RedirectStandardOutput = true;
|
process.StartInfo.RedirectStandardOutput = true;
|
||||||
process.StartInfo.CreateNoWindow = true;
|
process.StartInfo.CreateNoWindow = true;
|
||||||
|
|
||||||
process.StartInfo.FileName = "ssh-keyscan";
|
process.StartInfo.FileName = "ssh-keyscan";
|
||||||
process.StartInfo.Arguments = "-t rsa " + host;
|
process.StartInfo.Arguments = "-t rsa " + host;
|
||||||
|
|
||||||
process.Start ();
|
process.Start ();
|
||||||
|
@ -240,7 +323,7 @@ namespace SparkleLib {
|
||||||
// WaitForExit, or it will hang forever on output > 4096 bytes
|
// WaitForExit, or it will hang forever on output > 4096 bytes
|
||||||
string fingerprint = process.StandardOutput.ReadToEnd ().Trim ();
|
string fingerprint = process.StandardOutput.ReadToEnd ().Trim ();
|
||||||
process.WaitForExit ();
|
process.WaitForExit ();
|
||||||
|
|
||||||
File.Delete (tmp_file_path);
|
File.Delete (tmp_file_path);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -286,98 +369,5 @@ namespace SparkleLib {
|
||||||
if (warn)
|
if (warn)
|
||||||
this.warnings.Add ("The following host key has been accepted:\n" + GetFingerprint (host_key));
|
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"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ namespace SparkleLib {
|
||||||
public event DisconnectedEventHandler Disconnected;
|
public event DisconnectedEventHandler Disconnected;
|
||||||
public delegate void DisconnectedEventHandler ();
|
public delegate void DisconnectedEventHandler ();
|
||||||
|
|
||||||
public event ReceivedEventHandler Received;
|
public event AnnouncementReceivedEventHandler AnnouncementReceived;
|
||||||
public delegate void ReceivedEventHandler (SparkleAnnouncement announcement);
|
public delegate void AnnouncementReceivedEventHandler (SparkleAnnouncement announcement);
|
||||||
|
|
||||||
public readonly Uri Server;
|
public readonly Uri Server;
|
||||||
|
|
||||||
|
@ -175,8 +175,8 @@ namespace SparkleLib {
|
||||||
AddRecentAnnouncement (announcement);
|
AddRecentAnnouncement (announcement);
|
||||||
this.queue_down [announcement.FolderIdentifier] = announcement;
|
this.queue_down [announcement.FolderIdentifier] = announcement;
|
||||||
|
|
||||||
if (Received != null)
|
if (AnnouncementReceived != null)
|
||||||
Received (announcement);
|
AnnouncementReceived (announcement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -83,13 +83,16 @@ namespace SparkleLib {
|
||||||
if (File.Exists (id_path))
|
if (File.Exists (id_path))
|
||||||
this.identifier = File.ReadAllText (id_path).Trim ();
|
this.identifier = File.ReadAllText (id_path).Trim ();
|
||||||
|
|
||||||
if (this.identifier != null && this.identifier.Length > 0) {
|
if (!string.IsNullOrEmpty (this.identifier)) {
|
||||||
return this.identifier;
|
return this.identifier;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Random random = new Random ();
|
string config_identifier = SparkleConfig.DefaultConfig.GetIdentifierForFolder (Name);
|
||||||
string number = "" + random.Next () + "" + random.Next () + "" + random.Next ();
|
|
||||||
this.identifier = SparkleHelpers.SHA1 (number);
|
if (!string.IsNullOrEmpty (config_identifier))
|
||||||
|
this.identifier = config_identifier;
|
||||||
|
else
|
||||||
|
this.identifier = SparkleFetcherBase.CreateIdentifier ();
|
||||||
|
|
||||||
File.WriteAllText (id_path, this.identifier);
|
File.WriteAllText (id_path, this.identifier);
|
||||||
File.SetAttributes (id_path, FileAttributes.Hidden);
|
File.SetAttributes (id_path, FileAttributes.Hidden);
|
||||||
|
@ -148,9 +151,6 @@ namespace SparkleLib {
|
||||||
|
|
||||||
this.identifier = Identifier;
|
this.identifier = Identifier;
|
||||||
|
|
||||||
if (CurrentRevision == null)
|
|
||||||
CreateInitialChangeSet ();
|
|
||||||
|
|
||||||
ChangeSets = GetChangeSets ();
|
ChangeSets = GetChangeSets ();
|
||||||
this.watcher = CreateWatcher ();
|
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<SparkleChangeSet> GetChangeSets () {
|
public List<SparkleChangeSet> GetChangeSets () {
|
||||||
return GetChangeSets (30);
|
return GetChangeSets (30);
|
||||||
}
|
}
|
||||||
|
@ -427,52 +405,15 @@ namespace SparkleLib {
|
||||||
|
|
||||||
new Thread (
|
new Thread (
|
||||||
new ThreadStart (delegate {
|
new ThreadStart (delegate {
|
||||||
if (!is_syncing && HasRemoteChanges)
|
if (!is_syncing && !HasLocalChanges && HasRemoteChanges)
|
||||||
SyncDownBase ();
|
SyncDownBase ();
|
||||||
})
|
})
|
||||||
).Start ();
|
).Start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop polling when the connection to the irc channel is succesful
|
this.listener.Connected += ListenerConnectedDelegate;
|
||||||
this.listener.Connected += delegate {
|
this.listener.Disconnected += ListenerDisconnectedDelegate;
|
||||||
this.poll_interval = PollInterval.Long;
|
this.listener.AnnouncementReceived += ListenerAnnouncementReceivedDelegate;
|
||||||
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");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Start listening
|
// Start listening
|
||||||
if (!this.listener.IsConnected && !this.listener.IsConnecting)
|
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 DateTime progress_last_change = DateTime.Now;
|
||||||
private TimeSpan progress_change_interval = new TimeSpan (0, 0, 0, 1);
|
private TimeSpan progress_change_interval = new TimeSpan (0, 0, 0, 1);
|
||||||
|
|
||||||
|
@ -535,8 +523,15 @@ namespace SparkleLib {
|
||||||
|
|
||||||
public void Dispose ()
|
public void Dispose ()
|
||||||
{
|
{
|
||||||
|
this.remote_timer.Stop ();
|
||||||
this.remote_timer.Dispose ();
|
this.remote_timer.Dispose ();
|
||||||
|
|
||||||
|
this.listener.Connected -= ListenerConnectedDelegate;
|
||||||
|
this.listener.Disconnected -= ListenerDisconnectedDelegate;
|
||||||
|
this.listener.AnnouncementReceived -= ListenerAnnouncementReceivedDelegate;
|
||||||
|
|
||||||
this.listener.Dispose ();
|
this.listener.Dispose ();
|
||||||
|
this.watcher.Dispose ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
50
SparkleLib/SparkleWatcherFactory.cs
Normal file
50
SparkleLib/SparkleWatcherFactory.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// SparkleShare, a collaboration and sharing tool.
|
||||||
|
// Copyright (C) 2010 Hylke Bons <hylkebons@gmail.com>
|
||||||
|
//
|
||||||
|
// 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace SparkleLib {
|
||||||
|
|
||||||
|
public static class SparkleListenerFactory {
|
||||||
|
|
||||||
|
private static List<SparkleWatcher> watchers = new List<SparkleWatcher> ();
|
||||||
|
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ namespace SparkleShare {
|
||||||
|
|
||||||
|
|
||||||
// Let's use the bundled git first
|
// Let's use the bundled git first
|
||||||
SparkleLib.Git.SparkleGit.Path =
|
SparkleLib.Git.SparkleGit.GitPath =
|
||||||
Path.Combine (NSBundle.MainBundle.ResourcePath,
|
Path.Combine (NSBundle.MainBundle.ResourcePath,
|
||||||
"git", "libexec", "git-core", "git");
|
"git", "libexec", "git-core", "git");
|
||||||
|
|
||||||
|
|
|
@ -34,12 +34,8 @@ namespace SparkleShare {
|
||||||
|
|
||||||
public SparkleRepoBase [] Repositories {
|
public SparkleRepoBase [] Repositories {
|
||||||
get {
|
get {
|
||||||
lock (this.repo_lock) {
|
lock (this.repo_lock)
|
||||||
SparkleRepoBase [] repositories =
|
return this.repositories.GetRange (0, this.repositories.Count).ToArray ();
|
||||||
this.repositories.GetRange (0, this.repositories.Count).ToArray ();
|
|
||||||
|
|
||||||
return repositories;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,8 +166,8 @@ namespace SparkleShare {
|
||||||
|
|
||||||
|
|
||||||
private SparkleFetcherBase fetcher;
|
private SparkleFetcherBase fetcher;
|
||||||
private Object repo_lock = new Object ();
|
private Object repo_lock = new Object ();
|
||||||
private Object delete_watcher_lock = new Object ();
|
private Object check_repos_lock = new Object ();
|
||||||
|
|
||||||
|
|
||||||
// Short alias for the translations
|
// 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 ()
|
public virtual void Initialize ()
|
||||||
{
|
{
|
||||||
SparklePlugin.PluginsPath = PluginsPath;
|
SparklePlugin.PluginsPath = PluginsPath;
|
||||||
|
@ -201,69 +304,17 @@ namespace SparkleShare {
|
||||||
ImportPrivateKey ();
|
ImportPrivateKey ();
|
||||||
|
|
||||||
// Watch the SparkleShare folder
|
// Watch the SparkleShare folder
|
||||||
FileSystemWatcher watcher = new FileSystemWatcher (SparkleConfig.DefaultConfig.FoldersPath) {
|
FileSystemWatcher watcher = new FileSystemWatcher () {
|
||||||
|
Filter = "*",
|
||||||
IncludeSubdirectories = false,
|
IncludeSubdirectories = false,
|
||||||
EnableRaisingEvents = true,
|
Path = SparkleConfig.DefaultConfig.FoldersPath
|
||||||
Filter = "*"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
watcher.Deleted += delegate (object o, FileSystemEventArgs args) {
|
watcher.Deleted += OnFolderActivity;
|
||||||
lock (this.delete_watcher_lock) {
|
watcher.Created += OnFolderActivity;
|
||||||
foreach (string folder_name in SparkleConfig.DefaultConfig.Folders) {
|
watcher.Renamed += OnFolderActivity;
|
||||||
string folder_path = new SparkleFolder (folder_name).FullPath;
|
|
||||||
|
|
||||||
if (!Directory.Exists (folder_path)) {
|
watcher.EnableRaisingEvents = true;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,11 +378,9 @@ namespace SparkleShare {
|
||||||
|
|
||||||
string path = new SparkleFolder (name).FullPath;
|
string path = new SparkleFolder (name).FullPath;
|
||||||
|
|
||||||
lock (this.repo_lock) {
|
foreach (SparkleRepoBase repo in Repositories) {
|
||||||
foreach (SparkleRepoBase repo in Repositories) {
|
if (repo.LocalPath.Equals (path))
|
||||||
if (repo.LocalPath.Equals (path))
|
return repo.ChangeSets;
|
||||||
return repo.ChangeSets;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -511,7 +560,6 @@ namespace SparkleShare {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Adds a repository to the list of repositories
|
|
||||||
private void AddRepository (string folder_path)
|
private void AddRepository (string folder_path)
|
||||||
{
|
{
|
||||||
SparkleRepoBase repo = null;
|
SparkleRepoBase repo = null;
|
||||||
|
@ -531,16 +579,8 @@ namespace SparkleShare {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repo.ChangesDetected += delegate {
|
||||||
repo.NewChangeSet += delegate (SparkleChangeSet change_set) {
|
UpdateState ();
|
||||||
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.SyncStatusChanged += delegate (SyncStatus status) {
|
repo.SyncStatusChanged += delegate (SyncStatus status) {
|
||||||
|
@ -565,8 +605,15 @@ namespace SparkleShare {
|
||||||
UpdateState ();
|
UpdateState ();
|
||||||
};
|
};
|
||||||
|
|
||||||
repo.ChangesDetected += delegate {
|
repo.NewChangeSet += delegate (SparkleChangeSet change_set) {
|
||||||
UpdateState ();
|
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);
|
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)
|
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++) {
|
if (repo.LocalPath.Equals (folder_path)) {
|
||||||
SparkleRepoBase repo = Repositories [i];
|
|
||||||
|
|
||||||
if (repo.Name.Equals (folder_name)) {
|
|
||||||
repo.Dispose ();
|
repo.Dispose ();
|
||||||
|
this.repositories.Remove (repo);
|
||||||
lock (this.repo_lock) {
|
|
||||||
this.repositories.Remove (repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
repo = null;
|
repo = null;
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Updates the list of repositories with all the
|
|
||||||
// folders in the SparkleShare folder
|
|
||||||
private void PopulateRepositories ()
|
private void PopulateRepositories ()
|
||||||
{
|
{
|
||||||
lock (this.repo_lock) {
|
CheckRepositories ();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RepositoriesLoaded = true;
|
RepositoriesLoaded = true;
|
||||||
|
|
||||||
if (FolderListChanged != null)
|
if (FolderListChanged != null)
|
||||||
|
@ -910,7 +937,8 @@ namespace SparkleShare {
|
||||||
Directory.Move (this.fetcher.TargetFolder, target_folder_path);
|
Directory.Move (this.fetcher.TargetFolder, target_folder_path);
|
||||||
|
|
||||||
string backend = SparkleFetcherBase.GetBackend (this.fetcher.RemoteUrl.AbsolutePath);
|
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)
|
if (FolderFetched != null)
|
||||||
FolderFetched (this.fetcher.RemoteUrl.ToString (), this.fetcher.Warnings.ToArray ());
|
FolderFetched (this.fetcher.RemoteUrl.ToString (), this.fetcher.Warnings.ToArray ());
|
||||||
|
@ -921,9 +949,7 @@ namespace SparkleShare {
|
||||||
target_folder_name, "announcements_url", announcements_url);
|
target_folder_name, "announcements_url", announcements_url);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
lock (this.repo_lock) {
|
AddRepository (target_folder_path);
|
||||||
AddRepository (target_folder_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FolderListChanged != null)
|
if (FolderListChanged != null)
|
||||||
FolderListChanged ();
|
FolderListChanged ();
|
||||||
|
|
Loading…
Reference in a new issue