2011-06-01 23:08:05 +00:00
|
|
|
|
// SparkleShare, a collaboration and sharing tool.
|
2010-06-20 21:05:11 +00:00
|
|
|
|
// 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
|
2010-11-21 12:33:24 +00:00
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2010-06-20 21:05:11 +00:00
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
2010-07-22 21:10:38 +00:00
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2010-06-20 21:05:11 +00:00
|
|
|
|
|
2011-02-23 01:13:54 +00:00
|
|
|
|
|
2010-06-20 21:05:11 +00:00
|
|
|
|
using System;
|
2010-09-04 15:23:20 +00:00
|
|
|
|
using System.Collections.Generic;
|
2010-06-20 21:05:11 +00:00
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text.RegularExpressions;
|
2011-06-22 01:03:27 +00:00
|
|
|
|
using System.Xml;
|
2011-03-08 23:55:21 +00:00
|
|
|
|
|
2010-08-02 15:42:42 +00:00
|
|
|
|
namespace SparkleLib {
|
2010-06-20 21:05:11 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public class SparkleRepoGit : SparkleRepoBase {
|
2011-05-18 18:12:45 +00:00
|
|
|
|
|
2011-09-05 15:36:03 +00:00
|
|
|
|
private string exlude_rules_file_path;
|
|
|
|
|
private string ExclusionBlock = "#Temporary Exclusions";
|
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public SparkleRepoGit (string path, SparkleBackend backend) :
|
2011-09-05 15:36:03 +00:00
|
|
|
|
base (path, backend) {
|
|
|
|
|
// Set exclude file path
|
|
|
|
|
exlude_rules_file_path = SparkleHelpers.CombineMore (
|
|
|
|
|
LocalPath, ".git", "info", "exclude");
|
|
|
|
|
}
|
2011-05-18 18:12:45 +00:00
|
|
|
|
|
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public override string Identifier {
|
2011-05-14 17:11:31 +00:00
|
|
|
|
get {
|
|
|
|
|
|
|
|
|
|
// Because git computes a hash based on content,
|
|
|
|
|
// author, and timestamp; it is unique enough to
|
|
|
|
|
// use the hash of the first commit as an identifier
|
|
|
|
|
// for our folder
|
2011-05-17 12:15:44 +00:00
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "rev-list --reverse HEAD");
|
2011-05-14 17:11:31 +00:00
|
|
|
|
git.Start ();
|
2011-05-17 12:15:44 +00:00
|
|
|
|
|
|
|
|
|
// Reading the standard output HAS to go before
|
|
|
|
|
// WaitForExit, or it will hang forever on output > 4096 bytes
|
|
|
|
|
string output = git.StandardOutput.ReadToEnd ();
|
2011-05-14 17:11:31 +00:00
|
|
|
|
git.WaitForExit ();
|
|
|
|
|
|
2011-08-06 21:44:37 +00:00
|
|
|
|
if (output.Length < 40)
|
|
|
|
|
return null;
|
|
|
|
|
|
2011-05-17 12:15:44 +00:00
|
|
|
|
return output.Substring (0, 40);
|
2011-05-14 17:11:31 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-06-29 19:28:49 +00:00
|
|
|
|
public override string [] UnsyncedFilePaths {
|
|
|
|
|
get {
|
|
|
|
|
List<string> file_paths = new List<string> ();
|
|
|
|
|
|
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "status --porcelain");
|
|
|
|
|
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 ().TrimEnd ();
|
|
|
|
|
git.WaitForExit ();
|
|
|
|
|
|
|
|
|
|
string [] lines = output.Split ("\n".ToCharArray ());
|
|
|
|
|
foreach (string line in lines) {
|
|
|
|
|
if (line [1].ToString ().Equals ("M") ||
|
|
|
|
|
line [1].ToString ().Equals ("?") ||
|
|
|
|
|
line [1].ToString ().Equals ("A")) {
|
|
|
|
|
|
|
|
|
|
string path = line.Substring (3);
|
|
|
|
|
path = path.Trim ("\"".ToCharArray ());
|
|
|
|
|
file_paths.Add (path);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return file_paths.ToArray ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public override string CurrentRevision {
|
|
|
|
|
get {
|
|
|
|
|
|
|
|
|
|
// Remove stale rebase-apply files because it
|
|
|
|
|
// makes the method return the wrong hashes.
|
|
|
|
|
string rebase_apply_file = SparkleHelpers.CombineMore (LocalPath, ".git", "rebase-apply");
|
|
|
|
|
if (File.Exists (rebase_apply_file))
|
|
|
|
|
File.Delete (rebase_apply_file);
|
|
|
|
|
|
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "log -1 --format=%H");
|
|
|
|
|
git.Start ();
|
|
|
|
|
git.WaitForExit ();
|
|
|
|
|
|
|
|
|
|
if (git.ExitCode == 0) {
|
2011-08-25 15:02:34 +00:00
|
|
|
|
string output = git.StandardOutput.ReadToEnd ();
|
2011-05-19 16:05:58 +00:00
|
|
|
|
return output.TrimEnd ();
|
2011-08-25 15:02:34 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public override bool CheckForRemoteChanges ()
|
2011-04-20 14:02:20 +00:00
|
|
|
|
{
|
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Checking for remote changes...");
|
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "ls-remote origin master");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
git.Start ();
|
|
|
|
|
git.WaitForExit ();
|
2011-05-18 18:57:52 +00:00
|
|
|
|
|
|
|
|
|
if (git.ExitCode != 0)
|
2011-05-19 16:05:58 +00:00
|
|
|
|
return false;
|
2011-05-18 18:57:52 +00:00
|
|
|
|
|
|
|
|
|
string remote_revision = git.StandardOutput.ReadToEnd ().TrimEnd ();
|
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
if (!remote_revision.StartsWith (CurrentRevision)) {
|
2011-05-18 18:57:52 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Remote changes found. (" + remote_revision + ")");
|
2011-05-19 16:05:58 +00:00
|
|
|
|
return true;
|
2011-08-25 15:02:34 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
} else {
|
|
|
|
|
return false;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-23 00:09:44 +00:00
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public override bool SyncUp ()
|
2011-04-20 14:02:20 +00:00
|
|
|
|
{
|
2011-05-19 16:05:58 +00:00
|
|
|
|
Add ();
|
2011-10-01 22:52:21 +00:00
|
|
|
|
|
|
|
|
|
string message = FormatCommitMessage ();
|
|
|
|
|
Commit (message);
|
2011-04-20 14:02:20 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "push origin master");
|
|
|
|
|
git.Start ();
|
2011-07-20 23:02:21 +00:00
|
|
|
|
git.StandardOutput.ReadToEnd ();
|
2011-05-19 16:05:58 +00:00
|
|
|
|
git.WaitForExit ();
|
2011-04-20 14:02:20 +00:00
|
|
|
|
|
2011-05-22 17:49:04 +00:00
|
|
|
|
if (git.ExitCode == 0)
|
2011-05-19 16:05:58 +00:00
|
|
|
|
return true;
|
2011-05-22 17:49:04 +00:00
|
|
|
|
else
|
2011-05-19 16:05:58 +00:00
|
|
|
|
return false;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
2010-08-28 18:56:19 +00:00
|
|
|
|
|
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public override bool SyncDown ()
|
2011-04-20 14:02:20 +00:00
|
|
|
|
{
|
2011-06-24 22:43:11 +00:00
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "fetch -v");
|
2011-05-19 16:05:58 +00:00
|
|
|
|
git.Start ();
|
|
|
|
|
git.WaitForExit ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2011-05-22 14:46:15 +00:00
|
|
|
|
if (git.ExitCode == 0) {
|
2011-05-19 16:05:58 +00:00
|
|
|
|
Rebase ();
|
|
|
|
|
return true;
|
2011-08-25 15:02:34 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
} else {
|
|
|
|
|
return false;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2011-04-15 00:28:42 +00:00
|
|
|
|
|
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public override bool AnyDifferences {
|
2011-04-20 14:02:20 +00:00
|
|
|
|
get {
|
2011-10-01 22:52:21 +00:00
|
|
|
|
FillEmptyDirectories (LocalPath);
|
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "status --porcelain");
|
|
|
|
|
git.Start ();
|
|
|
|
|
|
2011-06-29 19:45:37 +00:00
|
|
|
|
// Reading the standard output HAS to go before
|
|
|
|
|
// WaitForExit, or it will hang forever on output > 4096 bytes
|
2011-04-21 13:46:46 +00:00
|
|
|
|
string output = git.StandardOutput.ReadToEnd ().TrimEnd ();
|
2011-06-29 19:45:37 +00:00
|
|
|
|
git.WaitForExit ();
|
|
|
|
|
|
2011-04-21 13:46:46 +00:00
|
|
|
|
string [] lines = output.Split ("\n".ToCharArray ());
|
|
|
|
|
|
|
|
|
|
foreach (string line in lines) {
|
2011-04-28 22:32:16 +00:00
|
|
|
|
if (line.Length > 1 && !line [1].Equals (" "))
|
2011-04-21 13:46:46 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public override bool HasUnsyncedChanges {
|
2011-04-21 21:14:44 +00:00
|
|
|
|
get {
|
2011-05-19 16:05:58 +00:00
|
|
|
|
string unsynced_file_path = SparkleHelpers.CombineMore (LocalPath,
|
|
|
|
|
".git", "has_unsynced_changes");
|
|
|
|
|
|
|
|
|
|
return File.Exists (unsynced_file_path);
|
|
|
|
|
}
|
2011-04-21 21:14:44 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
set {
|
|
|
|
|
string unsynced_file_path = SparkleHelpers.CombineMore (LocalPath,
|
|
|
|
|
".git", "has_unsynced_changes");
|
|
|
|
|
|
|
|
|
|
if (value) {
|
|
|
|
|
if (!File.Exists (unsynced_file_path))
|
2011-10-01 22:52:21 +00:00
|
|
|
|
File.Create (unsynced_file_path).Close ();
|
2011-05-19 16:05:58 +00:00
|
|
|
|
} else {
|
|
|
|
|
File.Delete (unsynced_file_path);
|
|
|
|
|
}
|
2011-04-21 21:14:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
// Stages the made changes
|
|
|
|
|
private void Add ()
|
|
|
|
|
{
|
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "add --all");
|
2011-04-16 23:30:57 +00:00
|
|
|
|
git.Start ();
|
|
|
|
|
git.WaitForExit ();
|
|
|
|
|
|
2011-05-17 19:40:14 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Changes staged");
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
2010-07-22 21:10:38 +00:00
|
|
|
|
|
2011-09-05 15:36:03 +00:00
|
|
|
|
// Add a new file to be ignored
|
|
|
|
|
public override bool AddExclusionRule (FileSystemEventArgs args) {
|
|
|
|
|
|
|
|
|
|
string RelativePath = SparkleHelpers.DiffPaths(args.FullPath, LocalPath);
|
|
|
|
|
|
|
|
|
|
List<String> exclusions;
|
|
|
|
|
try {
|
|
|
|
|
exclusions = ReadExclusionRules();
|
|
|
|
|
}
|
|
|
|
|
catch {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Look for the local exclusions section
|
|
|
|
|
bool added = false;
|
|
|
|
|
for(int i = 0; i < exclusions.Count; i++) {
|
|
|
|
|
string entry = exclusions[i];
|
|
|
|
|
if(entry.Equals(ExclusionBlock)) {
|
|
|
|
|
// add a new exclusion rule containing a file path
|
|
|
|
|
exclusions.Insert(i + 1, RelativePath);
|
|
|
|
|
added = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* For compability to existing repos:
|
|
|
|
|
* Add a "#Temporary Exclusions"-Block to the
|
|
|
|
|
* ignore file in order to recognize this
|
|
|
|
|
* exclude rules later on
|
|
|
|
|
*/
|
|
|
|
|
if(!added) {
|
|
|
|
|
exclusions.Add(ExclusionBlock);
|
|
|
|
|
exclusions.Add(RelativePath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write exceptions list back to file
|
|
|
|
|
return WriteExclusionRules(exclusions);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check whether a specific rule exists in the exclusion file
|
|
|
|
|
public override bool ExclusionRuleExists(FileSystemEventArgs args) {
|
|
|
|
|
string RelativePath = SparkleHelpers.DiffPaths(args.FullPath, LocalPath);
|
|
|
|
|
|
|
|
|
|
List<String> exclusions;
|
|
|
|
|
try {
|
|
|
|
|
// Read rules from temporary block only
|
|
|
|
|
exclusions = ReadExclusionRules(true);
|
|
|
|
|
|
|
|
|
|
foreach(string entry in exclusions) {
|
|
|
|
|
if(entry.Equals(RelativePath)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch {
|
|
|
|
|
SparkleHelpers.DebugInfo("Error", "Cannot determine whether an exclusion rule for " +
|
|
|
|
|
args.FullPath + " already exists or not.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove file from exclusion list when they are readable again
|
|
|
|
|
public override bool RemoveExclusionRule(FileSystemEventArgs args) {
|
|
|
|
|
string RelativePath = SparkleHelpers.DiffPaths(args.FullPath, LocalPath);
|
|
|
|
|
|
|
|
|
|
List<String> exclusions;
|
|
|
|
|
try {
|
|
|
|
|
exclusions = ReadExclusionRules();
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Removing a rule should only apply to rules in the "Temporary Exclusion"-block.
|
|
|
|
|
* Therefore we first read until reaching the block and then remove the rule.
|
|
|
|
|
*
|
|
|
|
|
* We cannot use ReadExclusionRules(true) here since we write all lines back
|
|
|
|
|
* to the file. This would result in a crippled exclusion file.
|
|
|
|
|
*/
|
|
|
|
|
bool BlockReached = false;
|
|
|
|
|
foreach(string entry in exclusions) {
|
|
|
|
|
if(entry.Equals(ExclusionBlock)) {
|
|
|
|
|
BlockReached = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove this rule
|
|
|
|
|
if(BlockReached && entry.Equals(RelativePath)) {
|
|
|
|
|
exclusions.Remove(entry);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return WriteExclusionRules(exclusions);
|
|
|
|
|
} catch {
|
|
|
|
|
SparkleHelpers.DebugInfo("Error", "Unable to remove exclusion rule for entry " + RelativePath);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reads the exclusion rules file into a string list
|
|
|
|
|
private List<String> ReadExclusionRules() {
|
|
|
|
|
|
|
|
|
|
List<String> exclusions = new List<String>();
|
|
|
|
|
TextReader reader = new StreamReader (exlude_rules_file_path);;
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
while(reader.Peek() > -1) {
|
|
|
|
|
exclusions.Add(reader.ReadLine().TrimEnd());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (IOException e) {
|
|
|
|
|
SparkleHelpers.DebugInfo("Error", "Reading from exclusion file failed: " + e.Message);
|
|
|
|
|
return new List<String>();
|
|
|
|
|
}
|
|
|
|
|
finally {
|
|
|
|
|
if(reader != null) {
|
|
|
|
|
reader.Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return exclusions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reads rules only from temporary exclusion block
|
|
|
|
|
private List<String> ReadExclusionRules(bool TempOnly) {
|
|
|
|
|
if(TempOnly) {
|
|
|
|
|
bool ForceRead = false;
|
|
|
|
|
List<String> exclusions = new List<String>();
|
|
|
|
|
foreach(string entry in ReadExclusionRules()) {
|
|
|
|
|
if(ForceRead || entry.Equals(ExclusionBlock)) {
|
|
|
|
|
exclusions.Add(entry);
|
|
|
|
|
ForceRead = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return exclusions;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ReadExclusionRules();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Writes the exclusion rules file with a given string list
|
|
|
|
|
private bool WriteExclusionRules(List<String> lines) {
|
|
|
|
|
|
|
|
|
|
TextWriter writer = new StreamWriter (exlude_rules_file_path);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
foreach(string line in lines) {
|
|
|
|
|
writer.WriteLine(line.TrimEnd());
|
|
|
|
|
}
|
|
|
|
|
} catch(IOException e) {
|
|
|
|
|
SparkleHelpers.DebugInfo("Error", "Writing into exclusion file failed: " + e.Message);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
finally {
|
|
|
|
|
if(writer != null) {
|
|
|
|
|
writer.Close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
// Removes unneeded objects
|
|
|
|
|
private void CollectGarbage ()
|
|
|
|
|
{
|
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "gc");
|
|
|
|
|
git.Start ();
|
|
|
|
|
git.WaitForExit ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Garbage collected.");
|
|
|
|
|
}
|
2010-08-05 10:40:12 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
// Commits the made changes
|
2011-05-18 22:18:11 +00:00
|
|
|
|
private void Commit (string message)
|
2011-04-20 14:02:20 +00:00
|
|
|
|
{
|
2011-06-10 20:40:13 +00:00
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "commit -m \"" + message + "\"");
|
2011-04-20 14:02:20 +00:00
|
|
|
|
git.Start ();
|
2011-07-20 23:02:21 +00:00
|
|
|
|
git.StandardOutput.ReadToEnd ();
|
2011-04-20 14:02:20 +00:00
|
|
|
|
git.WaitForExit ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Commit", "[" + Name + "] " + message);
|
2010-10-07 21:43:08 +00:00
|
|
|
|
|
2011-05-22 17:54:47 +00:00
|
|
|
|
// Collect garbage pseudo-randomly. Turn off for
|
|
|
|
|
// now: too resource heavy.
|
|
|
|
|
// if (DateTime.Now.Second % 10 == 0)
|
|
|
|
|
// CollectGarbage ();
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
2010-10-07 21:43:08 +00:00
|
|
|
|
|
2011-02-26 14:20:32 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
// Merges the fetched changes
|
2011-05-18 22:18:11 +00:00
|
|
|
|
private void Rebase ()
|
2011-04-20 14:02:20 +00:00
|
|
|
|
{
|
2011-05-18 22:18:11 +00:00
|
|
|
|
DisableWatching ();
|
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
if (AnyDifferences) {
|
|
|
|
|
Add ();
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
string commit_message = FormatCommitMessage ();
|
|
|
|
|
Commit (commit_message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SparkleGit git = new SparkleGit (LocalPath, "rebase -v FETCH_HEAD");
|
|
|
|
|
|
2011-05-18 18:57:52 +00:00
|
|
|
|
git.Start ();
|
|
|
|
|
git.WaitForExit ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2011-05-18 18:57:52 +00:00
|
|
|
|
if (git.ExitCode != 0) {
|
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Conflict detected. Trying to get out...");
|
2011-02-26 14:20:32 +00:00
|
|
|
|
|
2011-05-22 15:29:23 +00:00
|
|
|
|
while (AnyDifferences)
|
2011-05-18 18:57:52 +00:00
|
|
|
|
ResolveConflict ();
|
2011-05-14 02:18:38 +00:00
|
|
|
|
|
2011-05-18 18:57:52 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Conflict resolved.");
|
2011-05-19 16:05:58 +00:00
|
|
|
|
OnConflictResolved ();
|
2011-05-18 18:57:52 +00:00
|
|
|
|
}
|
2011-03-03 12:08:50 +00:00
|
|
|
|
|
2011-05-18 22:18:11 +00:00
|
|
|
|
EnableWatching ();
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
2010-06-20 21:05:11 +00:00
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2011-04-28 11:49:14 +00:00
|
|
|
|
private void ResolveConflict ()
|
|
|
|
|
{
|
2011-04-30 00:42:48 +00:00
|
|
|
|
// This is al 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
|
|
|
|
|
//
|
|
|
|
|
// 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'
|
|
|
|
|
|
2011-04-28 11:49:14 +00:00
|
|
|
|
SparkleGit git_status = new SparkleGit (LocalPath, "status --porcelain");
|
|
|
|
|
git_status.Start ();
|
|
|
|
|
|
2011-06-29 19:45:37 +00:00
|
|
|
|
// 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 ();
|
2011-04-28 11:49:14 +00:00
|
|
|
|
git_status.WaitForExit ();
|
|
|
|
|
|
2011-09-03 21:38:53 +00:00
|
|
|
|
if (String.IsNullOrEmpty (output)) {
|
|
|
|
|
// no conflict any more.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-28 11:49:14 +00:00
|
|
|
|
string [] lines = output.Split ("\n".ToCharArray ());
|
|
|
|
|
|
|
|
|
|
foreach (string line in lines) {
|
2011-04-30 00:42:48 +00:00
|
|
|
|
string conflicting_path = line.Substring (3);
|
|
|
|
|
conflicting_path = conflicting_path.Trim ("\"".ToCharArray ());
|
|
|
|
|
|
2011-05-06 10:31:30 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Conflict type: " + line);
|
|
|
|
|
|
2011-04-30 00:42:48 +00:00
|
|
|
|
// 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 ();
|
2011-04-28 11:49:14 +00:00
|
|
|
|
|
2011-08-27 00:42:09 +00:00
|
|
|
|
// 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 ("HH\\hmm MMM d");
|
2011-10-01 22:52:21 +00:00
|
|
|
|
string their_path = conflicting_path + " (" + SparkleConfig.DefaultConfig.User.Name + ", " + timestamp + ")";
|
2011-04-30 00:42:48 +00:00
|
|
|
|
string abs_conflicting_path = Path.Combine (LocalPath, conflicting_path);
|
|
|
|
|
string abs_their_path = Path.Combine (LocalPath, their_path);
|
2011-04-28 11:49:14 +00:00
|
|
|
|
|
2011-04-30 00:42:48 +00:00
|
|
|
|
File.Move (abs_conflicting_path, abs_their_path);
|
|
|
|
|
|
|
|
|
|
// Recover server version
|
2011-04-28 11:49:14 +00:00
|
|
|
|
SparkleGit git_ours = new SparkleGit (LocalPath,
|
2011-04-30 00:42:48 +00:00
|
|
|
|
"checkout --ours \"" + conflicting_path + "\"");
|
2011-04-28 11:49:14 +00:00
|
|
|
|
git_ours.Start ();
|
|
|
|
|
git_ours.WaitForExit ();
|
|
|
|
|
|
2011-04-30 00:42:48 +00:00
|
|
|
|
Add ();
|
2011-04-28 11:49:14 +00:00
|
|
|
|
|
2011-04-30 00:42:48 +00:00
|
|
|
|
SparkleGit git_rebase_continue = new SparkleGit (LocalPath, "rebase --continue");
|
|
|
|
|
git_rebase_continue.Start ();
|
|
|
|
|
git_rebase_continue.WaitForExit ();
|
|
|
|
|
}
|
2011-04-28 22:32:16 +00:00
|
|
|
|
|
2011-04-30 00:42:48 +00:00
|
|
|
|
// The local version has been modified, but the server version was removed
|
|
|
|
|
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
|
|
|
|
|
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 ();
|
2011-04-28 11:49:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-05-18 18:12:45 +00:00
|
|
|
|
// Returns a list of the latest change sets
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public override List <SparkleChangeSet> GetChangeSets (int count)
|
2011-04-20 14:02:20 +00:00
|
|
|
|
{
|
|
|
|
|
if (count < 1)
|
|
|
|
|
count = 30;
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-05-16 23:49:01 +00:00
|
|
|
|
List <SparkleChangeSet> change_sets = new List <SparkleChangeSet> ();
|
2011-04-20 14:02:20 +00:00
|
|
|
|
|
2011-04-28 11:46:22 +00:00
|
|
|
|
SparkleGit git_log = new SparkleGit (LocalPath, "log -" + count + " --raw -M --date=iso");
|
2011-06-11 19:52:41 +00:00
|
|
|
|
if ((SparkleBackend.Platform == PlatformID.Unix ||
|
|
|
|
|
SparkleBackend.Platform == PlatformID.MacOSX)) {
|
|
|
|
|
// this causes an IOException on windows
|
|
|
|
|
Console.OutputEncoding = System.Text.Encoding.Unicode;
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
git_log.Start ();
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
// 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 j = 0;
|
|
|
|
|
string entry = "", last_entry = "";
|
|
|
|
|
foreach (string line in lines) {
|
|
|
|
|
if (line.StartsWith ("commit") && j > 0) {
|
|
|
|
|
entries.Add (entry);
|
|
|
|
|
entry = "";
|
2011-05-19 16:05:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
entry += line + "\n";
|
|
|
|
|
j++;
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
last_entry = entry;
|
|
|
|
|
}
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
entries.Add (last_entry);
|
|
|
|
|
|
2011-05-04 23:07:02 +00:00
|
|
|
|
Regex merge_regex = new Regex (@"commit ([a-z0-9]{40})\n" +
|
2011-05-03 17:13:02 +00:00
|
|
|
|
"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);
|
|
|
|
|
|
2011-05-04 23:07:02 +00:00
|
|
|
|
Regex non_merge_regex = new Regex (@"commit ([a-z0-9]{40})\n" +
|
2011-05-03 17:13:02 +00:00
|
|
|
|
"Author: (.+) <(.+)>\n" +
|
|
|
|
|
"Date: ([0-9]{4})-([0-9]{2})-([0-9]{2}) " +
|
2011-05-29 15:48:47 +00:00
|
|
|
|
"([0-9]{2}):([0-9]{2}):([0-9]{2}) (.[0-9]{4})\n" +
|
2011-05-03 17:13:02 +00:00
|
|
|
|
"*", RegexOptions.Compiled);
|
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
foreach (string log_entry in entries) {
|
|
|
|
|
Regex regex;
|
|
|
|
|
bool is_merge_commit = false;
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
if (log_entry.Contains ("\nMerge: ")) {
|
2011-05-03 17:13:02 +00:00
|
|
|
|
regex = merge_regex;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
is_merge_commit = true;
|
|
|
|
|
} else {
|
2011-05-03 17:13:02 +00:00
|
|
|
|
regex = non_merge_regex;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
Match match = regex.Match (log_entry);
|
|
|
|
|
|
|
|
|
|
if (match.Success) {
|
2011-05-16 23:49:01 +00:00
|
|
|
|
SparkleChangeSet change_set = new SparkleChangeSet ();
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-06-22 01:03:27 +00:00
|
|
|
|
change_set.Folder = Name;
|
|
|
|
|
change_set.Revision = match.Groups [1].Value;
|
2011-10-01 22:52:21 +00:00
|
|
|
|
change_set.User.Name = match.Groups [2].Value;
|
|
|
|
|
change_set.User.Email = match.Groups [3].Value;
|
|
|
|
|
change_set.IsMagical = is_merge_commit;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
|
2011-05-16 23:59:03 +00:00
|
|
|
|
change_set.Timestamp = new DateTime (int.Parse (match.Groups [4].Value),
|
2011-04-20 14:02:20 +00:00
|
|
|
|
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));
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-06-14 23:34:29 +00:00
|
|
|
|
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);
|
2011-05-29 15:48:47 +00:00
|
|
|
|
|
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
string [] entry_lines = log_entry.Split ("\n".ToCharArray ());
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
foreach (string entry_line in entry_lines) {
|
|
|
|
|
if (entry_line.StartsWith (":")) {
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
string change_type = entry_line [37].ToString ();
|
|
|
|
|
string file_path = entry_line.Substring (39);
|
2011-04-28 11:46:22 +00:00
|
|
|
|
string to_file_path;
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-10-01 22:52:21 +00:00
|
|
|
|
if (file_path.EndsWith (".empty"))
|
|
|
|
|
file_path = file_path.Substring (0, file_path.Length - ".empty".Length);
|
|
|
|
|
|
2011-07-17 00:22:39 +00:00
|
|
|
|
if (change_type.Equals ("A") && !file_path.Contains (".notes")) {
|
2011-05-16 23:49:01 +00:00
|
|
|
|
change_set.Added.Add (file_path);
|
2011-06-09 23:01:45 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
} else if (change_type.Equals ("M")) {
|
2011-05-16 23:49:01 +00:00
|
|
|
|
change_set.Edited.Add (file_path);
|
2011-06-09 23:01:45 +00:00
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
} else if (change_type.Equals ("D")) {
|
2011-05-16 23:49:01 +00:00
|
|
|
|
change_set.Deleted.Add (file_path);
|
2011-06-09 23:01:45 +00:00
|
|
|
|
|
2011-04-28 11:46:22 +00:00
|
|
|
|
} 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);
|
|
|
|
|
|
2011-05-16 23:49:01 +00:00
|
|
|
|
change_set.MovedFrom.Add (file_path);
|
|
|
|
|
change_set.MovedTo.Add (to_file_path);
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-05-19 16:05:58 +00:00
|
|
|
|
|
2011-07-17 00:37:36 +00:00
|
|
|
|
if ((change_set.Added.Count +
|
|
|
|
|
change_set.Edited.Count +
|
2011-08-26 20:00:33 +00:00
|
|
|
|
change_set.Deleted.Count +
|
|
|
|
|
change_set.MovedFrom.Count) > 0) {
|
2011-07-17 00:22:39 +00:00
|
|
|
|
|
|
|
|
|
change_set.Notes.AddRange (GetNotes (change_set.Revision));
|
|
|
|
|
change_sets.Add (change_set);
|
|
|
|
|
}
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-08 19:16:48 +00:00
|
|
|
|
|
2011-05-16 23:49:01 +00:00
|
|
|
|
return change_sets;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
2010-08-29 10:38:34 +00:00
|
|
|
|
|
2010-06-20 21:05:11 +00:00
|
|
|
|
|
2011-10-01 22:52:21 +00:00
|
|
|
|
// Git doesn't track empty directories, so this method
|
|
|
|
|
// fills them all with a hidden empty file
|
|
|
|
|
private void FillEmptyDirectories (string path)
|
|
|
|
|
{
|
|
|
|
|
foreach (string child_path in Directory.GetDirectories (path)) {
|
|
|
|
|
if (child_path.EndsWith (".git") || child_path.EndsWith (".notes"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
FillEmptyDirectories (child_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Directory.GetFiles (path).Length == 0)
|
|
|
|
|
File.Create (Path.Combine (path, ".empty")).Close ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2011-04-20 14:02:20 +00:00
|
|
|
|
// Creates a pretty commit message based on what has changed
|
|
|
|
|
private string FormatCommitMessage ()
|
|
|
|
|
{
|
2011-04-27 16:44:59 +00:00
|
|
|
|
List<string> Added = new List<string> ();
|
|
|
|
|
List<string> Modified = new List<string> ();
|
|
|
|
|
List<string> Removed = new List<string> ();
|
2011-04-21 12:25:28 +00:00
|
|
|
|
string file_name = "";
|
2011-05-17 12:15:44 +00:00
|
|
|
|
string message = "";
|
2011-04-21 12:25:28 +00:00
|
|
|
|
|
|
|
|
|
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
|
2011-04-21 13:46:46 +00:00
|
|
|
|
string output = git_status.StandardOutput.ReadToEnd ().Trim ("\n".ToCharArray ());
|
2011-04-21 12:25:28 +00:00
|
|
|
|
git_status.WaitForExit ();
|
|
|
|
|
|
|
|
|
|
string [] lines = output.Split ("\n".ToCharArray ());
|
|
|
|
|
foreach (string line in lines) {
|
|
|
|
|
if (line.StartsWith ("A"))
|
2011-05-17 19:40:14 +00:00
|
|
|
|
Added.Add (line.Substring (3));
|
2011-04-21 12:25:28 +00:00
|
|
|
|
else if (line.StartsWith ("M"))
|
2011-05-17 19:40:14 +00:00
|
|
|
|
Modified.Add (line.Substring (3));
|
2011-04-21 12:25:28 +00:00
|
|
|
|
else if (line.StartsWith ("D"))
|
2011-05-17 19:40:14 +00:00
|
|
|
|
Removed.Add (line.Substring (3));
|
2011-04-27 10:04:51 +00:00
|
|
|
|
else if (line.StartsWith ("R")) {
|
|
|
|
|
Removed.Add (line.Substring (3, (line.IndexOf (" -> ") - 3)));
|
|
|
|
|
Added.Add (line.Substring (line.IndexOf (" -> ") + 4));
|
|
|
|
|
}
|
2011-04-21 12:25:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-17 21:37:22 +00:00
|
|
|
|
int count = 0;
|
|
|
|
|
int max_count = 20;
|
|
|
|
|
|
|
|
|
|
string n = Environment.NewLine;
|
|
|
|
|
|
2011-05-18 13:03:50 +00:00
|
|
|
|
foreach (string added in Added) {
|
|
|
|
|
file_name = added.Trim ("\"".ToCharArray ());
|
|
|
|
|
message += "+ ‘" + file_name + "’" + n;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
|
2011-05-18 13:03:50 +00:00
|
|
|
|
count++;
|
|
|
|
|
if (count == max_count)
|
|
|
|
|
return message + "...";
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-18 13:03:50 +00:00
|
|
|
|
foreach (string modified in Modified) {
|
|
|
|
|
file_name = modified.Trim ("\"".ToCharArray ());
|
|
|
|
|
message += "/ ‘" + file_name + "’" + n;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
|
2011-05-18 13:03:50 +00:00
|
|
|
|
count++;
|
|
|
|
|
if (count == max_count)
|
|
|
|
|
return message + "...";
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-18 13:03:50 +00:00
|
|
|
|
foreach (string removed in Removed) {
|
|
|
|
|
file_name = removed.Trim ("\"".ToCharArray ());
|
|
|
|
|
message += "- ‘" + file_name + "’" + n;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
|
2011-05-18 13:03:50 +00:00
|
|
|
|
count++;
|
|
|
|
|
if (count == max_count)
|
|
|
|
|
return message + "..." + n;
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-06-10 20:40:13 +00:00
|
|
|
|
message = message.Replace ("\"", "");
|
2011-05-18 18:57:52 +00:00
|
|
|
|
return message.TrimEnd ();
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
2010-06-20 21:05:11 +00:00
|
|
|
|
|
2010-10-10 22:04:08 +00:00
|
|
|
|
|
2011-05-19 16:05:58 +00:00
|
|
|
|
public override bool UsesNotificationCenter
|
2011-03-22 13:44:52 +00:00
|
|
|
|
{
|
2011-04-20 14:02:20 +00:00
|
|
|
|
get {
|
|
|
|
|
string file_path = SparkleHelpers.CombineMore (LocalPath, ".git", "disable_notification_center");
|
|
|
|
|
return !File.Exists (file_path);
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-06-21 19:15:40 +00:00
|
|
|
|
|
|
|
|
|
|
2011-06-28 19:02:48 +00:00
|
|
|
|
public override void CreateInitialChangeSet ()
|
|
|
|
|
{
|
|
|
|
|
base.CreateInitialChangeSet ();
|
|
|
|
|
SyncUp ();
|
|
|
|
|
}
|
2011-04-20 14:02:20 +00:00
|
|
|
|
}
|
2010-07-24 12:32:05 +00:00
|
|
|
|
}
|