public override bool Fetch()
        {
            SparkleHg hg = new SparkleHg (SparklePaths.SparkleTmpPath,
                "clone \"" + base.remote_url + "\" " + "\"" + base.target_folder + "\"");

            hg.Start ();
            hg.WaitForExit ();

            SparkleHelpers.DebugInfo ("Hg", "Exit code " + hg.ExitCode.ToString ());

            if (hg.ExitCode != 0) {
                return false;
            } else {
                InstallConfiguration ();
                InstallExcludeRules ();
                return true;
            }
        }
        // Merges the fetched changes
        private void Merge()
        {
            DisableWatching ();

            if (AnyDifferences) {
                Add ();

                string commit_message = FormatCommitMessage ();
                Commit (commit_message);
            }

            SparkleHg hg = new SparkleHg (LocalPath, "update");

            hg.Start ();
            hg.WaitForExit ();

            EnableWatching ();
        }
        // Commits the made changes
        private void Commit(string message)
        {
            if (!AnyDifferences)
                return;

            SparkleHg hg = new SparkleHg (LocalPath, "commit -m '" + message + "'");
            hg.Start ();
            hg.WaitForExit ();

            SparkleHelpers.DebugInfo ("Commit", "[" + Name + "] " + message);
        }
        // Stages the made changes
        private void Add()
        {
            SparkleHg hg = new SparkleHg (LocalPath, "addremove --quiet");
            hg.Start ();
            hg.WaitForExit ();

            SparkleHelpers.DebugInfo ("Hg", "[" + Name + "] Changes staged");
        }
        public override bool SyncUp()
        {
            Add ();

            string message = FormatCommitMessage ();
            Commit (message);

            SparkleHg hg = new SparkleHg (LocalPath, "push");

            hg.Start ();
            hg.WaitForExit ();

            if (hg.ExitCode == 0) {
                return true;
            } else {
                return false;
            }
        }
        public override bool SyncDown()
        {
            SparkleHg hg = new SparkleHg (LocalPath, "pull");

            hg.Start ();
            hg.WaitForExit ();

            if (hg.ExitCode == 0) {
                Merge ();
                return true;
            } else {
                return false;
            }
        }
        // Returns a list of the latest change sets
        public override List<SparkleChangeSet> GetChangeSets(int count)
        {
            if (count < 1)
                count = 30;

            List <SparkleChangeSet> change_sets = new List <SparkleChangeSet> ();

            SparkleHg hg_log = new SparkleHg (LocalPath, "log --limit " + count + " --style changelog --verbose --stat");
            Console.OutputEncoding = System.Text.Encoding.Unicode;
            hg_log.Start ();

            // Reading the standard output HAS to go before
            // WaitForExit, or it will hang forever on output > 4096 bytes
            string output = hg_log.StandardOutput.ReadToEnd ();
            hg_log.WaitForExit ();

            string [] lines       = output.Split ("\n".ToCharArray ());
            List <string> entries = new List <string> ();

            int j = 0;
            string entry = "", last_entry = "";
            foreach (string line in lines) {
                if (line.StartsWith ("2") && line.EndsWith (")") && j > 0) {
                    entries.Add (entry);
                    entry = "";
                }

                entry += line + "\n";
                j++;

                last_entry = entry;
            }

            entries.Add (last_entry);

            Regex regex = new Regex (@"([0-9]{4})-([0-9]{2})-([0-9]{2}).*([0-9]{2}):([0-9]{2}).*.([0-9]{4})" +
                                      "(.+)<(.+)>.*.([a-z0-9]{12})", RegexOptions.Compiled);

            foreach (string log_entry in entries) {

                bool is_merge_commit = false;

                Match match = regex.Match (log_entry);

                if (!match.Success)
                    continue;

                SparkleChangeSet change_set = new SparkleChangeSet () {
                    Revision  = match.Groups [9].Value,
                    UserName  = match.Groups [7].Value.Trim (),
                    UserEmail = match.Groups [8].Value,
                    IsMerge   = is_merge_commit
                };

                change_set.Timestamp = new DateTime (int.Parse (match.Groups [1].Value),
                    int.Parse (match.Groups [2].Value), int.Parse (match.Groups [3].Value),
                    int.Parse (match.Groups [4].Value), int.Parse (match.Groups [5].Value), 0);

                string [] entry_lines = log_entry.Split ("\n".ToCharArray ());

                foreach (string entry_line in entry_lines) {
                    if (!entry_line.StartsWith ("\t* "))
                        continue;

                    if (entry_line.EndsWith ("new file.")) {
                        string files = entry_line.Substring (3, entry_line.Length - 13);
                        string [] added_files = files.Split (",".ToCharArray ());

                        foreach (string added_file in added_files) {
                            string file = added_file.TrimEnd (": ".ToCharArray ());
                            change_set.Added.Add (file);
                        }

                    } else if (entry_line.EndsWith ("deleted file.")) {
                        string files = entry_line.Substring (3, entry_line.Length - 17);
                        string [] deleted_files = files.Split (",".ToCharArray ());

                        foreach (string deleted_file in deleted_files) {
                            string file = deleted_file.TrimEnd (": ".ToCharArray ());
                            change_set.Deleted.Add (file);
                        }

                    } else if (!"".Equals (entry_line.Trim ())){
                        string files = entry_line.Substring (3);
                        files = files.TrimEnd (":".ToCharArray());
                        string [] edited_files = files.Split (",".ToCharArray ());

                        foreach (string edited_file in edited_files) {
                            if (!change_set.Added.Contains (edited_file) &&
                                !change_set.Deleted.Contains (edited_file)) {

                                change_set.Edited.Add (edited_file);
                            }
                        }
                    }
                }

                change_sets.Add (change_set);
            }

            return change_sets;
        }