save work
This commit is contained in:
parent
19aca9d238
commit
2168fa2ab9
|
@ -15,7 +15,9 @@ SOURCES = \
|
|||
SparkleListenerIrc.cs \
|
||||
SparkleOptions.cs \
|
||||
SparklePaths.cs \
|
||||
SparkleRepo.cs
|
||||
SparkleRepoBase.cs \
|
||||
SparkleRepoGit.cs
|
||||
|
||||
|
||||
SMARTIRC4NET_FILES_EXPANDED = $(foreach file, $(SMARTIRC4NET_FILES), $(top_builddir)/$(file))
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="SparkleRepo.cs" />
|
||||
<Compile Include="SparkleRepoBase.cs" />
|
||||
<Compile Include="SparkleRepoGit.cs" />
|
||||
<Compile Include="SparkleFetcherBase.cs" />
|
||||
<Compile Include="SparkleFetcherGit.cs" />
|
||||
<Compile Include="Defines.cs" />
|
||||
|
|
479
SparkleLib/SparkleRepoBase.cs
Normal file
479
SparkleLib/SparkleRepoBase.cs
Normal file
|
@ -0,0 +1,479 @@
|
|||
// 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
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics; // remove
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Timers;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
public enum SyncStatus {
|
||||
Idle,
|
||||
SyncUp,
|
||||
SyncDown,
|
||||
Error
|
||||
}
|
||||
|
||||
|
||||
public abstract class SparkleRepoBase {
|
||||
|
||||
public readonly SparkleBackend Backend;
|
||||
public readonly string LocalPath;
|
||||
public readonly string Name;
|
||||
|
||||
protected SyncStatus status;
|
||||
protected bool is_buffering = false;
|
||||
protected bool is_polling = true;
|
||||
protected bool server_online = true;
|
||||
|
||||
private Timer local_timer = new Timer () { Interval = 250 };
|
||||
private Timer remote_timer = new Timer () { Interval = 60000 };
|
||||
private FileSystemWatcher watcher;
|
||||
private SparkleListenerBase listener;
|
||||
private List <double> sizebuffer = new List<double> ();
|
||||
private bool has_changed = false;
|
||||
private Object change_lock = new Object ();
|
||||
|
||||
public string Domain {
|
||||
get {
|
||||
Regex regex = new Regex (@"*://(.+)(/|:)*");
|
||||
Match match = regex.Match (Url);
|
||||
|
||||
if (match.Success)
|
||||
return match.Groups [1].Value;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract string Url { get; }
|
||||
public abstract bool AnyDifferences { get; }
|
||||
public abstract string Identifier { get; }
|
||||
public abstract string CurrentRevision { get; }
|
||||
public abstract bool SyncUp ();
|
||||
public abstract bool SyncDown ();
|
||||
|
||||
public virtual bool CheckForRemoteChanges () // HasRemoteChanges { get; } ?
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual List<SparkleChangeSet> GetChangeSets (int count) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual bool UsesNotificationCenter {
|
||||
get {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public string RemoteName {
|
||||
get {
|
||||
return Path.GetFileNameWithoutExtension (Url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsBuffering {
|
||||
get {
|
||||
return this.is_buffering;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPolling {
|
||||
get {
|
||||
return this.is_polling;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract bool HasUnsyncedChanges { get; set; }
|
||||
|
||||
public bool ServerOnline {
|
||||
get {
|
||||
return this.server_online;
|
||||
}
|
||||
}
|
||||
|
||||
public SyncStatus Status {
|
||||
get {
|
||||
return this.status;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void SyncStatusChangedEventHandler (SyncStatus new_status);
|
||||
public event SyncStatusChangedEventHandler SyncStatusChanged;
|
||||
|
||||
|
||||
public delegate void NewChangeSetEventHandler (SparkleChangeSet change_set, string source_path);
|
||||
public delegate void ConflictResolvedEventHandler ();
|
||||
public delegate void ChangesDetectedEventHandler ();
|
||||
|
||||
public event NewChangeSetEventHandler NewChangeSet;
|
||||
public event ConflictResolvedEventHandler ConflictResolved;
|
||||
public event ChangesDetectedEventHandler ChangesDetected;
|
||||
|
||||
protected void OnConflictResolved ()
|
||||
{
|
||||
if (ConflictResolved != null)
|
||||
ConflictResolved ();
|
||||
}
|
||||
|
||||
// TODO: constructor (path, url, backend)
|
||||
public SparkleRepoBase (string path, SparkleBackend backend)
|
||||
{
|
||||
LocalPath = path;
|
||||
Name = Path.GetFileName (LocalPath);
|
||||
Backend = backend;
|
||||
|
||||
SyncStatusChanged += delegate (SyncStatus status) {
|
||||
this.status = status;
|
||||
};
|
||||
|
||||
if (CurrentRevision == null) {
|
||||
CreateInitialChangeSet ();
|
||||
SyncUpBase ();
|
||||
}
|
||||
|
||||
// Watch the repository's folder
|
||||
this.watcher = new FileSystemWatcher (LocalPath) {
|
||||
IncludeSubdirectories = true,
|
||||
EnableRaisingEvents = true,
|
||||
Filter = "*"
|
||||
};
|
||||
|
||||
this.watcher.Changed += new FileSystemEventHandler (OnFileActivity);
|
||||
this.watcher.Created += new FileSystemEventHandler (OnFileActivity);
|
||||
this.watcher.Deleted += new FileSystemEventHandler (OnFileActivity);
|
||||
this.watcher.Renamed += new RenamedEventHandler (OnFileActivity);
|
||||
|
||||
CreateListener ();
|
||||
|
||||
|
||||
this.local_timer.Elapsed += delegate (object o, ElapsedEventArgs args) {
|
||||
CheckForChanges ();
|
||||
};
|
||||
|
||||
this.remote_timer.Elapsed += delegate {
|
||||
if (this.is_polling) {
|
||||
if (CheckForRemoteChanges ())
|
||||
SyncDownBase ();
|
||||
}
|
||||
|
||||
if (this.is_polling && !this.listener.IsConnected)
|
||||
this.listener.Connect ();
|
||||
|
||||
if (HasUnsyncedChanges)
|
||||
SyncUpBase ();
|
||||
};
|
||||
|
||||
this.remote_timer.Start ();
|
||||
this.local_timer.Start ();
|
||||
|
||||
// Sync up everything that changed
|
||||
// since we've been off
|
||||
DisableWatching ();
|
||||
if (AnyDifferences) {
|
||||
SyncUpBase ();
|
||||
while (HasUnsyncedChanges)
|
||||
SyncUpBase ();
|
||||
}
|
||||
EnableWatching ();
|
||||
}
|
||||
|
||||
|
||||
private void CreateListener ()
|
||||
{
|
||||
NotificationServerType server_type;
|
||||
if (UsesNotificationCenter)
|
||||
server_type = NotificationServerType.Central;
|
||||
else
|
||||
server_type = NotificationServerType.Own;
|
||||
this.listener = new SparkleListenerIrc (Domain, Identifier, server_type);////////////
|
||||
|
||||
// Stop polling when the connection to the irc channel is succesful
|
||||
this.listener.Connected += delegate {
|
||||
this.is_polling = false;
|
||||
|
||||
// Check for changes manually one more time
|
||||
CheckForRemoteChanges ();
|
||||
|
||||
// Push changes that were made since the last disconnect
|
||||
if (HasUnsyncedChanges)
|
||||
SyncUpBase ();
|
||||
};
|
||||
|
||||
// Start polling when the connection to the irc channel is lost
|
||||
this.listener.Disconnected += delegate {
|
||||
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Falling back to polling");
|
||||
this.is_polling = true;
|
||||
};
|
||||
|
||||
// Fetch changes when there is a message in the irc channel
|
||||
this.listener.RemoteChange += delegate (string change_id) {
|
||||
if (!change_id.Equals (CurrentRevision) && change_id.Length == 40) {
|
||||
if (Status != SyncStatus.SyncUp &&
|
||||
Status != SyncStatus.SyncDown &&
|
||||
!this.is_buffering) {
|
||||
|
||||
while (this.listener.ChangesQueue > 0) {
|
||||
SyncDownBase ();
|
||||
this.listener.DecrementChangesQueue ();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Start listening
|
||||
this.listener.Connect ();
|
||||
}
|
||||
|
||||
|
||||
private void CheckForChanges ()
|
||||
{
|
||||
lock (this.change_lock) {
|
||||
if (this.has_changed) {
|
||||
if ( this.sizebuffer.Count >= 4)
|
||||
this.sizebuffer.RemoveAt (0);
|
||||
|
||||
DirectoryInfo dir_info = new DirectoryInfo (LocalPath);
|
||||
this.sizebuffer.Add (CalculateFolderSize (dir_info));
|
||||
|
||||
if ( this.sizebuffer [0].Equals (this.sizebuffer [1]) &&
|
||||
this.sizebuffer [1].Equals (this.sizebuffer [2]) &&
|
||||
this.sizebuffer [2].Equals (this.sizebuffer [3])) {
|
||||
|
||||
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes have settled.");
|
||||
this.is_buffering = false;
|
||||
this.has_changed = false;
|
||||
|
||||
DisableWatching ();
|
||||
while (AnyDifferences)
|
||||
SyncUpBase ();//TODO look at algorithm
|
||||
EnableWatching ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Starts a timer when something changes
|
||||
private void OnFileActivity (object o, FileSystemEventArgs fse_args)
|
||||
{
|
||||
if (fse_args.Name.StartsWith (".git/"))
|
||||
return;
|
||||
|
||||
WatcherChangeTypes wct = fse_args.ChangeType;
|
||||
|
||||
if (AnyDifferences) {
|
||||
this.is_buffering = true;
|
||||
|
||||
// Only fire the event if the timer has been stopped.
|
||||
// This prevents multiple events from being raised whilst "buffering".
|
||||
if (!this.has_changed) {
|
||||
if (ChangesDetected != null)
|
||||
ChangesDetected ();
|
||||
}
|
||||
|
||||
SparkleHelpers.DebugInfo ("Event", "[" + Name + "] " + wct.ToString () + " '" + fse_args.Name + "'");
|
||||
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes found, checking if settled.");
|
||||
|
||||
this.remote_timer.Stop ();
|
||||
|
||||
lock (this.change_lock) {
|
||||
this.has_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SyncUpBase ()
|
||||
{
|
||||
try {
|
||||
this.local_timer.Stop ();
|
||||
this.remote_timer.Stop ();
|
||||
|
||||
SparkleHelpers.DebugInfo ("SyncUp", "[" + Name + "] Initiated");
|
||||
|
||||
//if (AnyDifferences) {
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.SyncUp);
|
||||
|
||||
if (SyncUp ()) {
|
||||
SparkleHelpers.DebugInfo ("SyncUp", "[" + Name + "] Done");
|
||||
|
||||
HasUnsyncedChanges = false;
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Idle);
|
||||
|
||||
this.listener.Announce (CurrentRevision);
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("SyncUp", "[" + Name + "] Error");
|
||||
|
||||
HasUnsyncedChanges = true;
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Error);
|
||||
|
||||
SyncDownBase ();
|
||||
}
|
||||
//}
|
||||
} finally {
|
||||
this.remote_timer.Start ();
|
||||
this.local_timer.Start ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SyncDownBase ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("SyncDown", "[" + Name + "] Initiated");
|
||||
this.remote_timer.Stop ();
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.SyncDown);
|
||||
|
||||
if (SyncDown ()) {
|
||||
SparkleHelpers.DebugInfo ("SyncDown", "[" + Name + "] Done");
|
||||
this.server_online = true;
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Idle);
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("SyncDown", "[" + Name + "] Error");
|
||||
this.server_online = false;
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Error);
|
||||
}
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Idle);
|
||||
|
||||
this.remote_timer.Start ();
|
||||
|
||||
if (NewChangeSet != null)
|
||||
NewChangeSet (GetChangeSets (1) [0], LocalPath);
|
||||
}
|
||||
|
||||
|
||||
public void DisableWatching ()
|
||||
{
|
||||
this.watcher.EnableRaisingEvents = false;
|
||||
}
|
||||
|
||||
|
||||
public void EnableWatching ()
|
||||
{
|
||||
this.watcher.EnableRaisingEvents = true;
|
||||
}
|
||||
|
||||
|
||||
private string GetUserName () // TODO
|
||||
{
|
||||
SparkleGit git = new SparkleGit (LocalPath, "config --get user.name");
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
string output = git.StandardOutput.ReadToEnd ();
|
||||
string user_name = output.Trim ();
|
||||
|
||||
return user_name;
|
||||
}
|
||||
|
||||
|
||||
private string GetUserEmail ()
|
||||
{
|
||||
SparkleGit git = new SparkleGit (LocalPath, "config --get user.email");
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
string output = git.StandardOutput.ReadToEnd ();
|
||||
string user_email = output.Trim ();
|
||||
|
||||
return user_email;
|
||||
}
|
||||
|
||||
|
||||
// Recursively gets a folder's size in bytes
|
||||
private double CalculateFolderSize (DirectoryInfo parent)
|
||||
{
|
||||
if (!System.IO.Directory.Exists (parent.ToString ()))
|
||||
return 0;
|
||||
|
||||
double size = 0;
|
||||
|
||||
// Ignore the temporary 'rebase-apply' directory. This prevents potential
|
||||
// crashes when files are being queried whilst the files have already been deleted.
|
||||
if (parent.Name.Equals ("rebase-apply"))
|
||||
return 0;
|
||||
|
||||
foreach (FileInfo file in parent.GetFiles()) {
|
||||
if (!file.Exists)
|
||||
return 0;
|
||||
|
||||
size += file.Length;
|
||||
}
|
||||
|
||||
foreach (DirectoryInfo directory in parent.GetDirectories())
|
||||
size += CalculateFolderSize (directory);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
// Create an initial change set when the
|
||||
// user has fetched an empty remote folder
|
||||
public virtual void CreateInitialChangeSet ()
|
||||
{
|
||||
string file_path = Path.Combine (LocalPath, "SparkleShare.txt");
|
||||
TextWriter writer = new StreamWriter (file_path);
|
||||
writer.WriteLine (":)");
|
||||
writer.Close ();
|
||||
}
|
||||
|
||||
|
||||
public string GetConfigItem (string name)
|
||||
{
|
||||
if (String.Compare (name, "sparkleshare.user.name", true) == 0)
|
||||
return GetUserName ();
|
||||
else if (String.Compare (name, "sparkleshare.user.email", true) == 0)
|
||||
return GetUserEmail ();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static bool IsRepo (string path)
|
||||
{
|
||||
return System.IO.Directory.Exists (Path.Combine (path, ".git"));
|
||||
}
|
||||
|
||||
|
||||
// Disposes all resourses of this object
|
||||
public void Dispose ()
|
||||
{
|
||||
this.remote_timer.Dispose ();
|
||||
this.local_timer.Dispose ();
|
||||
this.listener.Dispose ();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,91 +20,152 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Timers;
|
||||
|
||||
using Meebey.SmartIrc4net;
|
||||
using Mono.Unix;
|
||||
|
||||
namespace SparkleLib {
|
||||
|
||||
public enum SyncStatus {
|
||||
Idle,
|
||||
SyncUp,
|
||||
SyncDown,
|
||||
Error
|
||||
}
|
||||
public class SparkleRepoGit : SparkleRepoBase {
|
||||
|
||||
public SparkleRepoGit (string path, SparkleBackend backend) :
|
||||
base (path, backend) { }
|
||||
|
||||
|
||||
public class SparkleRepo {
|
||||
|
||||
public readonly SparkleBackend Backend;
|
||||
public readonly string LocalPath;
|
||||
public readonly string Name;
|
||||
|
||||
protected SyncStatus status;
|
||||
protected string revision;
|
||||
protected bool is_buffering = false;
|
||||
protected bool is_polling = true;
|
||||
protected bool server_online = true;
|
||||
|
||||
private Timer remote_timer;
|
||||
private Timer local_timer;
|
||||
private FileSystemWatcher watcher;
|
||||
private SparkleListenerBase listener;
|
||||
private List <double> sizebuffer;
|
||||
private bool has_changed = false;
|
||||
private Object change_lock = new Object ();
|
||||
|
||||
|
||||
// TODO: make this a regexp
|
||||
public string Url {
|
||||
public override string Url {
|
||||
get {
|
||||
SparkleGit git = new SparkleGit (LocalPath, "config --get remote.origin.url");
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
|
||||
string output = git.StandardOutput.ReadToEnd ();
|
||||
return output.TrimEnd ();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make this a regexp
|
||||
public string Domain {
|
||||
get {
|
||||
string domain = Url.Substring (Url.IndexOf ("@") + 1);
|
||||
|
||||
if (domain.Contains (":"))
|
||||
return domain = domain.Substring (0, domain.IndexOf (":"));
|
||||
else
|
||||
return domain = domain.Substring (0, domain.IndexOf ("/"));
|
||||
public override string Identifier {
|
||||
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
|
||||
SparkleGit git = new SparkleGit (LocalPath, "rev-list --reverse HEAD");
|
||||
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 ();
|
||||
|
||||
return output.Substring (0, 40);
|
||||
}
|
||||
}
|
||||
|
||||
public string RemoteName {
|
||||
|
||||
public override string CurrentRevision {
|
||||
get {
|
||||
return Path.GetFileNameWithoutExtension (Url);
|
||||
|
||||
// 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) {
|
||||
string output = git.StandardOutput.ReadToEnd ();
|
||||
return output.TrimEnd ();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Revision {
|
||||
get {
|
||||
return this.revision;
|
||||
|
||||
public override bool CheckForRemoteChanges ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Checking for remote changes...");
|
||||
SparkleGit git = new SparkleGit (LocalPath, "ls-remote origin master");
|
||||
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
if (git.ExitCode != 0)
|
||||
return false;
|
||||
|
||||
string remote_revision = git.StandardOutput.ReadToEnd ().TrimEnd ();
|
||||
|
||||
if (!remote_revision.StartsWith (CurrentRevision)) {
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Remote changes found. (" + remote_revision + ")");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsBuffering {
|
||||
get {
|
||||
return this.is_buffering;
|
||||
|
||||
public override bool SyncUp ()
|
||||
{
|
||||
Add ();
|
||||
|
||||
string message = FormatCommitMessage ();
|
||||
Commit (message);
|
||||
|
||||
SparkleGit git = new SparkleGit (LocalPath, "push origin master");
|
||||
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
if (git.ExitCode == 0) {
|
||||
return true;
|
||||
//FetchRebaseAndPush ();TODO
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsPolling {
|
||||
get {
|
||||
return this.is_polling;
|
||||
|
||||
public override bool SyncDown ()
|
||||
{
|
||||
SparkleGit git = new SparkleGit (LocalPath, "fetch -v origin master");
|
||||
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
if (git.ExitCode == 0) {
|
||||
Rebase ();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasUnsyncedChanges {
|
||||
|
||||
public override bool AnyDifferences {
|
||||
get {
|
||||
SparkleGit git = new SparkleGit (LocalPath, "status --porcelain");
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
string output = git.StandardOutput.ReadToEnd ().TrimEnd ();
|
||||
string [] lines = output.Split ("\n".ToCharArray ());
|
||||
|
||||
foreach (string line in lines) {
|
||||
if (line.Length > 1 && !line [1].Equals (" "))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public override bool HasUnsyncedChanges {
|
||||
get {
|
||||
string unsynced_file_path = SparkleHelpers.CombineMore (LocalPath,
|
||||
".git", "has_unsynced_changes");
|
||||
|
@ -125,324 +186,10 @@ namespace SparkleLib {
|
|||
}
|
||||
}
|
||||
|
||||
public bool ServerOnline {
|
||||
get {
|
||||
return this.server_online;
|
||||
}
|
||||
}
|
||||
|
||||
public SyncStatus Status {
|
||||
get {
|
||||
return this.status;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void SyncStatusChangedEventHandler (SyncStatus new_status);
|
||||
public event SyncStatusChangedEventHandler SyncStatusChanged;
|
||||
|
||||
|
||||
public delegate void NewChangeSetEventHandler (SparkleChangeSet change_set, string source_path);
|
||||
public delegate void ConflictResolvedEventHandler ();
|
||||
public delegate void ChangesDetectedEventHandler ();
|
||||
|
||||
public event NewChangeSetEventHandler NewChangeSet;
|
||||
public event ConflictResolvedEventHandler ConflictResolved;
|
||||
public event ChangesDetectedEventHandler ChangesDetected;
|
||||
|
||||
public SparkleRepo (string path, SparkleBackend backend)
|
||||
{
|
||||
LocalPath = path;
|
||||
Name = Path.GetFileName (LocalPath);
|
||||
Backend = backend;
|
||||
|
||||
SyncStatusChanged += delegate (SyncStatus status) {
|
||||
this.status = status;
|
||||
};
|
||||
|
||||
if (IsEmpty)
|
||||
this.revision = null;
|
||||
else
|
||||
this.revision = GetRevision ();
|
||||
|
||||
if (this.revision == null)
|
||||
CreateInitialChangeSet ();
|
||||
|
||||
// Watch the repository's folder
|
||||
this.watcher = new FileSystemWatcher (LocalPath) {
|
||||
IncludeSubdirectories = true,
|
||||
EnableRaisingEvents = true,
|
||||
Filter = "*"
|
||||
};
|
||||
|
||||
this.watcher.Changed += new FileSystemEventHandler (OnFileActivity);
|
||||
this.watcher.Created += new FileSystemEventHandler (OnFileActivity);
|
||||
this.watcher.Deleted += new FileSystemEventHandler (OnFileActivity);
|
||||
this.watcher.Renamed += new RenamedEventHandler (OnFileActivity);
|
||||
|
||||
NotificationServerType server_type;
|
||||
if (UsesNotificationCenter)
|
||||
server_type = NotificationServerType.Central;
|
||||
else
|
||||
server_type = NotificationServerType.Own;
|
||||
|
||||
this.listener = new SparkleListenerIrc (Domain, Identifier, server_type);
|
||||
|
||||
// ...fetch remote changes every 60 seconds if that fails
|
||||
this.remote_timer = new Timer () {
|
||||
Interval = 60000
|
||||
};
|
||||
|
||||
this.remote_timer.Elapsed += delegate {
|
||||
if (this.is_polling) {
|
||||
CheckForRemoteChanges ();
|
||||
|
||||
if (!this.listener.IsConnected)
|
||||
this.listener.Connect ();
|
||||
}
|
||||
|
||||
if (HasUnsyncedChanges)
|
||||
FetchRebaseAndPush ();
|
||||
};
|
||||
|
||||
// Stop polling when the connection to the irc channel is succesful
|
||||
this.listener.Connected += delegate {
|
||||
this.is_polling = false;
|
||||
|
||||
// Check for changes manually one more time
|
||||
CheckForRemoteChanges ();
|
||||
|
||||
// Push changes that were made since the last disconnect
|
||||
if (HasUnsyncedChanges)
|
||||
Push ();
|
||||
};
|
||||
|
||||
// Start polling when the connection to the irc channel is lost
|
||||
this.listener.Disconnected += delegate {
|
||||
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Falling back to polling");
|
||||
this.is_polling = true;
|
||||
};
|
||||
|
||||
// Fetch changes when there is a message in the irc channel
|
||||
this.listener.RemoteChange += delegate (string change_id) {
|
||||
if (!change_id.Equals (this.revision) && change_id.Length == 40) {
|
||||
if (Status != SyncStatus.SyncUp &&
|
||||
Status != SyncStatus.SyncDown &&
|
||||
!this.is_buffering) {
|
||||
|
||||
while (this.listener.ChangesQueue > 0) {
|
||||
SyncDown ();
|
||||
this.listener.DecrementChangesQueue ();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Start listening
|
||||
this.listener.Connect ();
|
||||
|
||||
this.sizebuffer = new List <double> ();
|
||||
|
||||
// Keep a timer that checks if there are changes and
|
||||
// whether they have settled
|
||||
this.local_timer = new Timer () {
|
||||
Interval = 250
|
||||
};
|
||||
|
||||
this.local_timer.Elapsed += delegate (object o, ElapsedEventArgs args) {
|
||||
CheckForChanges ();
|
||||
};
|
||||
|
||||
this.remote_timer.Start ();
|
||||
this.local_timer.Start ();
|
||||
|
||||
// Add everything that changed
|
||||
// since SparkleShare was stopped
|
||||
AddCommitAndPush ();
|
||||
|
||||
if (this.revision == null)
|
||||
this.revision = GetRevision ();
|
||||
}
|
||||
|
||||
|
||||
public string Identifier {
|
||||
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
|
||||
SparkleGit git = new SparkleGit (LocalPath, "rev-list --reverse HEAD");
|
||||
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 ();
|
||||
|
||||
return output.Substring (0, 40);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CheckForRemoteChanges ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Checking for remote changes...");
|
||||
SparkleGit git = new SparkleGit (LocalPath, "ls-remote origin master");
|
||||
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
if (git.ExitCode != 0)
|
||||
return;
|
||||
|
||||
string remote_revision = git.StandardOutput.ReadToEnd ().TrimEnd ();
|
||||
|
||||
if (!remote_revision.StartsWith (this.revision)) {
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Remote changes found. (" + remote_revision + ")");
|
||||
SyncDown ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CheckForChanges ()
|
||||
{
|
||||
lock (this.change_lock) {
|
||||
if (this.has_changed) {
|
||||
if ( this.sizebuffer.Count >= 4)
|
||||
this.sizebuffer.RemoveAt (0);
|
||||
|
||||
DirectoryInfo dir_info = new DirectoryInfo (LocalPath);
|
||||
this.sizebuffer.Add (CalculateFolderSize (dir_info));
|
||||
|
||||
if ( this.sizebuffer [0].Equals (this.sizebuffer [1]) &&
|
||||
this.sizebuffer [1].Equals (this.sizebuffer [2]) &&
|
||||
this.sizebuffer [2].Equals (this.sizebuffer [3])) {
|
||||
|
||||
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes have settled.");
|
||||
this.is_buffering = false;
|
||||
this.has_changed = false;
|
||||
|
||||
while (AnyDifferences) {
|
||||
this.watcher.EnableRaisingEvents = false;
|
||||
AddCommitAndPush ();
|
||||
this.watcher.EnableRaisingEvents = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Starts a timer when something changes
|
||||
private void OnFileActivity (object o, FileSystemEventArgs fse_args)
|
||||
{
|
||||
if (fse_args.Name.StartsWith (".git/"))
|
||||
return;
|
||||
|
||||
WatcherChangeTypes wct = fse_args.ChangeType;
|
||||
|
||||
if (AnyDifferences) {
|
||||
this.is_buffering = true;
|
||||
|
||||
// Only fire the event if the timer has been stopped.
|
||||
// This prevents multiple events from being raised whilst "buffering".
|
||||
if (!this.has_changed) {
|
||||
if (ChangesDetected != null)
|
||||
ChangesDetected ();
|
||||
}
|
||||
|
||||
SparkleHelpers.DebugInfo ("Event", "[" + Name + "] " + wct.ToString () + " '" + fse_args.Name + "'");
|
||||
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes found, checking if settled.");
|
||||
|
||||
this.remote_timer.Stop ();
|
||||
|
||||
lock (this.change_lock) {
|
||||
this.has_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// When there are changes we generally want to Add, Commit and Push,
|
||||
// so this method does them all with appropriate timers, etc. switched off
|
||||
public void AddCommitAndPush ()
|
||||
{
|
||||
try {
|
||||
this.local_timer.Stop ();
|
||||
this.remote_timer.Stop ();
|
||||
|
||||
if (AnyDifferences) {
|
||||
Add ();
|
||||
|
||||
string message = FormatCommitMessage ();
|
||||
Commit (message);
|
||||
|
||||
Push ();
|
||||
} else {
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Idle); // TODO: in checklocalforchanges
|
||||
}
|
||||
} finally {
|
||||
this.remote_timer.Start ();
|
||||
this.local_timer.Start ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void FetchRebaseAndPush ()
|
||||
{
|
||||
CheckForRemoteChanges ();
|
||||
Push ();
|
||||
}
|
||||
|
||||
|
||||
private bool AnyDifferences {
|
||||
get {
|
||||
SparkleGit git = new SparkleGit (LocalPath, "status --porcelain");
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
string output = git.StandardOutput.ReadToEnd ().TrimEnd ();
|
||||
string [] lines = output.Split ("\n".ToCharArray ());
|
||||
|
||||
foreach (string line in lines) {
|
||||
if (line.Length > 1 && !line [1].Equals (" "))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool IsEmpty {
|
||||
get {
|
||||
SparkleGit git = new SparkleGit (LocalPath, "log -1");
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
return (git.ExitCode != 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string GetRevision ()
|
||||
{
|
||||
// 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 ();
|
||||
|
||||
string output = git.StandardOutput.ReadToEnd ();
|
||||
string revision = output.Trim ();
|
||||
|
||||
return revision;
|
||||
}
|
||||
|
||||
|
||||
// Stages the made changes
|
||||
|
@ -477,59 +224,15 @@ namespace SparkleLib {
|
|||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
this.revision = GetRevision ();
|
||||
SparkleHelpers.DebugInfo ("Commit", "[" + Name + "] " + message + " (" + this.revision + ")");
|
||||
SparkleHelpers.DebugInfo ("Commit", "[" + Name + "] " + message);
|
||||
|
||||
// Collect garbage pseudo-randomly
|
||||
if (DateTime.Now.Second % 10 == 0)
|
||||
CollectGarbage ();
|
||||
}
|
||||
|
||||
public virtual void SyncDownBase ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Sync", "[" + Name + "] Initiated");
|
||||
this.remote_timer.Stop ();
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.SyncDown);
|
||||
|
||||
if (SyncDown ()) {
|
||||
SparkleHelpers.DebugInfo ("Sync", "[" + Name + "] Done");
|
||||
this.server_online = true;
|
||||
this.revision = GetRevision ();
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Idle);
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("Sync", "[" + Name + "] Error");
|
||||
this.server_online = false;
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Error);
|
||||
}
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Idle);
|
||||
|
||||
this.remote_timer.Start ();
|
||||
}
|
||||
|
||||
|
||||
// Fetches changes from the remote repository
|
||||
public bool SyncDown ()
|
||||
{
|
||||
SparkleGit git = new SparkleGit (LocalPath, "fetch -v origin master");
|
||||
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
if (git.ExitCode == 0) {
|
||||
Rebase ();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Merges the fetched changes
|
||||
|
@ -539,7 +242,7 @@ namespace SparkleLib {
|
|||
|
||||
if (AnyDifferences) {
|
||||
Add ();
|
||||
|
||||
|
||||
string commit_message = FormatCommitMessage ();
|
||||
Commit (commit_message);
|
||||
}
|
||||
|
@ -559,21 +262,17 @@ namespace SparkleLib {
|
|||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Conflict resolved.");
|
||||
EnableWatching ();
|
||||
|
||||
if (ConflictResolved != null)
|
||||
ConflictResolved ();
|
||||
OnConflictResolved ();
|
||||
|
||||
Push ();
|
||||
//TODO Push ();
|
||||
}
|
||||
|
||||
this.revision = GetRevision ();
|
||||
|
||||
if (NewChangeSet != null)
|
||||
NewChangeSet (GetChangeSets (1) [0], LocalPath);
|
||||
|
||||
EnableWatching ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void ResolveConflict ()
|
||||
{
|
||||
// This is al list of conflict status codes that Git uses, their
|
||||
|
@ -669,159 +368,19 @@ namespace SparkleLib {
|
|||
}
|
||||
|
||||
|
||||
// Pushes the changes to the remote repo
|
||||
public void Push ()
|
||||
{
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Pushing changes");
|
||||
SparkleGit git = new SparkleGit (LocalPath, "push origin master");
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.SyncUp);
|
||||
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
if (git.ExitCode != 0) {
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Changes not pushed");
|
||||
|
||||
HasUnsyncedChanges = true;
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Error);
|
||||
|
||||
FetchRebaseAndPush ();
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Changes pushed");
|
||||
|
||||
HasUnsyncedChanges = false;
|
||||
|
||||
if (SyncStatusChanged != null)
|
||||
SyncStatusChanged (SyncStatus.Idle);
|
||||
|
||||
this.listener.Announce (this.revision);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void DisableWatching ()
|
||||
{
|
||||
this.watcher.EnableRaisingEvents = false;
|
||||
}
|
||||
|
||||
|
||||
public void EnableWatching ()
|
||||
{
|
||||
this.watcher.EnableRaisingEvents = true;
|
||||
}
|
||||
|
||||
|
||||
// Gets the repository's description
|
||||
private 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;
|
||||
}
|
||||
|
||||
|
||||
private string GetUserName ()
|
||||
{
|
||||
SparkleGit git = new SparkleGit (LocalPath, "config --get user.name");
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
string output = git.StandardOutput.ReadToEnd ();
|
||||
string user_name = output.Trim ();
|
||||
|
||||
return user_name;
|
||||
}
|
||||
|
||||
|
||||
private string GetUserEmail ()
|
||||
{
|
||||
SparkleGit git = new SparkleGit (LocalPath, "config --get user.email");
|
||||
git.Start ();
|
||||
git.WaitForExit ();
|
||||
|
||||
string output = git.StandardOutput.ReadToEnd ();
|
||||
string user_email = output.Trim ();
|
||||
|
||||
return user_email;
|
||||
}
|
||||
|
||||
|
||||
// Recursively gets a folder's size in bytes
|
||||
private double CalculateFolderSize (DirectoryInfo parent)
|
||||
{
|
||||
if (!System.IO.Directory.Exists (parent.ToString ()))
|
||||
return 0;
|
||||
|
||||
double size = 0;
|
||||
|
||||
// Ignore the temporary 'rebase-apply' directory. This prevents potential
|
||||
// crashes when files are being queried whilst the files have already been deleted.
|
||||
if (parent.Name.Equals ("rebase-apply"))
|
||||
return 0;
|
||||
|
||||
foreach (FileInfo file in parent.GetFiles()) {
|
||||
if (!file.Exists)
|
||||
return 0;
|
||||
|
||||
size += file.Length;
|
||||
}
|
||||
|
||||
foreach (DirectoryInfo directory in parent.GetDirectories())
|
||||
size += CalculateFolderSize (directory);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
// Create an initial change set when the
|
||||
// user has fetched an empty remote folder
|
||||
protected virtual void CreateInitialChangeSet ()
|
||||
{
|
||||
string file_path = Path.Combine (LocalPath, "SparkleShare.txt");
|
||||
TextWriter writer = new StreamWriter (file_path);
|
||||
writer.WriteLine (":)");
|
||||
writer.Close ();
|
||||
}
|
||||
|
||||
|
||||
public string GetConfigItem (string name)
|
||||
{
|
||||
if (String.Compare (name, "sparkleshare.user.name", true) == 0)
|
||||
return GetUserName ();
|
||||
else if (String.Compare (name, "sparkleshare.user.email", true) == 0)
|
||||
return GetUserEmail ();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Returns a list of the latest change sets
|
||||
// TODO: Method needs to be made a lot faster
|
||||
public virtual List <SparkleChangeSet> GetChangeSets (int count)
|
||||
public override List <SparkleChangeSet> GetChangeSets (int count)
|
||||
{
|
||||
if (count < 1)
|
||||
count = 30;
|
||||
|
||||
|
||||
List <SparkleChangeSet> change_sets = new List <SparkleChangeSet> ();
|
||||
|
||||
SparkleGit git_log = new SparkleGit (LocalPath, "log -" + count + " --raw -M --date=iso");
|
||||
Console.OutputEncoding = System.Text.Encoding.Unicode;
|
||||
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 ();
|
||||
|
@ -836,14 +395,14 @@ namespace SparkleLib {
|
|||
if (line.StartsWith ("commit") && j > 0) {
|
||||
entries.Add (entry);
|
||||
entry = "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
entry += line + "\n";
|
||||
j++;
|
||||
|
||||
|
||||
last_entry = entry;
|
||||
}
|
||||
|
||||
|
||||
entries.Add (last_entry);
|
||||
|
||||
Regex merge_regex = new Regex (@"commit ([a-z0-9]{40})\n" +
|
||||
|
@ -863,19 +422,19 @@ namespace SparkleLib {
|
|||
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.Revision = match.Groups [1].Value;
|
||||
change_set.UserName = match.Groups [2].Value;
|
||||
change_set.UserEmail = match.Groups [3].Value;
|
||||
|
@ -885,16 +444,16 @@ namespace SparkleLib {
|
|||
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 [] 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 (change_type.Equals ("A")) {
|
||||
change_set.Added.Add (file_path);
|
||||
} else if (change_type.Equals ("M")) {
|
||||
|
@ -911,7 +470,7 @@ namespace SparkleLib {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
change_sets.Add (change_set);
|
||||
}
|
||||
}
|
||||
|
@ -987,13 +546,22 @@ namespace SparkleLib {
|
|||
}
|
||||
|
||||
|
||||
public static bool IsRepo (string path)
|
||||
public override void CreateInitialChangeSet ()
|
||||
{
|
||||
base.CreateInitialChangeSet ();
|
||||
Add ();
|
||||
|
||||
string message = FormatCommitMessage ();
|
||||
Commit (message);
|
||||
}
|
||||
|
||||
new public static bool IsRepo (string path)
|
||||
{
|
||||
return System.IO.Directory.Exists (Path.Combine (path, ".git"));
|
||||
}
|
||||
|
||||
|
||||
public bool UsesNotificationCenter
|
||||
public override bool UsesNotificationCenter
|
||||
{
|
||||
get {
|
||||
string file_path = SparkleHelpers.CombineMore (LocalPath, ".git", "disable_notification_center");
|
||||
|
@ -1002,12 +570,5 @@ namespace SparkleLib {
|
|||
}
|
||||
|
||||
|
||||
// Disposes all resourses of this object
|
||||
public void Dispose ()
|
||||
{
|
||||
this.remote_timer.Dispose ();
|
||||
this.local_timer.Dispose ();
|
||||
this.listener.Dispose ();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ namespace SparkleShare {
|
|||
|
||||
public abstract class SparkleController {
|
||||
|
||||
public List <SparkleRepo> Repositories;
|
||||
public List <SparkleRepoBase> Repositories;
|
||||
public string FolderSize;
|
||||
public bool FirstRun;
|
||||
public readonly string SparklePath;
|
||||
|
@ -162,7 +162,7 @@ namespace SparkleShare {
|
|||
// FIXME: this is broken :\
|
||||
if (OnInvitation != null)
|
||||
OnInvitation (server, folder, token);
|
||||
} else if (SparkleRepo.IsRepo (args.FullPath)) {
|
||||
} else if (SparkleRepoBase.IsRepo (args.FullPath)) {
|
||||
AddRepository (args.FullPath);
|
||||
|
||||
if (FolderListChanged != null)
|
||||
|
@ -240,7 +240,7 @@ namespace SparkleShare {
|
|||
get {
|
||||
List <string> folders = new List <string> ();
|
||||
|
||||
foreach (SparkleRepo repo in Repositories)
|
||||
foreach (SparkleRepoBase repo in Repositories)
|
||||
folders.Add (repo.LocalPath);
|
||||
|
||||
return folders;
|
||||
|
@ -253,7 +253,7 @@ namespace SparkleShare {
|
|||
string path = Path.Combine (SparklePaths.SparklePath, name);
|
||||
int log_size = 30;
|
||||
|
||||
foreach (SparkleRepo repo in Repositories) {
|
||||
foreach (SparkleRepoBase repo in Repositories) {
|
||||
if (repo.LocalPath.Equals (path))
|
||||
return repo.GetChangeSets (log_size);
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ namespace SparkleShare {
|
|||
// Fires events for the current syncing state
|
||||
private void UpdateState ()
|
||||
{
|
||||
foreach (SparkleRepo repo in Repositories) {
|
||||
foreach (SparkleRepoBase repo in Repositories) {
|
||||
if (repo.Status == SyncStatus.SyncDown ||
|
||||
repo.Status == SyncStatus.SyncUp ||
|
||||
repo.IsBuffering) {
|
||||
|
@ -512,10 +512,11 @@ namespace SparkleShare {
|
|||
// and use GitBackend.IsValidFolder (string path);
|
||||
|
||||
// Check if the folder is a Git repository TODO: remove later
|
||||
if (!SparkleRepo.IsRepo (folder_path))
|
||||
if (!SparkleRepoBase.IsRepo (folder_path))
|
||||
return;
|
||||
|
||||
SparkleRepo repo = new SparkleRepo (folder_path, SparkleBackend.DefaultBackend);
|
||||
//TODO
|
||||
SparkleRepoBase repo = new SparkleRepoGit (folder_path, SparkleBackend.DefaultBackend);
|
||||
|
||||
repo.NewChangeSet += delegate (SparkleChangeSet change_set, string repository_path) {
|
||||
string message = FormatMessage (change_set);
|
||||
|
@ -554,7 +555,7 @@ namespace SparkleShare {
|
|||
string folder_name = Path.GetFileName (folder_path);
|
||||
|
||||
for (int i = 0; i < Repositories.Count; i++) {
|
||||
SparkleRepo repo = Repositories [i];
|
||||
SparkleRepoBase repo = Repositories [i];
|
||||
|
||||
if (repo.Name.Equals (folder_name)) {
|
||||
Repositories.Remove (repo);
|
||||
|
@ -570,7 +571,7 @@ namespace SparkleShare {
|
|||
// folders in the SparkleShare folder
|
||||
private void PopulateRepositories ()
|
||||
{
|
||||
Repositories = new List <SparkleRepo> ();
|
||||
Repositories = new List <SparkleRepoBase> ();
|
||||
|
||||
foreach (string folder_path in Directory.GetDirectories (SparklePaths.SparklePath))
|
||||
AddRepository (folder_path);
|
||||
|
@ -1056,7 +1057,7 @@ namespace SparkleShare {
|
|||
// quits if safe
|
||||
public void TryQuit ()
|
||||
{
|
||||
foreach (SparkleRepo repo in Repositories) {
|
||||
foreach (SparkleRepoBase repo in Repositories) {
|
||||
if (repo.Status == SyncStatus.SyncUp ||
|
||||
repo.Status == SyncStatus.SyncDown ||
|
||||
repo.IsBuffering) {
|
||||
|
@ -1074,7 +1075,7 @@ namespace SparkleShare {
|
|||
|
||||
public void Quit ()
|
||||
{
|
||||
foreach (SparkleRepo repo in Repositories)
|
||||
foreach (SparkleRepoBase repo in Repositories)
|
||||
repo.Dispose ();
|
||||
|
||||
Environment.Exit (0);
|
||||
|
|
Loading…
Reference in a new issue