2010-05-03 00:04:39 +00:00
|
|
|
|
// SparkleShare, an instant update workflow to Git.
|
|
|
|
|
// 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
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// 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-05-03 00:04:39 +00:00
|
|
|
|
|
2010-06-01 22:51:43 +00:00
|
|
|
|
using Mono.Unix;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
using System;
|
2010-09-04 15:23:20 +00:00
|
|
|
|
using System.Collections.Generic;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
using System.Timers;
|
|
|
|
|
|
2010-08-02 15:42:42 +00:00
|
|
|
|
namespace SparkleLib {
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-08-12 23:27:28 +00:00
|
|
|
|
public class SparkleRepo {
|
2010-06-10 21:44:58 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
private Process Process;
|
2010-08-22 13:28:04 +00:00
|
|
|
|
private Timer RemoteTimer;
|
|
|
|
|
private Timer LocalTimer;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
private FileSystemWatcher Watcher;
|
2010-07-30 09:57:33 +00:00
|
|
|
|
private bool HasChanged;
|
2010-06-14 09:42:04 +00:00
|
|
|
|
private DateTime LastChange;
|
2010-07-03 19:37:43 +00:00
|
|
|
|
private System.Object ChangeLock = new System.Object();
|
2010-08-28 18:07:07 +00:00
|
|
|
|
private bool HasUnsyncedChanges;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
|
|
|
|
public string Name;
|
|
|
|
|
public string Domain;
|
2010-08-14 20:02:00 +00:00
|
|
|
|
public string Description;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
public string LocalPath;
|
|
|
|
|
public string RemoteOriginUrl;
|
|
|
|
|
public string CurrentHash;
|
|
|
|
|
public string UserEmail;
|
|
|
|
|
public string UserName;
|
2010-09-08 22:30:24 +00:00
|
|
|
|
public bool IsSyncing;
|
|
|
|
|
public bool IsBuffering;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-07-20 23:01:09 +00:00
|
|
|
|
public delegate void AddedEventHandler (object o, SparkleEventArgs args);
|
2010-07-21 23:17:20 +00:00
|
|
|
|
public delegate void CommitedEventHandler (object o, SparkleEventArgs args);
|
2010-07-24 12:32:05 +00:00
|
|
|
|
public delegate void PushingStartedEventHandler (object o, SparkleEventArgs args);
|
|
|
|
|
public delegate void PushingFinishedEventHandler (object o, SparkleEventArgs args);
|
2010-08-28 18:07:07 +00:00
|
|
|
|
public delegate void PushingFailedEventHandler (object o, SparkleEventArgs args);
|
2010-07-22 21:10:38 +00:00
|
|
|
|
public delegate void FetchingStartedEventHandler (object o, SparkleEventArgs args);
|
|
|
|
|
public delegate void FetchingFinishedEventHandler (object o, SparkleEventArgs args);
|
2010-07-24 12:32:05 +00:00
|
|
|
|
public delegate void NewCommitEventHandler (object o, NewCommitArgs args);
|
2010-07-24 14:03:58 +00:00
|
|
|
|
public delegate void ConflictDetectedEventHandler (object o, SparkleEventArgs args);
|
2010-08-28 18:07:07 +00:00
|
|
|
|
public delegate void ChangesDetectedEventHandler (object o, SparkleEventArgs args);
|
2010-08-28 18:56:19 +00:00
|
|
|
|
public delegate void CommitEndedUpEmptyEventHandler (object o, SparkleEventArgs args);
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
public event AddedEventHandler Added;
|
|
|
|
|
public event CommitedEventHandler Commited;
|
|
|
|
|
public event PushingStartedEventHandler PushingStarted;
|
|
|
|
|
public event PushingFinishedEventHandler PushingFinished;
|
2010-08-28 18:07:07 +00:00
|
|
|
|
public event PushingFailedEventHandler PushingFailed;
|
2010-07-24 14:03:58 +00:00
|
|
|
|
public event FetchingStartedEventHandler FetchingStarted;
|
|
|
|
|
public event FetchingFinishedEventHandler FetchingFinished;
|
|
|
|
|
public event NewCommitEventHandler NewCommit;
|
|
|
|
|
public event ConflictDetectedEventHandler ConflictDetected;
|
2010-08-28 18:07:07 +00:00
|
|
|
|
public event ChangesDetectedEventHandler ChangesDetected;
|
2010-08-28 18:56:19 +00:00
|
|
|
|
public event CommitEndedUpEmptyEventHandler CommitEndedUpEmpty;
|
2010-07-20 23:01:09 +00:00
|
|
|
|
|
2010-06-15 00:08:35 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
public SparkleRepo (string path)
|
2010-06-15 00:08:35 +00:00
|
|
|
|
{
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-07-31 19:13:01 +00:00
|
|
|
|
if (!Directory.Exists (path))
|
|
|
|
|
Directory.CreateDirectory (path);
|
2010-07-29 13:47:09 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
LocalPath = path;
|
|
|
|
|
Name = Path.GetFileName (LocalPath);
|
|
|
|
|
|
2010-07-27 13:49:48 +00:00
|
|
|
|
Process = new Process () {
|
|
|
|
|
EnableRaisingEvents = true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Process.StartInfo.FileName = "git";
|
2010-05-03 00:04:39 +00:00
|
|
|
|
Process.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
Process.StartInfo.UseShellExecute = false;
|
2010-07-20 21:21:37 +00:00
|
|
|
|
Process.StartInfo.WorkingDirectory = LocalPath;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-08-28 18:07:07 +00:00
|
|
|
|
UserName = GetUserName ();
|
|
|
|
|
UserEmail = GetUserEmail ();
|
|
|
|
|
RemoteOriginUrl = GetRemoteOriginUrl ();
|
|
|
|
|
CurrentHash = GetCurrentHash ();
|
|
|
|
|
Domain = GetDomain (RemoteOriginUrl);
|
|
|
|
|
Description = GetDescription ();
|
|
|
|
|
HasUnsyncedChanges = false;
|
2010-09-08 22:30:24 +00:00
|
|
|
|
IsSyncing = false;
|
|
|
|
|
IsBuffering = false;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-08-08 19:16:48 +00:00
|
|
|
|
if (CurrentHash == null)
|
|
|
|
|
CreateInitialCommit ();
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-07-30 09:57:33 +00:00
|
|
|
|
HasChanged = false;
|
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
// Watch the repository's folder
|
2010-07-20 21:21:37 +00:00
|
|
|
|
Watcher = new FileSystemWatcher (LocalPath) {
|
|
|
|
|
IncludeSubdirectories = true,
|
|
|
|
|
EnableRaisingEvents = true,
|
|
|
|
|
Filter = "*"
|
|
|
|
|
};
|
|
|
|
|
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Watcher.Changed += new FileSystemEventHandler (OnFileActivity);
|
|
|
|
|
Watcher.Created += new FileSystemEventHandler (OnFileActivity);
|
|
|
|
|
Watcher.Deleted += new FileSystemEventHandler (OnFileActivity);
|
2010-08-29 10:38:34 +00:00
|
|
|
|
Watcher.Renamed += new RenamedEventHandler (OnFileActivity);
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-07-24 21:31:24 +00:00
|
|
|
|
// Fetch remote changes every minute
|
2010-08-22 13:28:04 +00:00
|
|
|
|
RemoteTimer = new Timer () {
|
2010-08-22 13:30:17 +00:00
|
|
|
|
Interval = 60000
|
2010-07-20 21:21:37 +00:00
|
|
|
|
};
|
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
RemoteTimer.Elapsed += delegate {
|
|
|
|
|
CheckForRemoteChanges ();
|
2010-08-28 18:07:07 +00:00
|
|
|
|
if (HasUnsyncedChanges)
|
|
|
|
|
Push ();
|
2010-05-03 00:04:39 +00:00
|
|
|
|
};
|
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
// Keep a Local that checks if there are changes and
|
2010-07-20 21:21:37 +00:00
|
|
|
|
// whether they have settled
|
2010-08-22 13:28:04 +00:00
|
|
|
|
LocalTimer = new Timer () {
|
2010-07-20 21:21:37 +00:00
|
|
|
|
Interval = 4000
|
|
|
|
|
};
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
LocalTimer.Elapsed += delegate (object o, ElapsedEventArgs args) {
|
2010-07-20 21:21:37 +00:00
|
|
|
|
CheckForChanges ();
|
2010-05-29 14:18:38 +00:00
|
|
|
|
};
|
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
RemoteTimer.Start ();
|
|
|
|
|
LocalTimer.Start ();
|
2010-06-14 09:42:04 +00:00
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
// Add everything that changed
|
2010-08-08 14:45:28 +00:00
|
|
|
|
// since SparkleShare was stopped
|
2010-06-16 13:42:11 +00:00
|
|
|
|
AddCommitAndPush ();
|
2010-05-29 12:43:28 +00:00
|
|
|
|
|
2010-08-08 19:16:48 +00:00
|
|
|
|
if (CurrentHash == null)
|
|
|
|
|
CurrentHash = GetCurrentHash ();
|
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Idling...");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
private void CheckForRemoteChanges ()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Checking for remote changes...");
|
|
|
|
|
|
|
|
|
|
Process process = new Process () {
|
|
|
|
|
EnableRaisingEvents = true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
process.StartInfo.FileName = "git";
|
|
|
|
|
process.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
process.StartInfo.UseShellExecute = false;
|
|
|
|
|
process.StartInfo.WorkingDirectory = LocalPath;
|
|
|
|
|
process.StartInfo.Arguments = "ls-remote origin master";
|
|
|
|
|
process.Start ();
|
|
|
|
|
|
|
|
|
|
process.Exited += delegate {
|
2010-08-23 08:42:34 +00:00
|
|
|
|
|
|
|
|
|
if (process.ExitCode != 0)
|
|
|
|
|
return;
|
2010-08-22 13:28:04 +00:00
|
|
|
|
|
2010-08-23 08:42:34 +00:00
|
|
|
|
string remote_hash = process.StandardOutput.ReadToEnd ();
|
2010-08-22 13:28:04 +00:00
|
|
|
|
|
|
|
|
|
if (!remote_hash.StartsWith (CurrentHash)) {
|
|
|
|
|
|
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Remote changes found.");
|
|
|
|
|
Fetch ();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
private void CheckForChanges ()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
lock (ChangeLock) {
|
|
|
|
|
|
|
|
|
|
if (HasChanged) {
|
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes found, checking if settled.");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
|
|
|
|
DateTime now = DateTime.UtcNow;
|
|
|
|
|
TimeSpan changed = new TimeSpan (now.Ticks - LastChange.Ticks);
|
|
|
|
|
|
|
|
|
|
if (changed.TotalMilliseconds > 5000) {
|
2010-08-28 18:56:19 +00:00
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes have settled, adding files...");
|
2010-08-28 18:56:19 +00:00
|
|
|
|
|
2010-09-08 22:30:24 +00:00
|
|
|
|
IsBuffering = false;
|
|
|
|
|
|
2010-08-28 18:56:19 +00:00
|
|
|
|
HasChanged = false;
|
2010-07-20 21:21:37 +00:00
|
|
|
|
AddCommitAndPush ();
|
2010-08-28 18:56:19 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-28 18:07:07 +00:00
|
|
|
|
// Starts a timerwhen something changes
|
|
|
|
|
private void OnFileActivity (object o, FileSystemEventArgs fse_args)
|
2010-06-15 00:08:35 +00:00
|
|
|
|
{
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-28 18:07:07 +00:00
|
|
|
|
WatcherChangeTypes wct = fse_args.ChangeType;
|
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
if (!ShouldIgnore (fse_args.FullPath)) {
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-09-08 22:30:24 +00:00
|
|
|
|
IsBuffering = true;
|
|
|
|
|
|
2010-08-28 18:07:07 +00:00
|
|
|
|
// Only fire the event if the timer has been stopped.
|
|
|
|
|
// This prevents multiple events from being raised whilst "buffering".
|
|
|
|
|
if (!HasChanged) {
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-28 18:07:07 +00:00
|
|
|
|
SparkleEventArgs args = new SparkleEventArgs ("ChangesDetected");
|
2010-08-28 18:56:19 +00:00
|
|
|
|
|
2010-08-28 18:07:07 +00:00
|
|
|
|
if (ChangesDetected != null)
|
|
|
|
|
ChangesDetected (this, args);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SparkleHelpers.DebugInfo ("Event", "[" + Name + "] " + wct.ToString () + " '" + fse_args.Name + "'");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
RemoteTimer.Stop ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
|
|
|
|
lock (ChangeLock) {
|
2010-07-24 14:03:58 +00:00
|
|
|
|
|
2010-07-03 19:37:43 +00:00
|
|
|
|
LastChange = DateTime.UtcNow;
|
|
|
|
|
HasChanged = true;
|
2010-07-24 14:03:58 +00:00
|
|
|
|
|
2010-07-03 19:37:43 +00:00
|
|
|
|
}
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-28 18:56:19 +00:00
|
|
|
|
// When there are changes we generally want to Add, Commit and Push,
|
2010-07-20 21:21:37 +00:00
|
|
|
|
// so this method does them all with appropriate timers, etc. switched off
|
2010-06-16 13:42:11 +00:00
|
|
|
|
public void AddCommitAndPush ()
|
2010-06-15 00:08:35 +00:00
|
|
|
|
{
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-07-03 19:37:43 +00:00
|
|
|
|
try {
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
LocalTimer.Stop ();
|
|
|
|
|
RemoteTimer.Stop ();
|
2010-07-03 19:37:43 +00:00
|
|
|
|
|
|
|
|
|
Add ();
|
2010-07-24 14:03:58 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
string message = FormatCommitMessage ();
|
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
if (message != null) {
|
2010-07-24 14:03:58 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
Commit (message);
|
2010-08-22 13:28:04 +00:00
|
|
|
|
CheckForRemoteChanges ();
|
2010-07-03 19:37:43 +00:00
|
|
|
|
Push ();
|
2010-07-24 14:03:58 +00:00
|
|
|
|
|
2010-08-28 18:56:19 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
SparkleEventArgs args = new SparkleEventArgs ("CommitEndedUpEmpty");
|
|
|
|
|
|
|
|
|
|
if (CommitEndedUpEmpty != null)
|
|
|
|
|
CommitEndedUpEmpty (this, args);
|
|
|
|
|
|
2010-07-03 19:37:43 +00:00
|
|
|
|
}
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
RemoteTimer.Start ();
|
|
|
|
|
LocalTimer.Start ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
2010-06-20 21:05:11 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
|
|
|
|
|
2010-06-16 13:42:11 +00:00
|
|
|
|
// Stages the made changes
|
|
|
|
|
private void Add ()
|
2010-06-15 00:08:35 +00:00
|
|
|
|
{
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-06-04 19:45:42 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Staging changes...");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
Process.StartInfo.Arguments = "add --all";
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-05-10 23:21:56 +00:00
|
|
|
|
Process.WaitForExit ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-06-04 19:45:42 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Changes staged.");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
SparkleEventArgs args = new SparkleEventArgs ("Added");
|
|
|
|
|
|
2010-07-20 23:01:09 +00:00
|
|
|
|
if (Added != null)
|
|
|
|
|
Added (this, args);
|
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
// Commits the made changes
|
2010-07-24 14:03:58 +00:00
|
|
|
|
public void Commit (string message)
|
2010-06-15 00:08:35 +00:00
|
|
|
|
{
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
Process.StartInfo.Arguments = "status --porcelain";
|
|
|
|
|
Process.Start ();
|
|
|
|
|
Process.WaitForExit ();
|
|
|
|
|
|
2010-08-29 13:28:01 +00:00
|
|
|
|
if (Process.StandardOutput.ReadToEnd ().TrimEnd ("\n".ToCharArray ()).Equals (""))
|
2010-08-29 10:38:34 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Commit", "[" + Name + "] " + message);
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
Process.StartInfo.Arguments = "commit -m \"" + message + "\"";
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-05-10 23:21:56 +00:00
|
|
|
|
Process.WaitForExit ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
SparkleEventArgs args = new SparkleEventArgs ("Commited");
|
2010-07-24 14:03:58 +00:00
|
|
|
|
args.Message = message;
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
|
|
|
|
if (Commited != null)
|
2010-07-24 14:03:58 +00:00
|
|
|
|
Commited (this, args);
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-07-24 21:31:24 +00:00
|
|
|
|
// Fetches changes from the remote repository
|
2010-06-15 00:08:35 +00:00
|
|
|
|
public void Fetch ()
|
|
|
|
|
{
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-09-08 22:30:24 +00:00
|
|
|
|
IsSyncing = true;
|
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
RemoteTimer.Stop ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
Process process = new Process () {
|
|
|
|
|
EnableRaisingEvents = true
|
|
|
|
|
};
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
process.StartInfo.FileName = "git";
|
|
|
|
|
process.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
process.StartInfo.UseShellExecute = false;
|
|
|
|
|
process.StartInfo.WorkingDirectory = LocalPath;
|
2010-07-22 21:10:38 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
SparkleEventArgs args;
|
|
|
|
|
args = new SparkleEventArgs ("FetchingStarted");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
if (FetchingStarted != null)
|
|
|
|
|
FetchingStarted (this, args);
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Fetching changes...");
|
2010-07-27 11:00:01 +00:00
|
|
|
|
|
2010-08-14 10:22:49 +00:00
|
|
|
|
process.StartInfo.Arguments = "fetch -v origin master";
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
process.Start ();
|
2010-09-08 22:30:24 +00:00
|
|
|
|
process.WaitForExit ();
|
2010-08-05 10:40:12 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
process.Exited += delegate {
|
2010-08-05 10:40:12 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Changes fetched.");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
args = new SparkleEventArgs ("FetchingFinished");
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-09-11 09:52:10 +00:00
|
|
|
|
IsSyncing = false;
|
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
if (FetchingFinished != null)
|
|
|
|
|
FetchingFinished (this, args);
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
Rebase ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
RemoteTimer.Start ();
|
|
|
|
|
|
|
|
|
|
CurrentHash = GetCurrentHash ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-05 21:46:48 +00:00
|
|
|
|
};
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
// Merges the fetched changes
|
2010-06-15 00:08:35 +00:00
|
|
|
|
public void Rebase ()
|
|
|
|
|
{
|
2010-05-23 18:03:05 +00:00
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
Add ();
|
2010-08-11 22:53:32 +00:00
|
|
|
|
|
2010-05-23 13:14:24 +00:00
|
|
|
|
Watcher.EnableRaisingEvents = false;
|
2010-05-23 18:03:05 +00:00
|
|
|
|
|
2010-06-04 19:45:42 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Rebasing changes...");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-14 10:22:49 +00:00
|
|
|
|
Process.StartInfo.Arguments = "rebase -v FETCH_HEAD";
|
2010-05-03 00:04:39 +00:00
|
|
|
|
Process.WaitForExit ();
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-06-04 19:45:42 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Changes rebased.");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
|
|
|
|
string output = Process.StandardOutput.ReadToEnd ().Trim ();
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
if (!output.Contains ("up to date")) {
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
if (output.Contains ("Failed to merge")) {
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
2010-06-15 00:08:35 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Resolving conflict...");
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
|
|
|
|
Process.StartInfo.Arguments = "status";
|
|
|
|
|
Process.WaitForExit ();
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
output = Process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
string [] lines = Regex.Split (output, "\n");
|
2010-05-23 17:57:18 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
foreach (string line in lines) {
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
if (line.Contains ("needs merge")) {
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
string problem_file_name = line.Substring (line.IndexOf (": needs merge"));
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
Process.StartInfo.Arguments = "checkout --ours " + problem_file_name;
|
2010-05-23 17:40:35 +00:00
|
|
|
|
Process.WaitForExit ();
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
string timestamp = DateTime.Now.ToString ("H:mm d MMM yyyy");
|
2010-06-04 19:45:42 +00:00
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
File.Move (problem_file_name, problem_file_name + " (" + UserName + ", " + timestamp + ")");
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
Process.StartInfo.Arguments = "checkout --theirs " + problem_file_name;
|
2010-05-23 17:40:35 +00:00
|
|
|
|
Process.WaitForExit ();
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-05-23 17:40:35 +00:00
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
SparkleEventArgs args = new SparkleEventArgs ("ConflictDetected");
|
2010-06-12 17:03:15 +00:00
|
|
|
|
|
2010-07-24 14:03:58 +00:00
|
|
|
|
if (ConflictDetected != null)
|
|
|
|
|
ConflictDetected (this, args);
|
2010-06-12 17:03:15 +00:00
|
|
|
|
|
2010-05-23 17:40:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Add ();
|
|
|
|
|
|
2010-05-29 14:37:07 +00:00
|
|
|
|
Process.StartInfo.Arguments = "rebase --continue";
|
2010-05-23 17:40:35 +00:00
|
|
|
|
Process.WaitForExit ();
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-06-15 00:08:35 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Conflict resolved.");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-05-23 17:40:35 +00:00
|
|
|
|
Push ();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-24 12:32:05 +00:00
|
|
|
|
// Get the last commiter
|
|
|
|
|
Process.StartInfo.Arguments = "log --format=\"%an\" -1";
|
|
|
|
|
Process.Start ();
|
|
|
|
|
string author = Process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
|
2010-05-16 22:26:34 +00:00
|
|
|
|
// Get the last committer e-mail
|
2010-05-03 00:04:39 +00:00
|
|
|
|
Process.StartInfo.Arguments = "log --format=\"%ae\" -1";
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-07-24 12:32:05 +00:00
|
|
|
|
string email = Process.StandardOutput.ReadToEnd ().Trim ();
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
|
|
|
|
// Get the last commit message
|
|
|
|
|
Process.StartInfo.Arguments = "log --format=\"%s\" -1";
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-07-24 12:32:05 +00:00
|
|
|
|
string message = Process.StandardOutput.ReadToEnd ().Trim ();
|
2010-06-15 23:10:08 +00:00
|
|
|
|
|
2010-08-19 20:13:45 +00:00
|
|
|
|
NewCommitArgs new_commit_args = new NewCommitArgs (author, email, message, Name);
|
2010-06-15 23:10:08 +00:00
|
|
|
|
|
2010-07-24 12:32:05 +00:00
|
|
|
|
if (NewCommit != null)
|
2010-07-24 14:03:58 +00:00
|
|
|
|
NewCommit (this, new_commit_args);
|
2010-05-23 13:14:24 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-05-23 13:14:24 +00:00
|
|
|
|
Watcher.EnableRaisingEvents = true;
|
2010-07-20 21:21:37 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Idling...");
|
2010-05-08 20:06:59 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
// Pushes the changes to the remote repo
|
2010-06-15 00:08:35 +00:00
|
|
|
|
public void Push ()
|
|
|
|
|
{
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-09-08 22:30:24 +00:00
|
|
|
|
IsSyncing = true;
|
|
|
|
|
|
2010-07-24 12:32:05 +00:00
|
|
|
|
SparkleEventArgs args = new SparkleEventArgs ("PushingStarted");
|
|
|
|
|
|
|
|
|
|
if (PushingStarted != null)
|
|
|
|
|
PushingStarted (this, args);
|
|
|
|
|
|
2010-06-04 19:45:42 +00:00
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Pushing changes...");
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-08 19:16:48 +00:00
|
|
|
|
Process.StartInfo.Arguments = "push origin master";
|
2010-09-08 22:30:24 +00:00
|
|
|
|
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-05-03 00:04:39 +00:00
|
|
|
|
Process.WaitForExit ();
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-07-24 12:32:05 +00:00
|
|
|
|
Process.Exited += delegate {
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-28 18:07:07 +00:00
|
|
|
|
if (Process.ExitCode != 0) {
|
|
|
|
|
|
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Pushing failed.");
|
|
|
|
|
|
|
|
|
|
HasUnsyncedChanges = true;
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-08-28 18:07:07 +00:00
|
|
|
|
args = new SparkleEventArgs ("PushingFailed");
|
|
|
|
|
|
|
|
|
|
if (PushingFailed != null)
|
|
|
|
|
PushingFailed (this, args);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Changes pushed.");
|
|
|
|
|
|
|
|
|
|
args = new SparkleEventArgs ("PushingFinished");
|
|
|
|
|
|
|
|
|
|
HasUnsyncedChanges = false;
|
|
|
|
|
|
|
|
|
|
if (PushingFinished != null)
|
|
|
|
|
PushingFinished (this, args);
|
|
|
|
|
|
|
|
|
|
}
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-09-08 22:30:24 +00:00
|
|
|
|
IsSyncing = false;
|
|
|
|
|
|
2010-07-24 12:32:05 +00:00
|
|
|
|
};
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-08 14:45:28 +00:00
|
|
|
|
public void Stop ()
|
|
|
|
|
{
|
|
|
|
|
|
2010-08-22 13:28:04 +00:00
|
|
|
|
RemoteTimer.Stop ();
|
|
|
|
|
LocalTimer.Stop ();
|
2010-08-08 14:45:28 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
// Ignores repos, dotfiles, swap files and the like
|
|
|
|
|
private bool ShouldIgnore (string file_path)
|
2010-08-08 14:45:28 +00:00
|
|
|
|
{
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
if (file_path.EndsWith (".lock") ||
|
2010-08-30 17:20:47 +00:00
|
|
|
|
file_path.EndsWith ("~") ||
|
|
|
|
|
file_path.Contains (".git") ||
|
|
|
|
|
file_path.Contains ("/.") ||
|
|
|
|
|
file_path.EndsWith (".swp") ||
|
2010-08-29 10:38:34 +00:00
|
|
|
|
Directory.Exists (LocalPath + file_path)) {
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
return true; // Yes, ignore it
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-07-20 21:21:37 +00:00
|
|
|
|
|
2010-07-24 21:31:24 +00:00
|
|
|
|
// Gets the domain name of a given URL
|
2010-07-21 23:17:20 +00:00
|
|
|
|
public string GetDomain (string url)
|
|
|
|
|
{
|
|
|
|
|
|
2010-08-08 19:16:48 +00:00
|
|
|
|
if (RemoteOriginUrl.Equals (""))
|
|
|
|
|
return "";
|
|
|
|
|
|
2010-07-24 21:31:24 +00:00
|
|
|
|
string domain = url.Substring (RemoteOriginUrl.IndexOf ("@") + 1);
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
|
|
|
|
if (domain.IndexOf (":") > -1)
|
|
|
|
|
domain = domain.Substring (0, domain.IndexOf (":"));
|
|
|
|
|
else
|
|
|
|
|
domain = domain.Substring (0, domain.IndexOf ("/"));
|
|
|
|
|
|
|
|
|
|
return domain;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-08-14 20:02:00 +00:00
|
|
|
|
// Gets the repository's description
|
|
|
|
|
public string GetDescription ()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
string description_file_path = SparkleHelpers.CombineMore (LocalPath, ".git", "description");
|
|
|
|
|
|
|
|
|
|
if (!File.Exists (description_file_path))
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
StreamReader reader = new StreamReader (description_file_path);
|
|
|
|
|
string description = reader.ReadToEnd ();
|
|
|
|
|
reader.Close ();
|
|
|
|
|
|
|
|
|
|
if (description.StartsWith ("Unnamed"))
|
|
|
|
|
description = null;
|
|
|
|
|
|
|
|
|
|
return description;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
// Gets hash of the current commit
|
|
|
|
|
public string GetCurrentHash ()
|
|
|
|
|
{
|
|
|
|
|
|
2010-08-08 19:16:48 +00:00
|
|
|
|
Process process = new Process () {
|
|
|
|
|
EnableRaisingEvents = true
|
|
|
|
|
};
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
|
|
|
|
process.StartInfo.RedirectStandardOutput = true;
|
2010-08-08 19:16:48 +00:00
|
|
|
|
process.StartInfo.UseShellExecute = false;
|
|
|
|
|
process.StartInfo.FileName = "git";
|
|
|
|
|
process.StartInfo.WorkingDirectory = LocalPath;
|
|
|
|
|
process.StartInfo.Arguments = "rev-list --max-count=1 HEAD";
|
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
process.Start ();
|
2010-08-08 19:16:48 +00:00
|
|
|
|
process.WaitForExit ();
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
2010-08-08 19:16:48 +00:00
|
|
|
|
string current_hash = process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
|
|
|
|
|
if (process.ExitCode != 0)
|
|
|
|
|
return null;
|
|
|
|
|
else
|
|
|
|
|
return current_hash;
|
2010-07-21 23:17:20 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Gets the user's name, example: "User Name"
|
|
|
|
|
public string GetUserName ()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
string user_name;
|
|
|
|
|
|
|
|
|
|
Process process = new Process ();
|
|
|
|
|
process.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
process.StartInfo.UseShellExecute = false;
|
|
|
|
|
process.StartInfo.FileName = "git";
|
2010-08-02 20:19:22 +00:00
|
|
|
|
process.StartInfo.WorkingDirectory = LocalPath;
|
2010-07-21 23:17:20 +00:00
|
|
|
|
process.StartInfo.Arguments = "config --get user.name";
|
|
|
|
|
process.Start ();
|
|
|
|
|
|
|
|
|
|
user_name = process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
|
|
|
|
|
if (user_name.Equals ("")) {
|
|
|
|
|
|
|
|
|
|
UnixUserInfo unix_user_info = new UnixUserInfo (UnixEnvironment.UserName);
|
|
|
|
|
|
|
|
|
|
if (unix_user_info.RealName.Equals (""))
|
2010-08-15 14:41:47 +00:00
|
|
|
|
user_name = "Mysterious Stranger";
|
2010-07-21 23:17:20 +00:00
|
|
|
|
else
|
|
|
|
|
user_name = unix_user_info.RealName;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return user_name;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Gets the user's email, example: "person@gnome.org"
|
|
|
|
|
public string GetUserEmail ()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
string user_email;
|
|
|
|
|
|
|
|
|
|
Process process = new Process ();
|
|
|
|
|
process.StartInfo.UseShellExecute = false;
|
|
|
|
|
process.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
process.StartInfo.FileName = "git";
|
2010-08-02 20:19:22 +00:00
|
|
|
|
process.StartInfo.WorkingDirectory = LocalPath;
|
2010-07-21 23:17:20 +00:00
|
|
|
|
process.StartInfo.Arguments = "config --get user.email";
|
|
|
|
|
process.Start ();
|
2010-08-15 14:41:47 +00:00
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
user_email = process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
|
2010-08-15 14:41:47 +00:00
|
|
|
|
if (user_email.Equals (""))
|
|
|
|
|
user_email = "Unknown Email";
|
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
return user_email;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-08-08 19:16:48 +00:00
|
|
|
|
// Create a first commit in case the user has cloned
|
|
|
|
|
// an empty repository
|
|
|
|
|
private void CreateInitialCommit ()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
TextWriter writer = new StreamWriter (Path.Combine (LocalPath, "SparkleShare.txt"));
|
|
|
|
|
writer.WriteLine (":)");
|
|
|
|
|
writer.Close ();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-07-21 23:17:20 +00:00
|
|
|
|
// Gets the url of the remote repo, example: "ssh://git@git.gnome.org/project"
|
|
|
|
|
public string GetRemoteOriginUrl ()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
string remote_origin_url;
|
|
|
|
|
|
|
|
|
|
Process process = new Process ();
|
|
|
|
|
process.StartInfo.UseShellExecute = false;
|
|
|
|
|
process.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
process.StartInfo.FileName = "git";
|
2010-08-02 20:19:22 +00:00
|
|
|
|
process.StartInfo.WorkingDirectory = LocalPath;
|
2010-07-21 23:17:20 +00:00
|
|
|
|
process.StartInfo.Arguments = "config --get remote.origin.url";
|
|
|
|
|
process.Start ();
|
|
|
|
|
|
|
|
|
|
remote_origin_url = process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
|
|
|
|
|
return remote_origin_url;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-09-04 15:23:20 +00:00
|
|
|
|
// Returns a list of latest commits
|
|
|
|
|
public List <SparkleCommit> GetCommits (int count)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (count < 0)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
List <SparkleCommit> commits = new List <SparkleCommit> ();
|
|
|
|
|
|
|
|
|
|
Process process = new Process () {
|
|
|
|
|
EnableRaisingEvents = true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
process.StartInfo.RedirectStandardOutput = true;
|
|
|
|
|
process.StartInfo.UseShellExecute = false;
|
|
|
|
|
process.StartInfo.WorkingDirectory = LocalPath;
|
2010-09-08 13:23:25 +00:00
|
|
|
|
|
|
|
|
|
// Get the user's timezone
|
|
|
|
|
process.StartInfo.FileName = "date";
|
|
|
|
|
process.StartInfo.Arguments = "+%z";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
process.Start ();
|
|
|
|
|
process.WaitForExit ();
|
|
|
|
|
|
|
|
|
|
string timezone = process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
int unix_timestamp = 0;
|
|
|
|
|
|
|
|
|
|
// Add the timezone difference in hours when in a positive timezone
|
|
|
|
|
if (timezone.StartsWith ("+"))
|
2010-09-08 13:33:27 +00:00
|
|
|
|
unix_timestamp = 3600 * int.Parse (timezone.Substring (1, 2));
|
2010-09-08 13:23:25 +00:00
|
|
|
|
|
|
|
|
|
// Remove the timezone difference in hours when in a negative timezone
|
|
|
|
|
if (timezone.StartsWith ("-"))
|
2010-09-08 13:33:27 +00:00
|
|
|
|
unix_timestamp = -3600 * int.Parse (timezone.Substring (1, 2));
|
2010-09-08 13:23:25 +00:00
|
|
|
|
|
2010-09-04 15:23:20 +00:00
|
|
|
|
process.StartInfo.FileName = "git";
|
2010-09-11 09:52:10 +00:00
|
|
|
|
process.StartInfo.Arguments = "log --format=\"%at\t%an\t%ae\t%H\" -" + count;
|
2010-09-04 15:23:20 +00:00
|
|
|
|
|
|
|
|
|
process.Start ();
|
|
|
|
|
process.WaitForExit ();
|
|
|
|
|
|
|
|
|
|
string output = process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
output = output.TrimStart ("\n".ToCharArray ());
|
|
|
|
|
|
|
|
|
|
string [] lines = Regex.Split (output, "\n");
|
|
|
|
|
|
|
|
|
|
Array.Sort (lines);
|
|
|
|
|
Array.Reverse (lines);
|
|
|
|
|
|
|
|
|
|
foreach (string line in lines) {
|
|
|
|
|
|
|
|
|
|
string [] parts = Regex.Split (line, "\t");
|
|
|
|
|
|
2010-09-08 13:33:27 +00:00
|
|
|
|
int local_timestamp = unix_timestamp + int.Parse (parts [0]);
|
2010-09-11 09:52:10 +00:00
|
|
|
|
string user_name = parts [1];
|
|
|
|
|
string user_email = parts [2];
|
|
|
|
|
string hash = parts [3];
|
2010-09-04 15:23:20 +00:00
|
|
|
|
|
2010-09-08 13:33:27 +00:00
|
|
|
|
DateTime date_time = SparkleHelpers.UnixTimestampToDateTime (local_timestamp);
|
2010-09-04 15:23:20 +00:00
|
|
|
|
|
|
|
|
|
SparkleCommit commit = new SparkleCommit (user_name, user_email, date_time, hash);
|
|
|
|
|
|
|
|
|
|
// Find out what has changed in the commit.
|
|
|
|
|
// --name-status lists affected files with the modification type,
|
|
|
|
|
// -C detects renames
|
|
|
|
|
process.StartInfo.Arguments = "show " + hash + " --name-status -C";
|
|
|
|
|
process.Start ();
|
|
|
|
|
process.WaitForExit ();
|
|
|
|
|
|
|
|
|
|
output = process.StandardOutput.ReadToEnd ().Trim ();
|
|
|
|
|
output = output.TrimStart ("\n".ToCharArray ());
|
|
|
|
|
|
|
|
|
|
string [] file_lines = Regex.Split (output, "\n");
|
|
|
|
|
|
|
|
|
|
foreach (string file_line in file_lines) {
|
|
|
|
|
|
|
|
|
|
string file_path = "";
|
|
|
|
|
|
|
|
|
|
if (file_line.Length > 1)
|
|
|
|
|
file_path = file_line.Substring (2);
|
|
|
|
|
|
|
|
|
|
if (file_line.StartsWith ("M\t"))
|
|
|
|
|
commit.Edited.Add (file_path);
|
|
|
|
|
|
|
|
|
|
if (file_line.StartsWith ("A\t"))
|
|
|
|
|
commit.Added.Add (file_path);
|
|
|
|
|
|
|
|
|
|
if (file_line.StartsWith ("D\t"))
|
|
|
|
|
commit.Deleted.Add (file_path);
|
|
|
|
|
|
|
|
|
|
if (file_line.StartsWith ("R")) {
|
|
|
|
|
|
|
|
|
|
file_path = file_line.Substring (5);
|
|
|
|
|
string [] paths = Regex.Split (file_path, "\t");
|
|
|
|
|
|
|
|
|
|
commit.MovedFrom.Add (paths [0]);
|
|
|
|
|
commit.MovedTo.Add (paths [1]);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
commits.Add (commit);
|
|
|
|
|
|
2010-09-08 13:33:27 +00:00
|
|
|
|
unix_timestamp = 0;
|
|
|
|
|
|
2010-09-04 15:23:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return commits;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
// Creates a pretty commit message based on what has changed
|
2010-06-16 23:16:50 +00:00
|
|
|
|
private string FormatCommitMessage ()
|
2010-06-15 00:08:35 +00:00
|
|
|
|
{
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
Process.StartInfo.Arguments = "status --porcelain";
|
2010-05-31 19:24:42 +00:00
|
|
|
|
Process.Start ();
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
string output = Process.StandardOutput.ReadToEnd ().TrimEnd ();
|
|
|
|
|
string [] lines = Regex.Split (output, "\n");
|
|
|
|
|
|
|
|
|
|
string file_name;
|
|
|
|
|
string file_action;
|
|
|
|
|
string message = null;
|
|
|
|
|
|
|
|
|
|
foreach (string line in lines) {
|
|
|
|
|
|
|
|
|
|
if (line.StartsWith ("A")) {
|
|
|
|
|
|
|
|
|
|
file_action = "added";
|
|
|
|
|
file_name = line.Substring (3);
|
|
|
|
|
message = file_action + " ‘" + file_name + "’";
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (line.StartsWith ("M")) {
|
|
|
|
|
|
|
|
|
|
file_action = "edited";
|
|
|
|
|
file_name = line.Substring (3);
|
|
|
|
|
message = file_action + " ‘" + file_name + "’";
|
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
if (line.StartsWith ("D")) {
|
|
|
|
|
|
|
|
|
|
file_action = "deleted";
|
|
|
|
|
file_name = line.Substring (3);
|
|
|
|
|
message = file_action + " ‘" + file_name + "’";
|
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
if (line.StartsWith ("R")) {
|
|
|
|
|
|
2010-08-29 12:04:44 +00:00
|
|
|
|
file_action = "moved";
|
2010-08-29 10:38:34 +00:00
|
|
|
|
message = file_action + " ‘" + line.Substring (3).Replace (" -> ", "’ to\n‘") + "’";
|
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
if (line.StartsWith ("C")) {
|
|
|
|
|
|
|
|
|
|
file_action = "copied";
|
|
|
|
|
file_name = line.Substring (3);
|
|
|
|
|
|
2010-05-03 00:04:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-29 10:38:34 +00:00
|
|
|
|
if (lines.Length > 1)
|
|
|
|
|
message += " and " + (lines.Length - 1) + " more";
|
|
|
|
|
|
|
|
|
|
return message;
|
2010-05-03 00:04:39 +00:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-24 12:32:05 +00:00
|
|
|
|
}
|