diff --git a/SparkleLib/Git/SparkleFetcherGit.cs b/SparkleLib/Git/SparkleFetcherGit.cs index d83057b5..a9a9b3e1 100755 --- a/SparkleLib/Git/SparkleFetcherGit.cs +++ b/SparkleLib/Git/SparkleFetcherGit.cs @@ -29,9 +29,12 @@ namespace SparkleLib.Git { private SparkleGit git; private bool use_git_bin; - private string cached_salt; + private Regex progress_regex = new Regex (@"([0-9]+)%", RegexOptions.Compiled); + private Regex speed_regex = new Regex (@"([0-9\.]+) ([KM])iB/s", RegexOptions.Compiled); + + private string crypto_salt { get { if (!string.IsNullOrEmpty (this.cached_salt)) @@ -123,7 +126,6 @@ namespace SparkleLib.Git { this.git.Start (); double percentage = 1.0; - Regex progress_regex = new Regex (@"([0-9]+)%", RegexOptions.Compiled); DateTime last_change = DateTime.Now; TimeSpan change_interval = new TimeSpan (0, 0, 0, 1); @@ -131,19 +133,42 @@ namespace SparkleLib.Git { try { while (!this.git.StandardError.EndOfStream) { string line = this.git.StandardError.ReadLine (); - Match match = progress_regex.Match (line); + Match match = this.progress_regex.Match (line); double number = 0.0; + double speed = 0.0; if (match.Success) { - number = double.Parse (match.Groups [1].Value, new CultureInfo ("en-US")); + try { + number = double.Parse (match.Groups [1].Value, new CultureInfo ("en-US")); + + } catch (FormatException) { + SparkleLogger.LogInfo ("Git", "Error parsing progress: \"" + match.Groups [1] + "\""); + } - // The cloning progress consists of two stages: the "Compressing - // objects" stage which we count as 20% of the total progress, and - // the "Receiving objects" stage which we count as the last 80% - if (line.Contains ("|")) - number = (number / 100 * 80 + 20); // "Receiving objects" stage - else - number = (number / 100 * 20); // "Compressing objects" stage + // The pushing progress consists of two stages: the "Compressing + // objects" stage which we count as 20% of the total progress, and + // the "Writing objects" stage which we count as the last 80% + if (line.Contains ("Compressing")) { + // "Compressing objects" stage + number = (number / 100 * 20); + + } else { + // "Writing objects" stage + number = (number / 100 * 80 + 20); + Match speed_match = this.speed_regex.Match (line); + + if (speed_match.Success) { + 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; + } + } } else { SparkleLogger.LogInfo ("Fetcher", line); @@ -166,7 +191,7 @@ namespace SparkleLib.Git { percentage = number; if (DateTime.Compare (last_change, DateTime.Now.Subtract (change_interval)) < 0) { - base.OnProgressChanged (percentage); + base.OnProgressChanged (percentage, speed); last_change = DateTime.Now; } } @@ -187,10 +212,10 @@ namespace SparkleLib.Git { break; Thread.Sleep (500); - base.OnProgressChanged (percentage); + base.OnProgressChanged (percentage, 0); } - base.OnProgressChanged (100); + base.OnProgressChanged (100, 0); InstallConfiguration (); InstallExcludeRules (); diff --git a/SparkleLib/SparkleExtensions.cs b/SparkleLib/SparkleExtensions.cs index ef6dd972..f1be5fec 100755 --- a/SparkleLib/SparkleExtensions.cs +++ b/SparkleLib/SparkleExtensions.cs @@ -60,11 +60,11 @@ namespace SparkleLib { public static string ToSize (this double byte_count) { if (byte_count >= 1099511627776) - return String.Format ("{0:##.##} ᴛʙ", Math.Round (byte_count / 1099511627776, 1)); + return String.Format ("{0:##.##} ᴛʙ", Math.Round (byte_count / 1099511627776, 2)); else if (byte_count >= 1073741824) return String.Format ("{0:##.##} ɢʙ", Math.Round (byte_count / 1073741824, 1)); else if (byte_count >= 1048576) - return String.Format ("{0:##.##} ᴍʙ", Math.Round (byte_count / 1048576, 0)); + return String.Format ("{0:##.##} ᴍʙ", Math.Round (byte_count / 1048576, 1)); else if (byte_count >= 1024) return String.Format ("{0:##.##} ᴋʙ", Math.Round (byte_count / 1024, 0)); else diff --git a/SparkleLib/SparkleFetcherBase.cs b/SparkleLib/SparkleFetcherBase.cs index 40261861..beaf6c13 100755 --- a/SparkleLib/SparkleFetcherBase.cs +++ b/SparkleLib/SparkleFetcherBase.cs @@ -44,7 +44,7 @@ namespace SparkleLib { public delegate void FinishedEventHandler (bool repo_is_encrypted, bool repo_is_empty, string [] warnings); public event ProgressChangedEventHandler ProgressChanged = delegate { }; - public delegate void ProgressChangedEventHandler (double percentage); + public delegate void ProgressChangedEventHandler (double percentage, double speed); public abstract bool Fetch (); @@ -53,6 +53,9 @@ namespace SparkleLib { public abstract bool IsFetchedRepoPasswordCorrect (string password); public abstract void EnableFetchedRepoCrypto (string password); + public double ProgressPercentage { get; private set; } + public double ProgressSpeed { get; private set; } + public Uri RemoteUrl { get; protected set; } public string RequiredFingerprint { get; protected set; } public readonly bool FetchPriorHistory = false; @@ -232,8 +235,8 @@ namespace SparkleLib { } - protected void OnProgressChanged (double percentage) { - ProgressChanged (percentage); + protected void OnProgressChanged (double percentage, double speed) { + ProgressChanged (percentage, speed); } diff --git a/SparkleLib/SparkleFetcherSSH.cs b/SparkleLib/SparkleFetcherSSH.cs index e7a9b287..abc1c0ae 100644 --- a/SparkleLib/SparkleFetcherSSH.cs +++ b/SparkleLib/SparkleFetcherSSH.cs @@ -16,11 +16,12 @@ namespace SparkleLib { public override bool Fetch () { - if (RemoteUrl.Host.EndsWith(".onion")) { + 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 (); diff --git a/SparkleShare/Mac/SparkleSetup.cs b/SparkleShare/Mac/SparkleSetup.cs index a9a079c1..70587521 100755 --- a/SparkleShare/Mac/SparkleSetup.cs +++ b/SparkleShare/Mac/SparkleSetup.cs @@ -37,7 +37,7 @@ namespace SparkleShare { private NSTextField FullNameTextField, FullNameLabel, EmailLabel, EmailTextField, LinkCodeTextField, AddressTextField, AddressLabel, AddressHelpLabel, PathTextField, PathLabel, - PathHelpLabel, PasswordTextField, VisiblePasswordTextField, PasswordLabel, WarningTextField; + PathHelpLabel, ProgressLabel, PasswordTextField, VisiblePasswordTextField, PasswordLabel, WarningTextField; private NSButton StartupCheckButton, HistoryCheckButton, ShowPasswordCheckButton; private NSProgressIndicator ProgressIndicator; @@ -368,16 +368,22 @@ namespace SparkleShare { Enabled = false }; + ProgressLabel = new SparkleLabel ("", NSTextAlignment.Right); + ProgressLabel.Frame = new RectangleF (Frame.Width - 40 - 75, 185, 75, 25); - Controller.UpdateProgressBarEvent += delegate (double percentage) { + + Controller.UpdateProgressBarEvent += delegate (double percentage, string speed) { Program.Controller.Invoke (() => { ProgressIndicator.DoubleValue = percentage; + ProgressLabel.StringValue = speed; }); }; + CancelButton.Activated += delegate { Controller.SyncingCancelled (); }; + ContentView.AddSubview (ProgressLabel); ContentView.AddSubview (ProgressIndicator); Buttons.Add (FinishButton); diff --git a/SparkleShare/SparkleControllerBase.cs b/SparkleShare/SparkleControllerBase.cs index 8bc626c8..43469711 100644 --- a/SparkleShare/SparkleControllerBase.cs +++ b/SparkleShare/SparkleControllerBase.cs @@ -57,7 +57,7 @@ namespace SparkleShare { public delegate void FolderFetchErrorHandler (string remote_url, string [] errors); public event FolderFetchingHandler FolderFetching = delegate { }; - public delegate void FolderFetchingHandler (double percentage); + public delegate void FolderFetchingHandler (double percentage, double speed); public event Action FolderListChanged = delegate { }; @@ -433,6 +433,7 @@ namespace SparkleShare { }; this.repositories.Add (repo); + this.repositories.Sort ((x, y) => string.Compare (x.Name, y.Name)); repo.Initialize (); } @@ -587,8 +588,8 @@ namespace SparkleShare { StopFetcher (); }; - this.fetcher.ProgressChanged += delegate (double percentage) { - FolderFetching (percentage); + this.fetcher.ProgressChanged += delegate (double percentage, double speed) { + FolderFetching (percentage, speed); }; this.fetcher.Start (); diff --git a/SparkleShare/SparkleSetupController.cs b/SparkleShare/SparkleSetupController.cs index d679b3b6..dc48ca35 100755 --- a/SparkleShare/SparkleSetupController.cs +++ b/SparkleShare/SparkleSetupController.cs @@ -53,7 +53,7 @@ namespace SparkleShare { public delegate void ChangePageEventHandler (PageType page, string [] warnings); public event UpdateProgressBarEventHandler UpdateProgressBarEvent = delegate { }; - public delegate void UpdateProgressBarEventHandler (double percentage); + public delegate void UpdateProgressBarEventHandler (double percentage, string speed); public event UpdateSetupContinueButtonEventHandler UpdateSetupContinueButtonEvent = delegate { }; public delegate void UpdateSetupContinueButtonEventHandler (bool button_enabled); @@ -409,10 +409,14 @@ namespace SparkleShare { Program.Controller.FolderFetching -= SyncingPageFetchingDelegate; } - private void SyncingPageFetchingDelegate (double percentage) + private void SyncingPageFetchingDelegate (double percentage, double speed) { ProgressBarPercentage = percentage; - UpdateProgressBarEvent (ProgressBarPercentage); + + if (speed == 0.0) + UpdateProgressBarEvent (ProgressBarPercentage, ""); + else + UpdateProgressBarEvent (ProgressBarPercentage, speed.ToSize () + "/s"); }