Inheritance: SparkleProcess
Example #1
0
        public override void RevertFile(string path, string revision)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (revision == null)
            {
                throw new ArgumentNullException("revision");
            }

            path = path.Replace("\\", "/");

            SparkleGit git = new SparkleGit(LocalPath, "checkout " + revision + " \"" + path + "\"");

            git.StartAndWaitForExit();

            if (git.ExitCode == 0)
            {
                SparkleLogger.LogInfo("Git", Name + " | Checked out \"" + path + "\" (" + revision + ")");
            }
            else
            {
                SparkleLogger.LogInfo("Git", Name + " | Failed to check out \"" + path + "\" (" + revision + ")");
            }
        }
Example #2
0
        // Merges the fetched changes
        private void Rebase()
        {
            if (HasLocalChanges)
            {
                Add();

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

            SparkleGit git = new SparkleGit(LocalPath, "rebase FETCH_HEAD");

            git.StartInfo.RedirectStandardOutput = false;

            git.Start();
            git.WaitForExit();

            if (git.ExitCode != 0)
            {
                SparkleHelpers.DebugInfo("Git", "[" + Name + "] Conflict detected, trying to get out...");

                while (HasLocalChanges)
                {
                    ResolveConflict();
                }

                SparkleHelpers.DebugInfo("Git", "[" + Name + "] Conflict resolved");
                OnConflictResolved();
            }
        }
Example #3
0
        public SparkleRepo(string path, SparkleConfig config) : base(path, config)
        {
            SparkleGit git = new SparkleGit(LocalPath, "config core.ignorecase false");

            git.StartAndWaitForExit();

            // Check if we should use git-bin
            git = new SparkleGit(LocalPath, "config --get filter.bin.clean");
            git.StartAndWaitForExit();

            this.use_git_bin = (git.ExitCode == 0);

            if (this.use_git_bin)
            {
                ConfigureGitBin();
            }

            git = new SparkleGit(LocalPath, "config remote.origin.url \"" + RemoteUrl + "\"");
            git.StartAndWaitForExit();

            string password_file_path = Path.Combine(LocalPath, ".git", "password");

            if (File.Exists(password_file_path))
            {
                this.is_encrypted = true;
            }
        }
        private void InstallConfiguration()
        {
            string [] settings = new string [] {
                "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.precomposeunicode true", // Use the same Unicode form on all filesystems
                "core.safecrlf false",
                "core.excludesfile \"\"",
                "core.packedGitLimit 128m", // Some memory limiting options
                "core.packedGitWindowSize 128m",
                "pack.deltaCacheSize 128m",
                "pack.packSizeLimit 128m",
                "pack.windowMemory 128m",
                "push.default matching"
            };

            foreach (string setting in settings)
            {
                SparkleGit git_config = new SparkleGit(TargetFolder, "config " + setting);
                git_config.StartAndWaitForExit();
            }

            if (this.use_git_bin)
            {
                InstallGitBinConfiguration();
            }
        }
Example #5
0
        // Merges the fetched changes
        private void Rebase()
        {
            if (HasLocalChanges)
            {
                Add();

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

            SparkleGit git = new SparkleGit(LocalPath, "rebase FETCH_HEAD");

            git.StartInfo.RedirectStandardOutput = false;
            git.StartAndWaitForExit();

            if (git.ExitCode != 0)
            {
                SparkleLogger.LogInfo("Git", Name + " | Conflict detected, trying to get out...");

                while (HasLocalChanges)
                {
                    try {
                        ResolveConflict();
                    } catch (IOException e) {
                        SparkleLogger.LogInfo("Git",
                                              Name + " | Failed to resolve conflict, trying again... (" + e.Message + ")");
                    }
                }

                SparkleLogger.LogInfo("Git", Name + " | Conflict resolved");
                OnConflictResolved();
            }
        }
        public override void EnableFetchedRepoCrypto(string password)
        {
            // Set up the encryption filter
            SparkleGit git_config_smudge = new SparkleGit(TargetFolder,
                                                          "config filter.encryption.smudge \"openssl enc -d -aes-256-cbc -base64 -S " + this.crypto_salt +
                                                          " -pass file:.git/info/encryption_password\"");

            SparkleGit git_config_clean = new SparkleGit(TargetFolder,
                                                         "config filter.encryption.clean  \"openssl enc -e -aes-256-cbc -base64 -S " + this.crypto_salt +
                                                         " -pass file:.git/info/encryption_password\"");

            git_config_smudge.StartAndWaitForExit();
            git_config_clean.StartAndWaitForExit();

            // Pass all files through the encryption filter
            string git_attributes_file_path = new string [] { TargetFolder, ".git", "info", "attributes" }.Combine();

            File.WriteAllText(git_attributes_file_path, "\n* filter=encryption");

            // Store the password
            string password_file_path = new string [] { TargetFolder, ".git", "info", "encryption_password" }.Combine();

            if (this.crypto_password_is_hashed)
            {
                File.WriteAllText(password_file_path, password.SHA256(this.crypto_salt));
            }
            else
            {
                File.WriteAllText(password_file_path, password);
            }
        }
Example #7
0
        private List <SparkleChange> ParseStatus()
        {
            List <SparkleChange> changes = new List <SparkleChange> ();

            SparkleGit git_status = new SparkleGit(LocalPath, "status --porcelain");

            git_status.Start();

            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", "");
                }

                SparkleChange change;

                if (line.StartsWith("R"))
                {
                    string path          = line.Substring(3, line.IndexOf(" -> ") - 3).Trim("\" ".ToCharArray());
                    string moved_to_path = line.Substring(line.IndexOf(" -> ") + 4).Trim("\" ".ToCharArray());

                    change = new SparkleChange()
                    {
                        Type        = SparkleChangeType.Moved,
                        Path        = EnsureSpecialCharacters(path),
                        MovedToPath = EnsureSpecialCharacters(moved_to_path)
                    };
                }
                else
                {
                    string path = line.Substring(2).Trim("\" ".ToCharArray());
                    change = new SparkleChange()
                    {
                        Path = EnsureSpecialCharacters(path)
                    };
                    change.Type = SparkleChangeType.Added;

                    if (line.StartsWith("M"))
                    {
                        change.Type = SparkleChangeType.Edited;
                    }
                    else if (line.StartsWith("D"))
                    {
                        change.Type = SparkleChangeType.Deleted;
                    }
                }

                changes.Add(change);
            }

            git_status.StandardOutput.ReadToEnd();
            git_status.WaitForExit();

            return(changes);
        }
Example #8
0
        // Stages the made changes
        private bool Add()
        {
            SparkleGit git = new SparkleGit(LocalPath, "add --all");

            git.StartAndWaitForExit();

            return(git.ExitCode == 0);
        }
Example #9
0
        // Stages the made changes
        private void Add()
        {
            SparkleGit git = new SparkleGit(LocalPath, "add --all");

            git.StartAndWaitForExit();

            SparkleLogger.LogInfo("Git", Name + " | Changes staged");
        }
Example #10
0
        // Creates a pretty commit message based on what has changed
        private string FormatCommitMessage()
        {
            int    count   = 0;
            string message = "";

            SparkleGit git_status = new SparkleGit(LocalPath, "status --porcelain");

            git_status.Start();

            while (!git_status.StandardOutput.EndOfStream)
            {
                string line = git_status.StandardOutput.ReadLine();

                if (line.EndsWith(".empty") || line.EndsWith(".empty\""))
                {
                    line = line.Replace(".empty", "");
                }

                if (line.StartsWith("R"))
                {
                    string path          = line.Substring(3, line.IndexOf(" -> ") - 3).Trim("\"".ToCharArray());
                    string moved_to_path = line.Substring(line.IndexOf(" -> ") + 4).Trim("\"".ToCharArray());

                    message += "< ‘" + EnsureSpecialCharacters(path) + "’\n";
                    message += "> ‘" + EnsureSpecialCharacters(moved_to_path) + "’\n";
                }
                else
                {
                    if (line.StartsWith("M"))
                    {
                        message += "/";
                    }
                    else if (line.StartsWith("D"))
                    {
                        message += "-";
                    }
                    else
                    {
                        message += "+";
                    }

                    string path = line.Substring(3).Trim("\"".ToCharArray());
                    message += " ‘" + EnsureSpecialCharacters(path) + "’\n";
                }

                count++;
                if (count == 10)
                {
                    message += "...\n";
                    break;
                }
            }

            git_status.StandardOutput.ReadToEnd();
            git_status.WaitForExit();

            return(message);
        }
Example #11
0
        // Stages the made changes
        private void Add()
        {
            SparkleGit git = new SparkleGit(LocalPath, "add --all");

            git.Start();
            git.WaitForExit();

            SparkleHelpers.DebugInfo("Git", "[" + Name + "] Changes staged");
        }
Example #12
0
        public override void RestoreFile(string path, string revision, string target_file_path)
        {
            if (path == null)
            {
                throw new ArgumentNullException("path");
            }

            if (revision == null)
            {
                throw new ArgumentNullException("revision");
            }

            SparkleLogger.LogInfo("Git", Name + " | Restoring \"" + path + "\" (revision " + revision + ")");

            // FIXME: git-show doesn't decrypt objects, so we can't use it to retrieve
            // files from the index. This is a suboptimal workaround but it does the job
            if (this.is_encrypted)
            {
                // Restore the older file...
                SparkleGit git = new SparkleGit(LocalPath, "checkout " + revision + " \"" + path + "\"");
                git.StartAndWaitForExit();

                string local_file_path = Path.Combine(LocalPath, path);

                // ...move it...
                try {
                    File.Move(local_file_path, target_file_path);
                } catch {
                    SparkleLogger.LogInfo("Git",
                                          Name + " | Could not move \"" + local_file_path + "\" to \"" + target_file_path + "\"");
                }

                // ...and restore the most recent revision
                git = new SparkleGit(LocalPath, "checkout " + CurrentRevision + " \"" + path + "\"");
                git.StartAndWaitForExit();

                // The correct way
            }
            else
            {
                path = path.Replace("\"", "\\\"");

                SparkleGit git = new SparkleGit(LocalPath, "show " + revision + ":\"" + path + "\"");
                git.Start();

                FileStream stream = File.OpenWrite(target_file_path);
                git.StandardOutput.BaseStream.CopyTo(stream);
                stream.Close();

                git.WaitForExit();
            }

            if (target_file_path.StartsWith(LocalPath))
            {
                new Thread(() => OnFileActivity(null)).Start();
            }
        }
        public override void Complete()
        {
            if (!IsFetchedRepoEmpty)
            {
                SparkleGit git = new SparkleGit(TargetFolder, "checkout --quiet HEAD");
                git.StartAndWaitForExit();
            }

            base.Complete();
        }
        public override bool IsFetchedRepoPasswordCorrect(string password)
        {
            string password_check_file_path = Path.Combine(TargetFolder, ".sparkleshare");

            if (!File.Exists(password_check_file_path))
            {
                SparkleGit git = new SparkleGit(TargetFolder, "show HEAD:.sparkleshare");
                git.Start();

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

                if (git.ExitCode != 0)
                {
                    return(false);
                }
                else
                {
                    File.WriteAllText(password_check_file_path, output);
                }
            }

            Process process = new Process()
            {
                EnableRaisingEvents = true
            };

            process.StartInfo.WorkingDirectory       = TargetFolder;
            process.StartInfo.UseShellExecute        = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.CreateNoWindow         = true;

            process.StartInfo.FileName  = "openssl";
            process.StartInfo.Arguments = "enc -d -aes-256-cbc -base64 -S " + this.crypto_salt +
                                          " -pass pass:\"" + password + "\" -in " + password_check_file_path;

            process.Start();

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

            if (process.ExitCode == 0)
            {
                File.Delete(password_check_file_path);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #15
0
        // Commits the made changes
        private void Commit(string message)
        {
            SparkleGit git = new SparkleGit(LocalPath,
                                            "commit -m \"" + message + "\" " +
                                            "--author=\"" + SparkleConfig.DefaultConfig.User.Name +
                                            " <" + SparkleConfig.DefaultConfig.User.Email + ">\"");

            git.Start();
            git.StandardOutput.ReadToEnd();
            git.WaitForExit();

            SparkleHelpers.DebugInfo("Commit", "[" + Name + "] " + message);
        }
        public void InstallGitBinConfiguration()
        {
            string [] settings = new string [] {
                "core.bigFileThreshold 1024g",
                "filter.bin.clean \"git bin clean %f\"",
                "filter.bin.smudge \"git bin smudge\""
            };

            foreach (string setting in settings)
            {
                SparkleGit git_config = new SparkleGit(TargetFolder, "config " + setting);
                git_config.StartAndWaitForExit();
            }
        }
Example #17
0
        public override bool IsFetchedRepoPasswordCorrect(string password)
        {
            string password_check_file_path = Path.Combine(TargetFolder, ".sparkleshare");

            if (!File.Exists(password_check_file_path))
            {
                SparkleGit git    = new SparkleGit(TargetFolder, "show HEAD:.sparkleshare");
                string     output = git.StartAndReadStandardOutput();

                if (git.ExitCode == 0)
                {
                    File.WriteAllText(password_check_file_path, output);
                }
                else
                {
                    return(false);
                }
            }

            Process process = new Process();

            process.EnableRaisingEvents              = true;
            process.StartInfo.WorkingDirectory       = TargetFolder;
            process.StartInfo.UseShellExecute        = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardInput  = true;
            process.StartInfo.CreateNoWindow         = true;

            process.StartInfo.FileName  = "openssl";
            process.StartInfo.Arguments = "enc -d -aes-256-cbc -base64 -pass stdin " +
                                          "-in \"" + password_check_file_path + "\"";

            SparkleLogger.LogInfo("Cmd | " + System.IO.Path.GetFileName(process.StartInfo.WorkingDirectory),
                                  System.IO.Path.GetFileName(process.StartInfo.FileName) + " " + process.StartInfo.Arguments);

            process.Start();
            process.StandardInput.WriteLine(password);
            process.WaitForExit();

            if (process.ExitCode == 0)
            {
                File.Delete(password_check_file_path);
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #18
0
        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 void Complete()
        {
            if (IsFetchedRepoEmpty)
            {
                return;
            }

            SparkleGit git = new SparkleGit(TargetFolder, "checkout HEAD");

            git.Start();

            // Reading the standard output HAS to go before
            // WaitForExit, or it will hang forever on output > 4096 bytes
            git.StandardOutput.ReadToEnd();
            git.WaitForExit();
        }
Example #20
0
        public SparkleRepo(string path, SparkleConfig config) : base(path, config)
        {
            SparkleGit git = new SparkleGit(LocalPath, "config --get filter.bin.clean");

            git.Start();
            git.WaitForExit();

            this.use_git_bin = (git.ExitCode == 0);

            string rebase_apply_path = new string [] { LocalPath, ".git", "rebase-apply" }.Combine();

            if (Directory.Exists(rebase_apply_path))
            {
                git = new SparkleGit(LocalPath, "rebase --abort");
                git.StartAndWaitForExit();
            }
        }
Example #21
0
        public void InstallGitBinConfiguration()
        {
            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\""
            };

            foreach (string setting in settings)
            {
                SparkleGit git_config = new SparkleGit(TargetFolder, "config " + setting);
                git_config.StartAndWaitForExit();
            }
        }
Example #22
0
        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.");
            }
        }
Example #23
0
        // Commits the made changes
        private void Commit(string message)
        {
            SparkleGit git;

            if (!this.user_is_set)
            {
                git = new SparkleGit(LocalPath, "config user.name \"" + base.local_config.User.Name + "\"");
                git.StartAndWaitForExit();

                git = new SparkleGit(LocalPath, "config user.email \"" + base.local_config.User.Email + "\"");
                git.StartAndWaitForExit();

                this.user_is_set = true;
            }

            git = new SparkleGit(LocalPath, "commit --all --message=\"" + message + "\" " +
                                 "--author=\"" + base.local_config.User.Name + " <" + base.local_config.User.Email + ">\"");

            git.StartAndReadStandardOutput();
        }
Example #24
0
        public SparkleRepo(string path, SparkleConfig config) : base(path, config)
        {
            // TODO: Set git locale to en-US

            SparkleGit git = new SparkleGit(LocalPath, "config --get filter.bin.clean");

            git.StartAndWaitForExit();

            this.use_git_bin = (git.ExitCode == 0);

            git = new SparkleGit(LocalPath, "config remote.origin.url \"" + RemoteUrl + "\"");
            git.StartAndWaitForExit();

            string rebase_apply_path = new string [] { LocalPath, ".git", "rebase-apply" }.Combine();

            if (Directory.Exists(rebase_apply_path))
            {
                git = new SparkleGit(LocalPath, "rebase --abort");
                git.StartAndWaitForExit();
            }
        }
Example #25
0
        // Creates a pretty commit message based on what has changed
        private string FormatCommitMessage()
        {
            List <string> Added     = new List <string> ();
            List <string> Modified  = new List <string> ();
            List <string> Removed   = new List <string> ();
            string        file_name = "";
            string        message   = "";

            SparkleGit git_status = new SparkleGit(LocalPath, "status --porcelain");

            git_status.Start();

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

            git_status.WaitForExit();

            string [] lines = output.Split("\n".ToCharArray());
            foreach (string line in lines)
            {
                if (line.StartsWith("A"))
                {
                    Added.Add(line.Substring(3));
                }
                else if (line.StartsWith("M"))
                {
                    Modified.Add(line.Substring(3));
                }
                else if (line.StartsWith("D"))
                {
                    Removed.Add(line.Substring(3));
                }
                else if (line.StartsWith("R"))
                {
                    Removed.Add(line.Substring(3, (line.IndexOf(" -> ") - 3)));
                    Added.Add(line.Substring(line.IndexOf(" -> ") + 4));
                }
            }

            int count     = 0;
            int max_count = 20;

            string n = Environment.NewLine;

            foreach (string added in Added)
            {
                file_name = added.Trim("\"".ToCharArray());

                if (file_name.EndsWith(".empty"))
                {
                    file_name = file_name.Substring(0, file_name.Length - 6);
                }

                message += "+ ‘" + file_name + "’" + n;

                count++;
                if (count == max_count)
                {
                    return(message + "...");
                }
            }

            foreach (string modified in Modified)
            {
                file_name = modified.Trim("\"".ToCharArray());

                if (file_name.EndsWith(".empty"))
                {
                    continue;
                }

                message += "/ ‘" + file_name + "’" + n;

                count++;
                if (count == max_count)
                {
                    return(message + "...");
                }
            }

            foreach (string removed in Removed)
            {
                file_name = removed.Trim("\"".ToCharArray());

                if (file_name.EndsWith(".empty"))
                {
                    file_name = file_name.Substring(0, file_name.Length - 6);
                }

                message += "- ‘" + file_name + "’" + n;

                count++;
                if (count == max_count)
                {
                    return(message + "..." + n);
                }
            }

            message = message.Replace("\"", "");
            return(message.TrimEnd());
        }
Example #26
0
        // Returns a list of the latest change sets
        public override List <SparkleChangeSet> GetChangeSets(int count)
        {
            if (count < 1)
            {
                count = 30;
            }

            count = 150;

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

            SparkleGit git_log = new SparkleGit(LocalPath,
                                                "log -" + count + " --raw -M --date=iso --format=medium --no-color --no-merges");

            git_log.Start();

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

            git_log.WaitForExit();

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

            int    line_number = 0;
            bool   first_pass = true;
            string entry = "", last_entry = "";

            foreach (string line in lines)
            {
                if (line.StartsWith("commit") && !first_pass)
                {
                    entries.Add(entry);
                    entry       = "";
                    line_number = 0;
                }
                else
                {
                    first_pass = false;
                }

                // Only parse 250 files to prevent memory issues
                if (line_number < 254)
                {
                    entry += line + "\n";
                    line_number++;
                }

                last_entry = entry;
            }

            entries.Add(last_entry);

            Regex merge_regex = new Regex(@"commit ([a-z0-9]{40})\n" +
                                          "Merge: .+ .+\n" +
                                          "Author: (.+) <(.+)>\n" +
                                          "Date:   ([0-9]{4})-([0-9]{2})-([0-9]{2}) " +
                                          "([0-9]{2}):([0-9]{2}):([0-9]{2}) .([0-9]{4})\n" +
                                          "*", RegexOptions.Compiled);

            Regex non_merge_regex = new Regex(@"commit ([a-z0-9]{40})\n" +
                                              "Author: (.+) <(.+)>\n" +
                                              "Date:   ([0-9]{4})-([0-9]{2})-([0-9]{2}) " +
                                              "([0-9]{2}):([0-9]{2}):([0-9]{2}) (.[0-9]{4})\n" +
                                              "*", RegexOptions.Compiled);

            foreach (string log_entry in entries)
            {
                Regex regex;
                bool  is_merge_commit = false;

                if (log_entry.Contains("\nMerge: "))
                {
                    regex           = merge_regex;
                    is_merge_commit = true;
                }
                else
                {
                    regex = non_merge_regex;
                }

                Match match = regex.Match(log_entry);

                if (match.Success)
                {
                    SparkleChangeSet change_set = new SparkleChangeSet();

                    change_set.Folder    = new SparkleFolder(Name);
                    change_set.Revision  = match.Groups [1].Value;
                    change_set.User      = new SparkleUser(match.Groups [2].Value, match.Groups [3].Value);
                    change_set.IsMagical = is_merge_commit;
                    change_set.RemoteUrl = RemoteUrl;

                    change_set.Timestamp = new DateTime(int.Parse(match.Groups [4].Value),
                                                        int.Parse(match.Groups [5].Value), int.Parse(match.Groups [6].Value),
                                                        int.Parse(match.Groups [7].Value), int.Parse(match.Groups [8].Value),
                                                        int.Parse(match.Groups [9].Value));

                    string time_zone    = match.Groups [10].Value;
                    int    our_offset   = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Hours;
                    int    their_offset = int.Parse(time_zone.Substring(0, 3));
                    change_set.Timestamp = change_set.Timestamp.AddHours(their_offset * -1);
                    change_set.Timestamp = change_set.Timestamp.AddHours(our_offset);


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

                    foreach (string entry_line in entry_lines)
                    {
                        if (entry_line.StartsWith(":"))
                        {
                            string change_type = entry_line [37].ToString();
                            string file_path   = entry_line.Substring(39);
                            string to_file_path;

                            if (file_path.EndsWith(".empty"))
                            {
                                file_path = file_path.Substring(0,
                                                                file_path.Length - ".empty".Length);
                            }

                            if (file_path.Equals(".sparkleshare"))
                            {
                                continue;
                            }

                            if (change_type.Equals("A"))
                            {
                                change_set.Changes.Add(
                                    new SparkleChange()
                                {
                                    Path      = file_path,
                                    Timestamp = change_set.Timestamp,
                                    Type      = SparkleChangeType.Added
                                }
                                    );
                            }
                            else if (change_type.Equals("M"))
                            {
                                change_set.Changes.Add(
                                    new SparkleChange()
                                {
                                    Path      = file_path,
                                    Timestamp = change_set.Timestamp,
                                    Type      = SparkleChangeType.Edited
                                }
                                    );
                            }
                            else if (change_type.Equals("D"))
                            {
                                change_set.Changes.Add(
                                    new SparkleChange()
                                {
                                    Path      = file_path,
                                    Timestamp = change_set.Timestamp,
                                    Type      = SparkleChangeType.Deleted
                                }
                                    );
                            }
                            else if (change_type.Equals("R"))
                            {
                                int tab_pos = entry_line.LastIndexOf("\t");
                                file_path    = entry_line.Substring(42, tab_pos - 42);
                                to_file_path = entry_line.Substring(tab_pos + 1);

                                if (file_path.EndsWith(".empty"))
                                {
                                    file_path = file_path.Substring(0, file_path.Length - 6);
                                }

                                if (to_file_path.EndsWith(".empty"))
                                {
                                    to_file_path = to_file_path.Substring(0, to_file_path.Length - 6);
                                }

                                change_set.Changes.Add(
                                    new SparkleChange()
                                {
                                    Path      = file_path,
                                    MovedPath = to_file_path,
                                    Timestamp = change_set.Timestamp,
                                    Type      = SparkleChangeType.Moved
                                }
                                    );
                            }
                        }
                    }

                    if (change_set.Changes.Count > 0)
                    {
                        if (change_sets.Count > 0)
                        {
                            SparkleChangeSet last_change_set = change_sets [change_sets.Count - 1];

                            if (change_set.Timestamp.Year == last_change_set.Timestamp.Year &&
                                change_set.Timestamp.Month == last_change_set.Timestamp.Month &&
                                change_set.Timestamp.Day == last_change_set.Timestamp.Day &&
                                change_set.User.Name.Equals(last_change_set.User.Name))
                            {
                                last_change_set.Changes.AddRange(change_set.Changes);

                                if (DateTime.Compare(last_change_set.Timestamp, change_set.Timestamp) < 1)
                                {
                                    last_change_set.FirstTimestamp = last_change_set.Timestamp;
                                    last_change_set.Timestamp      = change_set.Timestamp;
                                    last_change_set.Revision       = change_set.Revision;
                                }
                                else
                                {
                                    last_change_set.FirstTimestamp = change_set.Timestamp;
                                }
                            }
                            else
                            {
                                change_sets.Add(change_set);
                            }
                        }
                        else
                        {
                            change_sets.Add(change_set);
                        }
                    }
                }
            }

            return(change_sets);
        }
Example #27
0
        private void ResolveConflict()
        {
            // This is a list of conflict status codes that Git uses, their
            // meaning, and how SparkleShare should handle them.
            //
            // DD    unmerged, both deleted    -> Do nothing
            // AU    unmerged, added by us     -> Use theirs, save ours as a timestamped copy
            // UD    unmerged, deleted by them -> Use ours
            // UA    unmerged, added by them   -> Use theirs, save ours as a timestamped copy
            // DU    unmerged, deleted by us   -> Use theirs
            // AA    unmerged, both added      -> Use theirs, save ours as a timestamped copy
            // UU    unmerged, both modified   -> Use theirs, save ours as a timestamped copy
            // ??    unmerged, new files       -> Stage the new files
            //
            // Note that a rebase merge works by replaying each commit from the working branch on
            // top of the upstream branch. Because of this, when a merge conflict happens the
            // side reported as 'ours' is the so-far rebased series, starting with upstream,
            // and 'theirs' is the working branch. In other words, the sides are swapped.
            //
            // So: 'ours' means the 'server's version' and 'theirs' means the 'local version'

            SparkleGit git_status = new SparkleGit(LocalPath, "status --porcelain");

            git_status.Start();

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

            git_status.WaitForExit();

            string [] lines = output.Split("\n".ToCharArray());

            foreach (string line in lines)
            {
                string conflicting_path = line.Substring(3);
                conflicting_path = conflicting_path.Trim("\"".ToCharArray());

                SparkleHelpers.DebugInfo("Git", "[" + Name + "] Conflict type: " + line);

                // Both the local and server version have been modified
                if (line.StartsWith("UU") || line.StartsWith("AA") ||
                    line.StartsWith("AU") || line.StartsWith("UA"))
                {
                    // Recover local version
                    SparkleGit git_theirs = new SparkleGit(LocalPath,
                                                           "checkout --theirs \"" + conflicting_path + "\"");
                    git_theirs.Start();
                    git_theirs.WaitForExit();

                    // Append a timestamp to local version.
                    // Windows doesn't allow colons in the file name, so
                    // we use "h" between the hours and minutes instead.
                    string timestamp  = DateTime.Now.ToString("MMM d H\\hmm");
                    string their_path = Path.GetFileNameWithoutExtension(conflicting_path) +
                                        " (" + SparkleConfig.DefaultConfig.User.Name + ", " + timestamp + ")" + Path.GetExtension(conflicting_path);

                    string abs_conflicting_path = Path.Combine(LocalPath, conflicting_path);
                    string abs_their_path       = Path.Combine(LocalPath, their_path);

                    File.Move(abs_conflicting_path, abs_their_path);

                    // Recover server version
                    SparkleGit git_ours = new SparkleGit(LocalPath,
                                                         "checkout --ours \"" + conflicting_path + "\"");
                    git_ours.Start();
                    git_ours.WaitForExit();

                    Add();

                    SparkleGit git_rebase_continue = new SparkleGit(LocalPath, "rebase --continue");
                    git_rebase_continue.Start();
                    git_rebase_continue.WaitForExit();

                    // The local version has been modified, but the server version was removed
                }
                else if (line.StartsWith("DU"))
                {
                    // The modified local version is already in the
                    // checkout, so it just needs to be added.
                    //
                    // We need to specifically mention the file, so
                    // we can't reuse the Add () method
                    SparkleGit git_add = new SparkleGit(LocalPath,
                                                        "add \"" + conflicting_path + "\"");
                    git_add.Start();
                    git_add.WaitForExit();

                    SparkleGit git_rebase_continue = new SparkleGit(LocalPath, "rebase --continue");
                    git_rebase_continue.Start();
                    git_rebase_continue.WaitForExit();

                    // The server version has been modified, but the local version was removed
                }
                else if (line.StartsWith("UD"))
                {
                    // We can just skip here, the server version is
                    // already in the checkout
                    SparkleGit git_rebase_skip = new SparkleGit(LocalPath, "rebase --skip");
                    git_rebase_skip.Start();
                    git_rebase_skip.WaitForExit();

                    // New local files
                }
                else
                {
                    Add();

                    SparkleGit git_rebase_continue = new SparkleGit(LocalPath, "rebase --continue");
                    git_rebase_continue.Start();
                    git_rebase_continue.WaitForExit();
                }
            }
        }
Example #28
0
        private List <SparkleChangeSet> GetChangeSetsInternal(string path)
        {
            List <SparkleChangeSet> change_sets = new List <SparkleChangeSet> ();
            SparkleGit git;

            if (path == null)
            {
                git = new SparkleGit(LocalPath, "log --since=1.month --raw --find-renames --date=iso " +
                                     "--format=medium --no-color --no-merges");
            }
            else
            {
                path = path.Replace("\\", "/");

                git = new SparkleGit(LocalPath, "log --raw --find-renames --date=iso " +
                                     "--format=medium --no-color --no-merges -- \"" + path + "\"");
            }

            string output = git.StartAndReadStandardOutput();

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

            int    line_number = 0;
            bool   first_pass = true;
            string entry = "", last_entry = "";

            foreach (string line in lines)
            {
                if (line.StartsWith("commit") && !first_pass)
                {
                    entries.Add(entry);
                    entry       = "";
                    line_number = 0;
                }
                else
                {
                    first_pass = false;
                }

                // Only parse 250 files to prevent memory issues
                if (line_number < 254)
                {
                    entry += line + "\n";
                    line_number++;
                }

                last_entry = entry;
            }

            entries.Add(last_entry);


            foreach (string log_entry in entries)
            {
                Match match = this.log_regex.Match(log_entry);

                if (match.Success)
                {
                    SparkleChangeSet change_set = new SparkleChangeSet();

                    change_set.Folder    = new SparkleFolder(Name);
                    change_set.Revision  = match.Groups [1].Value;
                    change_set.User      = new SparkleUser(match.Groups [2].Value, match.Groups [3].Value);
                    change_set.RemoteUrl = RemoteUrl;

                    change_set.Timestamp = new DateTime(int.Parse(match.Groups [4].Value),
                                                        int.Parse(match.Groups [5].Value), int.Parse(match.Groups [6].Value),
                                                        int.Parse(match.Groups [7].Value), int.Parse(match.Groups [8].Value),
                                                        int.Parse(match.Groups [9].Value));

                    string time_zone    = match.Groups [10].Value;
                    int    our_offset   = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Hours;
                    int    their_offset = int.Parse(time_zone.Substring(0, 3));
                    change_set.Timestamp = change_set.Timestamp.AddHours(their_offset * -1);
                    change_set.Timestamp = change_set.Timestamp.AddHours(our_offset);

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

                    foreach (string entry_line in entry_lines)
                    {
                        if (entry_line.StartsWith(":"))
                        {
                            string type_letter      = entry_line [37].ToString();
                            string file_path        = entry_line.Substring(39);
                            bool   change_is_folder = false;

                            if (file_path.Equals(".sparkleshare"))
                            {
                                continue;
                            }

                            if (file_path.EndsWith(".empty"))
                            {
                                file_path        = file_path.Substring(0, file_path.Length - ".empty".Length);
                                change_is_folder = true;
                            }

                            file_path = EnsureSpecialCharacters(file_path);
                            file_path = file_path.Replace("\\\"", "\"");

                            if (type_letter.Equals("R"))
                            {
                                int tab_pos = entry_line.LastIndexOf("\t");
                                file_path = entry_line.Substring(42, tab_pos - 42);
                                string to_file_path = entry_line.Substring(tab_pos + 1);

                                file_path    = EnsureSpecialCharacters(file_path);
                                to_file_path = EnsureSpecialCharacters(to_file_path);

                                file_path    = file_path.Replace("\\\"", "\"");
                                to_file_path = to_file_path.Replace("\\\"", "\"");

                                if (file_path.EndsWith(".empty"))
                                {
                                    file_path        = file_path.Substring(0, file_path.Length - 6);
                                    change_is_folder = true;
                                }

                                if (to_file_path.EndsWith(".empty"))
                                {
                                    to_file_path     = to_file_path.Substring(0, to_file_path.Length - 6);
                                    change_is_folder = true;
                                }

                                change_set.Changes.Add(
                                    new SparkleChange()
                                {
                                    Path        = file_path,
                                    IsFolder    = change_is_folder,
                                    MovedToPath = to_file_path,
                                    Timestamp   = change_set.Timestamp,
                                    Type        = SparkleChangeType.Moved
                                }
                                    );
                            }
                            else
                            {
                                SparkleChangeType change_type = SparkleChangeType.Added;

                                if (type_letter.Equals("M"))
                                {
                                    change_type = SparkleChangeType.Edited;
                                }
                                else if (type_letter.Equals("D"))
                                {
                                    change_type = SparkleChangeType.Deleted;
                                }

                                change_set.Changes.Add(
                                    new SparkleChange()
                                {
                                    Path      = file_path,
                                    IsFolder  = change_is_folder,
                                    Timestamp = change_set.Timestamp,
                                    Type      = change_type
                                }
                                    );
                            }
                        }
                    }

                    if (change_sets.Count > 0 && path == null)
                    {
                        SparkleChangeSet last_change_set = change_sets [change_sets.Count - 1];

                        if (change_set.Timestamp.Year == last_change_set.Timestamp.Year &&
                            change_set.Timestamp.Month == last_change_set.Timestamp.Month &&
                            change_set.Timestamp.Day == last_change_set.Timestamp.Day &&
                            change_set.User.Name.Equals(last_change_set.User.Name))
                        {
                            last_change_set.Changes.AddRange(change_set.Changes);

                            if (DateTime.Compare(last_change_set.Timestamp, change_set.Timestamp) < 1)
                            {
                                last_change_set.FirstTimestamp = last_change_set.Timestamp;
                                last_change_set.Timestamp      = change_set.Timestamp;
                                last_change_set.Revision       = change_set.Revision;
                            }
                            else
                            {
                                last_change_set.FirstTimestamp = change_set.Timestamp;
                            }
                        }
                        else
                        {
                            change_sets.Add(change_set);
                        }
                    }
                    else
                    {
                        if (path != null)
                        {
                            bool skip_change_set = false;;

                            foreach (SparkleChange change in change_set.Changes)
                            {
                                if ((change.Type == SparkleChangeType.Deleted ||
                                     change.Type == SparkleChangeType.Moved) && change.Path.Equals(path))
                                {
                                    skip_change_set = true;
                                }
                            }

                            if (skip_change_set)
                            {
                                continue;
                            }
                        }

                        change_sets.Add(change_set);
                    }
                }
            }

            return(change_sets);
        }
Example #29
0
        public override bool SyncUp()
        {
            if (HasLocalChanges)
            {
                Add();

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

            SparkleGit git = new SparkleGit(LocalPath,
                                            "push --progress " + // Redirects progress stats to standarderror
                                            "\"" + RemoteUrl + "\" master");

            git.StartInfo.RedirectStandardError = true;
            git.Start();

            double percentage     = 1.0;
            Regex  progress_regex = new Regex(@"([0-9]+)%", RegexOptions.Compiled);

            while (!git.StandardError.EndOfStream)
            {
                string line   = git.StandardError.ReadLine();
                Match  match  = progress_regex.Match(line);
                string speed  = "";
                double number = 0.0;

                if (match.Success)
                {
                    number = double.Parse(match.Groups [1].Value);

                    // 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.StartsWith("Compressing"))
                    {
                        // "Compressing objects" stage
                        number = (number / 100 * 20);
                    }
                    else
                    {
                        if (line.StartsWith("ERROR: QUOTA EXCEEDED"))
                        {
                            int quota_limit = int.Parse(line.Substring(21).Trim());
                            throw new QuotaExceededException("Quota exceeded", quota_limit);
                        }


                        // "Writing objects" stage
                        number = (number / 100 * 80 + 20);

                        if (line.Contains("|"))
                        {
                            speed = line.Substring(line.IndexOf("|") + 1).Trim();
                            speed = speed.Replace(", done.", "").Trim();
                            speed = speed.Replace("i", "");
                            speed = speed.Replace("KB/s", "ᴋʙ/s");
                            speed = speed.Replace("MB/s", "ᴍʙ/s");
                        }
                    }
                }
                else
                {
                    SparkleHelpers.DebugInfo("Git", "[" + Name + "] " + line);
                }

                if (number >= percentage)
                {
                    percentage = number;
                    base.OnProgressChanged(percentage, speed);
                }
            }

            git.WaitForExit();

            UpdateSizes();
            ChangeSets = GetChangeSets();

            if (git.ExitCode == 0)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #30
0
        public override bool SyncDown()
        {
            SparkleGit git = new SparkleGit(LocalPath, "fetch --progress \"" + RemoteUrl + "\" master");

            git.StartInfo.RedirectStandardError = true;
            git.Start();

            double percentage     = 1.0;
            Regex  progress_regex = new Regex(@"([0-9]+)%", RegexOptions.Compiled);

            while (!git.StandardError.EndOfStream)
            {
                string line   = git.StandardError.ReadLine();
                Match  match  = progress_regex.Match(line);
                string speed  = "";
                double number = 0.0;

                if (match.Success)
                {
                    number = double.Parse(match.Groups [1].Value);

                    // The fetching 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.StartsWith("Compressing"))
                    {
                        // "Compressing objects" stage
                        number = (number / 100 * 20);
                    }
                    else
                    {
                        // "Writing objects" stage
                        number = (number / 100 * 80 + 20);

                        if (line.Contains("|"))
                        {
                            speed = line.Substring(line.IndexOf("|") + 1).Trim();
                            speed = speed.Replace(", done.", "").Trim();
                            speed = speed.Replace("i", "");
                            speed = speed.Replace("KB/s", "ᴋʙ/s");
                            speed = speed.Replace("MB/s", "ᴍʙ/s");
                        }
                    }
                }
                else
                {
                    SparkleHelpers.DebugInfo("Git", "[" + Name + "] " + line);
                }


                if (number >= percentage)
                {
                    percentage = number;
                    base.OnProgressChanged(percentage, speed);
                }
            }

            git.WaitForExit();

            UpdateSizes();

            if (git.ExitCode == 0)
            {
                Rebase();

                File.SetAttributes(
                    Path.Combine(LocalPath, ".sparkleshare"),
                    FileAttributes.Hidden
                    );

                ChangeSets = GetChangeSets();

                return(true);
            }
            else
            {
                ChangeSets = GetChangeSets();
                return(false);
            }
        }