diff --git a/SparkleLib/Git/SparkleFetcherGit.cs b/SparkleLib/Git/SparkleFetcherGit.cs index 4c11d3bf..bbb5d22f 100644 --- a/SparkleLib/Git/SparkleFetcherGit.cs +++ b/SparkleLib/Git/SparkleFetcherGit.cs @@ -18,6 +18,7 @@ using System; using System.IO; using System.Diagnostics; +using System.Text.RegularExpressions; using System.Xml; namespace SparkleLib { @@ -86,9 +87,45 @@ namespace SparkleLib { public override bool Fetch () { this.git = new SparkleGit (SparkleConfig.DefaultConfig.TmpPath, - "clone \"" + base.remote_url + "\" " + "\"" + base.target_folder + "\""); - + "clone " + + "--progress " + // Redirects progress stats to standarderror + "\"" + base.remote_url + "\" " + "\"" + base.target_folder + "\""); + + this.git.StartInfo.RedirectStandardError = true; this.git.Start (); + + double percentage = 1.0; + Regex progress_regex = new Regex (@"([0-9]+)%", RegexOptions.Compiled); + + while (!this.git.StandardError.EndOfStream) { + string line = this.git.StandardError.ReadLine (); + Match match = progress_regex.Match (line); + + double number = 0.0; + if (match.Success) { + number = double.Parse (match.Groups [1].Value); + + // 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 ("|")) + // "Receiving objects" stage + number = (number / 100 * 75 + 20); + else + // "Compressing objects" stage + number = (number / 100 * 20); + } + + if (number >= percentage) { + percentage = number; + + // FIXME: for some reason it doesn't go above 95% + base.OnProgressChanged (percentage); + } + + System.Threading.Thread.Sleep (100); + } + this.git.WaitForExit (); SparkleHelpers.DebugInfo ("Git", "Exit code " + this.git.ExitCode.ToString ()); diff --git a/SparkleLib/SparkleFetcherBase.cs b/SparkleLib/SparkleFetcherBase.cs index b9f61143..b4350932 100644 --- a/SparkleLib/SparkleFetcherBase.cs +++ b/SparkleLib/SparkleFetcherBase.cs @@ -31,10 +31,12 @@ namespace SparkleLib { public delegate void StartedEventHandler (); public delegate void FinishedEventHandler (); public delegate void FailedEventHandler (); + public delegate void ProgressChangedEventHandler (double percentage); public event StartedEventHandler Started; public event FinishedEventHandler Finished; public event FailedEventHandler Failed; + public event ProgressChangedEventHandler ProgressChanged; protected string target_folder; protected string remote_url; @@ -117,7 +119,13 @@ namespace SparkleLib { } } - + + protected void OnProgressChanged (double percentage) { + if (ProgressChanged != null) + ProgressChanged (percentage); + } + + private void DisableHostKeyCheckingForHost (string host) { string path = SparkleConfig.DefaultConfig.HomePath; diff --git a/SparkleShare/Mac/SparkleSetup.cs b/SparkleShare/Mac/SparkleSetup.cs index 4fa091e4..0baa75e9 100644 --- a/SparkleShare/Mac/SparkleSetup.cs +++ b/SparkleShare/Mac/SparkleSetup.cs @@ -295,11 +295,20 @@ namespace SparkleShare { "Are you sure it’s not coffee o'clock?"; ProgressIndicator = new NSProgressIndicator () { - Frame = new RectangleF (190, Frame.Height - 200, 640 - 150 - 80, 20), - Style = NSProgressIndicatorStyle.Bar + Frame = new RectangleF (190, Frame.Height - 200, 640 - 150 - 80, 20), + Style = NSProgressIndicatorStyle.Bar, + MinValue = 0.0, + MaxValue = 100.0 }; - - ProgressIndicator.StartAnimation (this); + + // ProgressIndicator.StartAnimation (this); + + Controller.UpdateProgressBarEvent += delegate (double percentage) { + InvokeOnMainThread (delegate { + ProgressIndicator.DoubleValue = percentage; + }); + }; + ContentView.AddSubview (ProgressIndicator); FinishButton = new NSButton () { diff --git a/SparkleShare/SparkleController.cs b/SparkleShare/SparkleController.cs index 750a6617..902142e8 100644 --- a/SparkleShare/SparkleController.cs +++ b/SparkleShare/SparkleController.cs @@ -46,6 +46,9 @@ namespace SparkleShare { public event FolderFetchErrorEventHandler FolderFetchError; public delegate void FolderFetchErrorEventHandler (); + + public event FolderFetchingEventHandler FolderFetching; + public delegate void FolderFetchingEventHandler (double percentage); public event FolderListChangedEventHandler FolderListChanged; public delegate void FolderListChangedEventHandler (); @@ -1055,6 +1058,12 @@ namespace SparkleShare { if (Directory.Exists (tmp_path)) Directory.Delete (tmp_path, true); }; + + + this.fetcher.ProgressChanged += delegate (double percentage) { + if (FolderFetching != null) + FolderFetching (percentage); + }; this.fetcher.Start (); diff --git a/SparkleShare/SparkleSetup.cs b/SparkleShare/SparkleSetup.cs index f4a33cde..2d69eb93 100644 --- a/SparkleShare/SparkleSetup.cs +++ b/SparkleShare/SparkleSetup.cs @@ -43,10 +43,8 @@ namespace SparkleShare { private Button SyncButton; private Table Table; - - private ProgressBar progress_bar = new ProgressBar () { PulseStep = 0.01 }; - private Timer progress_bar_pulse_timer = new Timer () { Interval = 25, Enabled = true }; - + private ProgressBar progress_bar = new ProgressBar (); + // Short alias for the translations public static string _ (string s) @@ -314,11 +312,11 @@ namespace SparkleShare { AddButton (cancel_button); AddButton (finish_button); - this.progress_bar_pulse_timer.Elapsed += delegate { - Application.Invoke (delegate { - progress_bar.Pulse (); - }); - }; + Controller.UpdateProgressBarEvent += delegate (double percentage) { + Application.Invoke (delegate { + this.progress_bar.Fraction = percentage / 100; + }); + }; if (this.progress_bar.Parent != null) (this.progress_bar.Parent as Container).Remove (this.progress_bar); diff --git a/SparkleShare/SparkleSetupController.cs b/SparkleShare/SparkleSetupController.cs index ad0f9754..c0d59251 100644 --- a/SparkleShare/SparkleSetupController.cs +++ b/SparkleShare/SparkleSetupController.cs @@ -33,6 +33,9 @@ namespace SparkleShare { public event ChangePageEventHandler ChangePageEvent; public delegate void ChangePageEventHandler (PageType page); + + public event UpdateProgressBarEventHandler UpdateProgressBarEvent; + public delegate void UpdateProgressBarEventHandler (double percentage); public string PreviousServer { get { @@ -120,6 +123,11 @@ namespace SparkleShare { this.syncing_folder = ""; }; + + SparkleShare.Controller.FolderFetching += delegate (double percentage) { + if (UpdateProgressBarEvent != null) + UpdateProgressBarEvent (percentage); + }; SparkleShare.Controller.FetchFolder (server, folder_name); }