Merge branch 'enhancements' of https://github.com/travisghansen/SparkleShare into thansen
Conflicts: SparkleLib/SparkleListenerBase.cs SparkleLib/SparkleRepoBase.cs
This commit is contained in:
commit
a785c78522
|
@ -16,8 +16,10 @@
|
||||||
|
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace SparkleLib {
|
namespace SparkleLib {
|
||||||
|
|
||||||
|
@ -80,7 +82,7 @@ namespace SparkleLib {
|
||||||
listeners.Add (new SparkleListenerTcp (announce_uri, folder_identifier));
|
listeners.Add (new SparkleListenerTcp (announce_uri, folder_identifier));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("ListenerFactory", "Issued new listener for " + announce_uri);
|
SparkleHelpers.DebugInfo ("ListenerFactory", "Issued new listener for " + announce_uri);
|
||||||
return (SparkleListenerBase) listeners [listeners.Count - 1];
|
return (SparkleListenerBase) listeners [listeners.Count - 1];
|
||||||
}
|
}
|
||||||
|
@ -104,20 +106,21 @@ namespace SparkleLib {
|
||||||
public event AnnouncementEventHandler Announcement;
|
public event AnnouncementEventHandler Announcement;
|
||||||
public delegate void AnnouncementEventHandler (SparkleAnnouncement announcement);
|
public delegate void AnnouncementEventHandler (SparkleAnnouncement announcement);
|
||||||
|
|
||||||
|
|
||||||
public abstract void Connect ();
|
public abstract void Connect ();
|
||||||
public abstract void Announce (SparkleAnnouncement announcent);
|
public abstract void Announce (SparkleAnnouncement announcent);
|
||||||
public abstract void AlsoListenTo (string folder_identifier);
|
public abstract void AlsoListenTo (string folder_identifier);
|
||||||
public abstract bool IsConnected { get; }
|
public abstract bool IsConnected { get; }
|
||||||
|
|
||||||
|
protected List<string> channels = new List<string> ();
|
||||||
protected List<string> channels = new List<string> ();
|
protected Dictionary<string,List<SparkleAnnouncement>> recent_announcements = new Dictionary<string, List<SparkleAnnouncement>> ();
|
||||||
protected List<SparkleAnnouncement> queue_up = new List<SparkleAnnouncement> ();
|
protected int max_recent_announcements = 10;
|
||||||
protected List<SparkleAnnouncement> queue_down = new List<SparkleAnnouncement> ();
|
protected Dictionary<string, SparkleAnnouncement> queue_up = new Dictionary<string, SparkleAnnouncement> ();
|
||||||
|
protected Dictionary<string,SparkleAnnouncement> queue_down = new Dictionary<string, SparkleAnnouncement> ();
|
||||||
protected bool is_connecting;
|
protected bool is_connecting;
|
||||||
protected Uri server;
|
protected Uri server;
|
||||||
protected Timer reconnect_timer = new Timer { Interval = 60 * 1000, Enabled = true };
|
protected Timer reconnect_timer = new Timer { Interval = 60 * 1000, Enabled = true };
|
||||||
|
|
||||||
|
|
||||||
public SparkleListenerBase (Uri server, string folder_identifier)
|
public SparkleListenerBase (Uri server, string folder_identifier)
|
||||||
{
|
{
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
@ -133,30 +136,23 @@ namespace SparkleLib {
|
||||||
|
|
||||||
public void AnnounceBase (SparkleAnnouncement announcement)
|
public void AnnounceBase (SparkleAnnouncement announcement)
|
||||||
{
|
{
|
||||||
if (IsConnected) {
|
if (!this.IsRecentAnnounement (announcement)) {
|
||||||
SparkleHelpers.DebugInfo ("Listener",
|
if (IsConnected) {
|
||||||
"Announcing to " + announcement.FolderIdentifier + " on " + this.server);
|
SparkleHelpers.DebugInfo ("Listener",
|
||||||
|
"Announcing message " + announcement.Message + " to " + announcement.FolderIdentifier + " on " + this.server);
|
||||||
|
|
||||||
Announce (announcement);
|
Announce (announcement);
|
||||||
|
this.AddRecentAnnouncement (announcement);
|
||||||
|
} else {
|
||||||
|
SparkleHelpers.DebugInfo ("Listener", "Can't send message to " + this.server + ". Queuing message");
|
||||||
|
this.queue_up [announcement.FolderIdentifier] = announcement;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
SparkleHelpers.DebugInfo ("Listener", "Not connected to " + this.server + ". Queuing message");
|
SparkleHelpers.DebugInfo ("Listener",
|
||||||
this.queue_up.Add (announcement);
|
"Already processed message " + announcement.Message + " to " + announcement.FolderIdentifier + " from " + this.server);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public string NextQueueDownMessage (string folder_identifier)
|
|
||||||
{
|
|
||||||
foreach (SparkleAnnouncement announcement in this.queue_down.GetRange (0, this.queue_down.Count)) {
|
|
||||||
if (announcement.FolderIdentifier.Equals (folder_identifier)) {
|
|
||||||
string message = announcement.Message;
|
|
||||||
this.queue_down.Remove (announcement);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,10 +173,12 @@ namespace SparkleLib {
|
||||||
if (this.queue_up.Count > 0) {
|
if (this.queue_up.Count > 0) {
|
||||||
SparkleHelpers.DebugInfo ("Listener", "Delivering " + this.queue_up.Count + " queued messages...");
|
SparkleHelpers.DebugInfo ("Listener", "Delivering " + this.queue_up.Count + " queued messages...");
|
||||||
|
|
||||||
foreach (SparkleAnnouncement announcement in this.queue_up.GetRange (0, this.queue_up.Count)) {
|
foreach (KeyValuePair<string, SparkleAnnouncement> item in this.queue_up) {
|
||||||
|
SparkleAnnouncement announcement = item.Value;
|
||||||
AnnounceBase (announcement);
|
AnnounceBase (announcement);
|
||||||
this.queue_up.Remove (announcement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.queue_down.Clear ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,15 +194,71 @@ namespace SparkleLib {
|
||||||
|
|
||||||
public void OnAnnouncement (SparkleAnnouncement announcement)
|
public void OnAnnouncement (SparkleAnnouncement announcement)
|
||||||
{
|
{
|
||||||
SparkleHelpers.DebugInfo ("Listener", "Got message from " + announcement.FolderIdentifier + " on " + this.server);
|
SparkleHelpers.DebugInfo ("Listener",
|
||||||
|
"Got message " + announcement.Message + " from " + announcement.FolderIdentifier + " on " + this.server);
|
||||||
|
|
||||||
this.queue_down.Add (announcement);
|
if (IsRecentAnnounement(announcement) ){
|
||||||
|
SparkleHelpers.DebugInfo ("Listener",
|
||||||
|
"Ignoring previously processed message " + announcement.Message +
|
||||||
|
" from " + announcement.FolderIdentifier + " on " + this.server);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SparkleHelpers.DebugInfo ("Listener",
|
||||||
|
"Processing message " + announcement.Message + " from " + announcement.FolderIdentifier + " on " + this.server);
|
||||||
|
|
||||||
|
AddRecentAnnouncement (announcement);
|
||||||
|
this.queue_down [announcement.FolderIdentifier] = announcement;
|
||||||
|
|
||||||
if (Announcement != null)
|
if (Announcement != null)
|
||||||
Announcement (announcement);
|
Announcement (announcement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool IsRecentAnnounement (SparkleAnnouncement announcement)
|
||||||
|
{
|
||||||
|
if (!HasRecentAnnouncements (announcement.FolderIdentifier)) {
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
foreach (SparkleAnnouncement recent_announcement in GetRecentAnnouncements (announcement.FolderIdentifier)) {
|
||||||
|
if (recent_announcement.Message.Equals (announcement.Message))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private List<SparkleAnnouncement> GetRecentAnnouncements (string folder_identifier)
|
||||||
|
{
|
||||||
|
if (!this.recent_announcements.ContainsKey (folder_identifier))
|
||||||
|
this.recent_announcements [folder_identifier] = new List<SparkleAnnouncement> ();
|
||||||
|
|
||||||
|
return (List<SparkleAnnouncement>) this.recent_announcements [folder_identifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void AddRecentAnnouncement (SparkleAnnouncement announcement)
|
||||||
|
{
|
||||||
|
List<SparkleAnnouncement> recent_announcements = this.GetRecentAnnouncements (announcement.FolderIdentifier);
|
||||||
|
|
||||||
|
if (!IsRecentAnnounement (announcement))
|
||||||
|
recent_announcements.Add (announcement);
|
||||||
|
|
||||||
|
if (recent_announcements.Count > this.max_recent_announcements)
|
||||||
|
recent_announcements.RemoveRange (0, (recent_announcements.Count - this.max_recent_announcements));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool HasRecentAnnouncements (string folder_identifier)
|
||||||
|
{
|
||||||
|
return this.recent_announcements.ContainsKey (folder_identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual void Dispose ()
|
public virtual void Dispose ()
|
||||||
{
|
{
|
||||||
this.reconnect_timer.Dispose ();
|
this.reconnect_timer.Dispose ();
|
||||||
|
@ -225,3 +279,4 @@ namespace SparkleLib {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace SparkleLib {
|
||||||
public class SparkleListenerTcp : SparkleListenerBase {
|
public class SparkleListenerTcp : SparkleListenerBase {
|
||||||
|
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
|
|
||||||
// these are shared
|
// these are shared
|
||||||
private readonly Object mutex = new Object();
|
private readonly Object mutex = new Object();
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
@ -93,11 +93,14 @@ namespace SparkleLib {
|
||||||
|
|
||||||
if (bytes_read > 0) {
|
if (bytes_read > 0) {
|
||||||
string received = Encoding.UTF8.GetString (bytes);
|
string received = Encoding.UTF8.GetString (bytes);
|
||||||
string folder_identifier = received.Substring (0, received.IndexOf ("!"));
|
string line = received.Substring (0, received.IndexOf ("\n"));
|
||||||
string message = received.Substring (received.IndexOf ("!") + 1);
|
if (!line.Contains ("!"))
|
||||||
|
continue;
|
||||||
OnAnnouncement (new SparkleAnnouncement (folder_identifier, message));
|
string folder_identifier = line.Substring (0, line.IndexOf ("!"));
|
||||||
|
string message = this.CleanMessage (line.Substring (line.IndexOf ("!") + 1));
|
||||||
|
if (!folder_identifier.Equals("debug") &&
|
||||||
|
!String.IsNullOrEmpty(message))
|
||||||
|
OnAnnouncement (new SparkleAnnouncement (folder_identifier, message));
|
||||||
} else {
|
} else {
|
||||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Error on socket");
|
SparkleHelpers.DebugInfo ("ListenerTcp", "Error on socket");
|
||||||
|
|
||||||
|
@ -109,9 +112,9 @@ namespace SparkleLib {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Disconnected from " + Server.Host);
|
SparkleHelpers.DebugInfo ("ListenerTcp", "Disconnected from " + Server.Host);
|
||||||
|
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
SparkleHelpers.DebugInfo ("ListenerTcp", "Could not connect to " + Server + ": " + e.Message);
|
SparkleHelpers.DebugInfo ("ListenerTcp", "Could not connect to " + Server + ": " + e.Message);
|
||||||
|
|
||||||
|
@ -173,5 +176,10 @@ namespace SparkleLib {
|
||||||
this.thread.Join ();
|
this.thread.Join ();
|
||||||
base.Dispose ();
|
base.Dispose ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string CleanMessage(string message)
|
||||||
|
{
|
||||||
|
return message.Trim ().Replace ("\n", "").Replace ("\0", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,12 +110,6 @@ namespace SparkleLib {
|
||||||
|
|
||||||
if (CheckForRemoteChanges ())
|
if (CheckForRemoteChanges ())
|
||||||
SyncDownBase ();
|
SyncDownBase ();
|
||||||
|
|
||||||
string message;
|
|
||||||
while ((message = this.listener.NextQueueDownMessage (Identifier)) != null) {
|
|
||||||
if (!message.Equals (CurrentRevision))
|
|
||||||
SyncDownBase ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the unlikely case that we haven't synced up our
|
// In the unlikely case that we haven't synced up our
|
||||||
|
@ -265,19 +259,18 @@ namespace SparkleLib {
|
||||||
if (announcement.FolderIdentifier.Equals (identifier) &&
|
if (announcement.FolderIdentifier.Equals (identifier) &&
|
||||||
!announcement.Message.Equals (CurrentRevision)) {
|
!announcement.Message.Equals (CurrentRevision)) {
|
||||||
|
|
||||||
if ((Status != SyncStatus.SyncUp) &&
|
while (this.IsSyncing ()) {
|
||||||
(Status != SyncStatus.SyncDown) &&
|
System.Threading.Thread.Sleep (100);
|
||||||
!this.is_buffering) {
|
|
||||||
|
|
||||||
string message;
|
|
||||||
while ((message = this.listener.NextQueueDownMessage (identifier)) != null) {
|
|
||||||
if (!message.Equals (CurrentRevision))
|
|
||||||
SyncDownBase ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
SparkleHelpers.DebugInfo ("Listener", "Syncing due to Announcement");
|
||||||
|
if (!announcement.Message.Equals (CurrentRevision))
|
||||||
|
SyncDownBase ();
|
||||||
|
} else {
|
||||||
|
if (announcement.FolderIdentifier.Equals (identifier))
|
||||||
|
SparkleHelpers.DebugInfo ("Listener", "Not syncing message is for current revision");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Start listening
|
// Start listening
|
||||||
if (!this.listener.IsConnected && !this.listener.IsConnecting) {
|
if (!this.listener.IsConnected && !this.listener.IsConnecting) {
|
||||||
this.listener.Connect ();
|
this.listener.Connect ();
|
||||||
|
@ -285,13 +278,21 @@ namespace SparkleLib {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private bool IsSyncing ()
|
||||||
|
{
|
||||||
|
if (Status == SyncStatus.SyncUp || Status == SyncStatus.SyncDown || this.is_buffering)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void CheckForChanges ()
|
private void CheckForChanges ()
|
||||||
{
|
{
|
||||||
lock (this.change_lock) {
|
lock (this.change_lock) {
|
||||||
if (this.has_changed) {
|
if (this.has_changed) {
|
||||||
if (this.sizebuffer.Count >= 4)
|
if (this.sizebuffer.Count >= 4)
|
||||||
this.sizebuffer.RemoveAt (0);
|
this.sizebuffer.RemoveAt (0);
|
||||||
|
|
||||||
DirectoryInfo dir_info = new DirectoryInfo (LocalPath);
|
DirectoryInfo dir_info = new DirectoryInfo (LocalPath);
|
||||||
this.sizebuffer.Add (CalculateFolderSize (dir_info));
|
this.sizebuffer.Add (CalculateFolderSize (dir_info));
|
||||||
|
|
||||||
|
@ -303,7 +304,7 @@ namespace SparkleLib {
|
||||||
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes have settled.");
|
SparkleHelpers.DebugInfo ("Local", "[" + Name + "] Changes have settled.");
|
||||||
this.is_buffering = false;
|
this.is_buffering = false;
|
||||||
this.has_changed = false;
|
this.has_changed = false;
|
||||||
|
|
||||||
DisableWatching ();
|
DisableWatching ();
|
||||||
while (AnyDifferences)
|
while (AnyDifferences)
|
||||||
SyncUpBase ();
|
SyncUpBase ();
|
||||||
|
@ -447,6 +448,8 @@ namespace SparkleLib {
|
||||||
if (SyncStatusChanged != null)
|
if (SyncStatusChanged != null)
|
||||||
SyncStatusChanged (SyncStatus.SyncDown);
|
SyncStatusChanged (SyncStatus.SyncDown);
|
||||||
|
|
||||||
|
string pre_sync_revision = CurrentRevision;
|
||||||
|
|
||||||
if (SyncDown ()) {
|
if (SyncDown ()) {
|
||||||
SparkleHelpers.DebugInfo ("SyncDown", "[" + Name + "] Done");
|
SparkleHelpers.DebugInfo ("SyncDown", "[" + Name + "] Done");
|
||||||
this.server_online = true;
|
this.server_online = true;
|
||||||
|
@ -454,24 +457,27 @@ namespace SparkleLib {
|
||||||
if (SyncStatusChanged != null)
|
if (SyncStatusChanged != null)
|
||||||
SyncStatusChanged (SyncStatus.Idle);
|
SyncStatusChanged (SyncStatus.Idle);
|
||||||
|
|
||||||
List<SparkleChangeSet> change_sets = GetChangeSets (1);
|
if (!pre_sync_revision.Equals (CurrentRevision)) {
|
||||||
if (change_sets != null && change_sets.Count > 0) {
|
List<SparkleChangeSet> change_sets = GetChangeSets (1);
|
||||||
SparkleChangeSet change_set = change_sets [0];
|
|
||||||
|
|
||||||
bool note_added = false;
|
if (change_sets != null && change_sets.Count > 0) {
|
||||||
foreach (string added in change_set.Added) {
|
SparkleChangeSet change_set = change_sets [0];
|
||||||
if (added.Contains (".notes")) {
|
|
||||||
if (NewNote != null)
|
|
||||||
NewNote (change_set.User.Name, change_set.User.Email);
|
|
||||||
|
|
||||||
note_added = true;
|
bool note_added = false;
|
||||||
break;
|
foreach (string added in change_set.Added) {
|
||||||
|
if (added.Contains (".notes")) {
|
||||||
|
if (NewNote != null)
|
||||||
|
NewNote (change_set.User.Name, change_set.User.Email);
|
||||||
|
|
||||||
|
note_added = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!note_added) {
|
if (!note_added) {
|
||||||
if (NewChangeSet != null)
|
if (NewChangeSet != null)
|
||||||
NewChangeSet (change_set);
|
NewChangeSet (change_set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ namespace SparkleShare {
|
||||||
public abstract string PluginsPath { get; }
|
public abstract string PluginsPath { get; }
|
||||||
|
|
||||||
private SparkleFetcherBase fetcher;
|
private SparkleFetcherBase fetcher;
|
||||||
|
private List<string> failed_avatars = new List<string> ();
|
||||||
|
|
||||||
|
|
||||||
// Short alias for the translations
|
// Short alias for the translations
|
||||||
|
@ -941,6 +942,8 @@ namespace SparkleShare {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (this.failed_avatars.Contains (email)) {
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
WebClient client = new WebClient ();
|
WebClient client = new WebClient ();
|
||||||
string url = "http://gravatar.com/avatar/" + GetMD5 (email) +
|
string url = "http://gravatar.com/avatar/" + GetMD5 (email) +
|
||||||
|
@ -962,8 +965,11 @@ namespace SparkleShare {
|
||||||
SparkleHelpers.DebugInfo ("Controller", "Failed fetching gravatar for " + email);
|
SparkleHelpers.DebugInfo ("Controller", "Failed fetching gravatar for " + email);
|
||||||
|
|
||||||
// Stop downloading further avatars if we have no internet access
|
// Stop downloading further avatars if we have no internet access
|
||||||
if (e.Status == WebExceptionStatus.Timeout)
|
if (e.Status == WebExceptionStatus.Timeout){
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
this.failed_avatars.Add (email);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
29
data/git-hooks/post-update
Executable file
29
data/git-hooks/post-update
Executable file
|
@ -0,0 +1,29 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# for use with gitolite
|
||||||
|
#
|
||||||
|
# http://sitaramc.github.com/gitolite/hooks.html
|
||||||
|
# copy this file to
|
||||||
|
# .gitolite/hooks/common/post-update
|
||||||
|
# run gl-setup again
|
||||||
|
|
||||||
|
# for use with standard ssh/http(s)/git repos
|
||||||
|
#
|
||||||
|
# simply move this file to
|
||||||
|
# .git/hooks/post-update in the remote repository
|
||||||
|
|
||||||
|
# make sure to chmod -x in all cases after the file has been copied
|
||||||
|
|
||||||
|
#To supress all output
|
||||||
|
exec > /dev/null 2>&1
|
||||||
|
|
||||||
|
# for information on running your own server
|
||||||
|
# https://github.com/hbons/fanout.node.js
|
||||||
|
SERVER="204.62.14.135"
|
||||||
|
PORT="1986"
|
||||||
|
CHANNEL=$(git rev-list --reverse HEAD | head -n 1)
|
||||||
|
MESSAGE=$(git rev-list HEAD | head -n 1)
|
||||||
|
DATA="announce ${CHANNEL} ${MESSAGE}"
|
||||||
|
echo "${DATA}\n" | socat - TCP-CONNECT:${SERVER}:${PORT} &
|
||||||
|
|
||||||
|
exit 0
|
Loading…
Reference in a new issue