Merge branch 'master' into translations
This commit is contained in:
commit
7e8e84618f
1
AUTHORS
1
AUTHORS
|
@ -13,6 +13,7 @@ Contributors:
|
||||||
Jakub Steiner <jimmac@novell.com>
|
Jakub Steiner <jimmac@novell.com>
|
||||||
Lapo Calamandrei <calamandrei@gmail.com>
|
Lapo Calamandrei <calamandrei@gmail.com>
|
||||||
Łukasz Jernaś <deejay1@srem.org>
|
Łukasz Jernaś <deejay1@srem.org>
|
||||||
|
Michael Monreal <michael.monreal@gmail.com>
|
||||||
Oleg Khlystov <pktfag@gmail.com>
|
Oleg Khlystov <pktfag@gmail.com>
|
||||||
Philipp Gildein <rmbl@openspeak-project.org>
|
Philipp Gildein <rmbl@openspeak-project.org>
|
||||||
Ruben Vermeersch <rubenv@gnome.org>
|
Ruben Vermeersch <rubenv@gnome.org>
|
||||||
|
|
|
@ -98,6 +98,7 @@ namespace SparkleLib {
|
||||||
private void InstallUserInfo ()
|
private void InstallUserInfo ()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// TODO: Use TargetFolder and move SparklePaths out of SparkleLib
|
||||||
string global_config_file_path = SparkleHelpers.CombineMore (SparklePaths.SparkleConfigPath, "config");
|
string global_config_file_path = SparkleHelpers.CombineMore (SparklePaths.SparkleConfigPath, "config");
|
||||||
|
|
||||||
if (File.Exists (global_config_file_path)) {
|
if (File.Exists (global_config_file_path)) {
|
||||||
|
|
|
@ -23,8 +23,7 @@ using System.Timers;
|
||||||
|
|
||||||
namespace SparkleLib {
|
namespace SparkleLib {
|
||||||
|
|
||||||
public class SparkleRepo
|
public class SparkleRepo {
|
||||||
{
|
|
||||||
|
|
||||||
private Process Process;
|
private Process Process;
|
||||||
private Timer FetchTimer;
|
private Timer FetchTimer;
|
||||||
|
@ -85,6 +84,8 @@ namespace SparkleLib {
|
||||||
CurrentHash = GetCurrentHash ();
|
CurrentHash = GetCurrentHash ();
|
||||||
Domain = GetDomain (RemoteOriginUrl);
|
Domain = GetDomain (RemoteOriginUrl);
|
||||||
|
|
||||||
|
if (CurrentHash == null)
|
||||||
|
CreateInitialCommit ();
|
||||||
|
|
||||||
HasChanged = false;
|
HasChanged = false;
|
||||||
|
|
||||||
|
@ -128,6 +129,9 @@ namespace SparkleLib {
|
||||||
// since SparkleShare was stopped
|
// since SparkleShare was stopped
|
||||||
AddCommitAndPush ();
|
AddCommitAndPush ();
|
||||||
|
|
||||||
|
if (CurrentHash == null)
|
||||||
|
CurrentHash = GetCurrentHash ();
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Idling...");
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Idling...");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -278,7 +282,7 @@ namespace SparkleLib {
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Fetching changes...");
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Fetching changes...");
|
||||||
|
|
||||||
process.StartInfo.Arguments = "fetch";
|
process.StartInfo.Arguments = "fetch -v origin master";
|
||||||
|
|
||||||
process.Start ();
|
process.Start ();
|
||||||
|
|
||||||
|
@ -306,11 +310,13 @@ namespace SparkleLib {
|
||||||
public void Rebase ()
|
public void Rebase ()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Add (); // TODO: Experiment for the "You have unstaged changes" bug
|
||||||
|
|
||||||
Watcher.EnableRaisingEvents = false;
|
Watcher.EnableRaisingEvents = false;
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Rebasing changes...");
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Rebasing changes...");
|
||||||
|
|
||||||
Process.StartInfo.Arguments = "rebase -v origin/master";
|
Process.StartInfo.Arguments = "rebase -v FETCH_HEAD";
|
||||||
Process.WaitForExit ();
|
Process.WaitForExit ();
|
||||||
Process.Start ();
|
Process.Start ();
|
||||||
|
|
||||||
|
@ -409,7 +415,7 @@ namespace SparkleLib {
|
||||||
|
|
||||||
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Pushing changes...");
|
SparkleHelpers.DebugInfo ("Git", "[" + Name + "] Pushing changes...");
|
||||||
|
|
||||||
Process.StartInfo.Arguments = "push";
|
Process.StartInfo.Arguments = "push origin master";
|
||||||
Process.Start ();
|
Process.Start ();
|
||||||
Process.WaitForExit ();
|
Process.WaitForExit ();
|
||||||
|
|
||||||
|
@ -466,6 +472,9 @@ namespace SparkleLib {
|
||||||
public string GetDomain (string url)
|
public string GetDomain (string url)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (RemoteOriginUrl.Equals (""))
|
||||||
|
return "";
|
||||||
|
|
||||||
string domain = url.Substring (RemoteOriginUrl.IndexOf ("@") + 1);
|
string domain = url.Substring (RemoteOriginUrl.IndexOf ("@") + 1);
|
||||||
|
|
||||||
if (domain.IndexOf (":") > -1)
|
if (domain.IndexOf (":") > -1)
|
||||||
|
@ -482,19 +491,25 @@ namespace SparkleLib {
|
||||||
public string GetCurrentHash ()
|
public string GetCurrentHash ()
|
||||||
{
|
{
|
||||||
|
|
||||||
string current_hash;
|
Process process = new Process () {
|
||||||
|
EnableRaisingEvents = true
|
||||||
|
};
|
||||||
|
|
||||||
Process process = new Process ();
|
|
||||||
process.StartInfo.RedirectStandardOutput = true;
|
process.StartInfo.RedirectStandardOutput = true;
|
||||||
process.StartInfo.UseShellExecute = false;
|
process.StartInfo.UseShellExecute = false;
|
||||||
process.StartInfo.FileName = "git";
|
process.StartInfo.FileName = "git";
|
||||||
process.StartInfo.WorkingDirectory = LocalPath;
|
process.StartInfo.WorkingDirectory = LocalPath;
|
||||||
process.StartInfo.Arguments = "rev-list --max-count=1 HEAD";
|
process.StartInfo.Arguments = "rev-list --max-count=1 HEAD";
|
||||||
|
|
||||||
process.Start ();
|
process.Start ();
|
||||||
|
process.WaitForExit ();
|
||||||
|
|
||||||
current_hash = process.StandardOutput.ReadToEnd ().Trim ();
|
string current_hash = process.StandardOutput.ReadToEnd ().Trim ();
|
||||||
|
|
||||||
return current_hash;
|
if (process.ExitCode != 0)
|
||||||
|
return null;
|
||||||
|
else
|
||||||
|
return current_hash;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,6 +566,18 @@ namespace SparkleLib {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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 ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Gets the url of the remote repo, example: "ssh://git@git.gnome.org/project"
|
// Gets the url of the remote repo, example: "ssh://git@git.gnome.org/project"
|
||||||
public string GetRemoteOriginUrl ()
|
public string GetRemoteOriginUrl ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,8 @@ SOURCES = \
|
||||||
SparkleBubble.cs \
|
SparkleBubble.cs \
|
||||||
SparkleEntry.cs \
|
SparkleEntry.cs \
|
||||||
SparkleIntro.cs \
|
SparkleIntro.cs \
|
||||||
|
SparkleInvitation.cs \
|
||||||
|
SparkleLog.cs \
|
||||||
SparkleShare.cs \
|
SparkleShare.cs \
|
||||||
SparkleSpinner.cs \
|
SparkleSpinner.cs \
|
||||||
SparkleStatusIcon.cs \
|
SparkleStatusIcon.cs \
|
||||||
|
|
File diff suppressed because it is too large
Load diff
43
SparkleShare/SparkleInvitation.cs
Normal file
43
SparkleShare/SparkleInvitation.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// 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.IO;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace SparkleShare {
|
||||||
|
|
||||||
|
class SparkleInvitation {
|
||||||
|
|
||||||
|
public SparkleInvitation (string file_path)
|
||||||
|
{
|
||||||
|
|
||||||
|
XmlDocument xml_doc = new XmlDocument ();
|
||||||
|
xml_doc.Load (file_path);
|
||||||
|
|
||||||
|
XmlNodeList server_xml = xml_doc.GetElementsByTagName ("server");
|
||||||
|
XmlNodeList repository_xml = xml_doc.GetElementsByTagName ("repository");
|
||||||
|
XmlNodeList key_xml = xml_doc.GetElementsByTagName ("key");
|
||||||
|
|
||||||
|
string server = server_xml [0].InnerText;
|
||||||
|
string repository = repository_xml [0].InnerText;
|
||||||
|
string key = key_xml [0].InnerText;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
318
SparkleShare/SparkleLog.cs
Normal file
318
SparkleShare/SparkleLog.cs
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
// 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 Gtk;
|
||||||
|
using Mono.Unix;
|
||||||
|
using SparkleLib;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace SparkleShare {
|
||||||
|
|
||||||
|
public class SparkleLog : Window {
|
||||||
|
|
||||||
|
private SparkleRepo SparkleRepo;
|
||||||
|
private VBox LayoutVertical;
|
||||||
|
private ScrolledWindow ScrolledWindow;
|
||||||
|
|
||||||
|
|
||||||
|
// Short alias for the translations
|
||||||
|
public static string _ (string s)
|
||||||
|
{
|
||||||
|
return Catalog.GetString (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SparkleLog (SparkleRepo sparkle_repo) : base ("")
|
||||||
|
{
|
||||||
|
|
||||||
|
SparkleRepo = sparkle_repo;
|
||||||
|
SetSizeRequest (540, 640);
|
||||||
|
SetPosition (WindowPosition.Center);
|
||||||
|
BorderWidth = 12;
|
||||||
|
|
||||||
|
// TRANSLATORS: {0} is a folder name, and {1} is a server address
|
||||||
|
Title = String.Format(_("Recent Events in ‘{0}’"), SparkleRepo.Name);
|
||||||
|
IconName = "folder";
|
||||||
|
|
||||||
|
LayoutVertical = new VBox (false, 12);
|
||||||
|
|
||||||
|
LayoutVertical.PackStart (CreateEventLog (), true, true, 0);
|
||||||
|
|
||||||
|
HButtonBox dialog_buttons = new HButtonBox {
|
||||||
|
Layout = ButtonBoxStyle.Edge,
|
||||||
|
BorderWidth = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
Button open_folder_button = new Button (_("Open Folder"));
|
||||||
|
|
||||||
|
open_folder_button.Clicked += delegate (object o, EventArgs args) {
|
||||||
|
|
||||||
|
string path = SparkleHelpers.CombineMore (SparklePaths.SparklePath, SparkleRepo.Name);
|
||||||
|
|
||||||
|
Process process = new Process ();
|
||||||
|
process.StartInfo.FileName = "xdg-open";
|
||||||
|
process.StartInfo.Arguments = path.Replace(" ", "\\ "); // Escape space-characters
|
||||||
|
process.Start ();
|
||||||
|
|
||||||
|
Destroy ();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Button close_button = new Button (Stock.Close);
|
||||||
|
|
||||||
|
close_button.Clicked += delegate (object o, EventArgs args) {
|
||||||
|
Destroy ();
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog_buttons.Add (open_folder_button);
|
||||||
|
dialog_buttons.Add (close_button);
|
||||||
|
|
||||||
|
LayoutVertical.PackStart (dialog_buttons, false, false, 0);
|
||||||
|
|
||||||
|
Add (LayoutVertical);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void UpdateEventLog ()
|
||||||
|
{
|
||||||
|
|
||||||
|
LayoutVertical.Remove (ScrolledWindow);
|
||||||
|
ScrolledWindow = CreateEventLog ();
|
||||||
|
LayoutVertical.PackStart (ScrolledWindow, true, true, 0);
|
||||||
|
LayoutVertical.ReorderChild (ScrolledWindow, 0);
|
||||||
|
ShowAll ();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ScrolledWindow CreateEventLog ()
|
||||||
|
{
|
||||||
|
|
||||||
|
int number_of_events = 50;
|
||||||
|
|
||||||
|
Process process = new Process () {
|
||||||
|
EnableRaisingEvents = true
|
||||||
|
};
|
||||||
|
|
||||||
|
process.StartInfo.RedirectStandardOutput = true;
|
||||||
|
process.StartInfo.UseShellExecute = false;
|
||||||
|
process.StartInfo.WorkingDirectory = SparkleRepo.LocalPath;
|
||||||
|
process.StartInfo.FileName = "git";
|
||||||
|
process.StartInfo.Arguments = "log --format=\"%at☃%an☃%ae☃%s\" -" + number_of_events;
|
||||||
|
|
||||||
|
process.Start ();
|
||||||
|
|
||||||
|
string output = process.StandardOutput.ReadToEnd ().Trim ();
|
||||||
|
|
||||||
|
output = output.TrimStart ("\n".ToCharArray ());
|
||||||
|
string [] lines = Regex.Split (output, "\n");
|
||||||
|
int linesLength = lines.Length;
|
||||||
|
if (output == "")
|
||||||
|
linesLength = 0;
|
||||||
|
|
||||||
|
// Sort by time and get the last 25
|
||||||
|
Array.Sort (lines);
|
||||||
|
Array.Reverse (lines);
|
||||||
|
|
||||||
|
List <ActivityDay> activity_days = new List <ActivityDay> ();
|
||||||
|
|
||||||
|
for (int i = 0; i < number_of_events && i < linesLength; i++) {
|
||||||
|
|
||||||
|
string line = lines [i];
|
||||||
|
|
||||||
|
// Look for the snowman!
|
||||||
|
string [] parts = Regex.Split (line, "☃");
|
||||||
|
|
||||||
|
int unix_timestamp = int.Parse (parts [0]);
|
||||||
|
string user_name = parts [1];
|
||||||
|
string user_email = parts [2];
|
||||||
|
string message = parts [3];
|
||||||
|
|
||||||
|
DateTime date_time = UnixTimestampToDateTime (unix_timestamp);
|
||||||
|
|
||||||
|
message = message.Replace ("\n", " ");
|
||||||
|
|
||||||
|
ChangeSet change_set = new ChangeSet (user_name, user_email, message, date_time);
|
||||||
|
|
||||||
|
bool change_set_inserted = false;
|
||||||
|
foreach (ActivityDay stored_activity_day in activity_days) {
|
||||||
|
|
||||||
|
if (stored_activity_day.DateTime.Year == change_set.DateTime.Year &&
|
||||||
|
stored_activity_day.DateTime.Month == change_set.DateTime.Month &&
|
||||||
|
stored_activity_day.DateTime.Day == change_set.DateTime.Day) {
|
||||||
|
|
||||||
|
stored_activity_day.Add (change_set);
|
||||||
|
change_set_inserted = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!change_set_inserted) {
|
||||||
|
|
||||||
|
ActivityDay activity_day = new ActivityDay (change_set.DateTime);
|
||||||
|
activity_day.Add (change_set);
|
||||||
|
activity_days.Add (activity_day);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VBox layout_vertical = new VBox (false, 0);
|
||||||
|
|
||||||
|
foreach (ActivityDay activity_day in activity_days) {
|
||||||
|
|
||||||
|
TreeIter iter = new TreeIter ();
|
||||||
|
ListStore list_store = new ListStore (typeof (Gdk.Pixbuf),
|
||||||
|
typeof (string),
|
||||||
|
typeof (string));
|
||||||
|
|
||||||
|
Gdk.Color color = Style.Foreground (StateType.Insensitive);
|
||||||
|
string secondary_text_color = GdkColorToHex (color);
|
||||||
|
|
||||||
|
foreach (ChangeSet change_set in activity_day) {
|
||||||
|
|
||||||
|
iter = list_store.Append ();
|
||||||
|
|
||||||
|
list_store.SetValue (iter, 0, SparkleHelpers.GetAvatar (change_set.UserEmail , 32));
|
||||||
|
|
||||||
|
list_store.SetValue (iter, 1, "<b>" + change_set.UserName + "</b>\n" +
|
||||||
|
"<span fgcolor='" + secondary_text_color +"'>" +
|
||||||
|
change_set.Message + "\n" +
|
||||||
|
"<small>" + change_set.DateTime.ToString ("HH:mm") + "</small>" +
|
||||||
|
"</span>");
|
||||||
|
|
||||||
|
list_store.SetValue (iter, 2, change_set.UserEmail);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Label date_label = new Label ("") {
|
||||||
|
UseMarkup = true,
|
||||||
|
Xalign = 0,
|
||||||
|
Xpad = 9,
|
||||||
|
Ypad = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
DateTime today = DateTime.Now;
|
||||||
|
DateTime yesterday = DateTime.Now.AddDays (-1);
|
||||||
|
|
||||||
|
if (today.Day == activity_day.DateTime.Day &&
|
||||||
|
today.Month == activity_day.DateTime.Month &&
|
||||||
|
today.Year == activity_day.DateTime.Year) {
|
||||||
|
|
||||||
|
date_label.Markup = "<b>Today</b>";
|
||||||
|
|
||||||
|
} else if (yesterday.Day == activity_day.DateTime.Day &&
|
||||||
|
yesterday.Month == activity_day.DateTime.Month &&
|
||||||
|
yesterday.Year == activity_day.DateTime.Year) {
|
||||||
|
|
||||||
|
date_label.Markup = "<b>Yesterday</b>";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
date_label.Markup = "<b>" + activity_day.DateTime.ToString ("ddd MMM d, yyyy") + "</b>";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
layout_vertical.PackStart (date_label, false, false, 0);
|
||||||
|
|
||||||
|
IconView icon_view = new IconView (list_store) {
|
||||||
|
ItemWidth = 470,
|
||||||
|
MarkupColumn = 1,
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
PixbufColumn = 0,
|
||||||
|
Spacing = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
icon_view.SelectionChanged += delegate {
|
||||||
|
icon_view.UnselectAll ();
|
||||||
|
};
|
||||||
|
|
||||||
|
layout_vertical.PackStart (icon_view, false, false, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrolledWindow = new ScrolledWindow ();
|
||||||
|
ScrolledWindow.ShadowType = ShadowType.None;
|
||||||
|
ScrolledWindow.AddWithViewport (layout_vertical);
|
||||||
|
|
||||||
|
return ScrolledWindow;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts a UNIX timestamp to a more usable time object
|
||||||
|
public DateTime UnixTimestampToDateTime (int timestamp)
|
||||||
|
{
|
||||||
|
DateTime unix_epoch = new DateTime (1970, 1, 1, 0, 0, 0, 0);
|
||||||
|
return unix_epoch.AddSeconds (timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Converts a Gdk RGB color to a hex value.
|
||||||
|
// Example: from "rgb:0,0,0" to "#000000"
|
||||||
|
public string GdkColorToHex (Gdk.Color color)
|
||||||
|
{
|
||||||
|
|
||||||
|
return String.Format ("#{0:X2}{1:X2}{2:X2}",
|
||||||
|
(int) Math.Truncate (color.Red / 256.00),
|
||||||
|
(int) Math.Truncate (color.Green / 256.00),
|
||||||
|
(int) Math.Truncate (color.Blue / 256.00));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class ActivityDay : List <ChangeSet>
|
||||||
|
{
|
||||||
|
|
||||||
|
public DateTime DateTime;
|
||||||
|
|
||||||
|
public ActivityDay (DateTime date_time)
|
||||||
|
{
|
||||||
|
DateTime = date_time;
|
||||||
|
DateTime = new DateTime (DateTime.Year, DateTime.Month, DateTime.Day);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class ChangeSet
|
||||||
|
{
|
||||||
|
|
||||||
|
public string UserName;
|
||||||
|
public string UserEmail;
|
||||||
|
public string Message;
|
||||||
|
public DateTime DateTime;
|
||||||
|
|
||||||
|
public ChangeSet (string user_name, string user_email, string message, DateTime date_time)
|
||||||
|
{
|
||||||
|
UserName = user_name;
|
||||||
|
UserEmail = user_email;
|
||||||
|
Message = message;
|
||||||
|
DateTime = date_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -25,13 +25,15 @@ namespace SparkleShare {
|
||||||
// This is SparkleShare!
|
// This is SparkleShare!
|
||||||
public class SparkleShare {
|
public class SparkleShare {
|
||||||
|
|
||||||
|
public static SparkleUI SparkleUI;
|
||||||
|
|
||||||
|
|
||||||
// Short alias for the translations
|
// Short alias for the translations
|
||||||
public static string _ (string s)
|
public static string _ (string s)
|
||||||
{
|
{
|
||||||
return Catalog.GetString (s);
|
return Catalog.GetString (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SparkleUI SparkleUI;
|
|
||||||
|
|
||||||
public static void Main (string [] args)
|
public static void Main (string [] args)
|
||||||
{
|
{
|
||||||
|
@ -60,41 +62,74 @@ namespace SparkleShare {
|
||||||
Environment.Exit (0);
|
Environment.Exit (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the command line arguments
|
|
||||||
bool HideUI = false;
|
bool HideUI = false;
|
||||||
|
|
||||||
|
// Parse the command line arguments
|
||||||
if (args.Length > 0) {
|
if (args.Length > 0) {
|
||||||
|
|
||||||
foreach (string Argument in args) {
|
foreach (string Argument in args) {
|
||||||
|
|
||||||
if (Argument.Equals ("--disable-gui") || Argument.Equals ("-d"))
|
if (Argument.Equals ("--disable-gui") || Argument.Equals ("-d"))
|
||||||
HideUI = true;
|
HideUI = true;
|
||||||
|
|
||||||
|
if (Argument.Equals ("--version") || Argument.Equals ("-v")) {
|
||||||
|
|
||||||
|
PrintVersion ();
|
||||||
|
Environment.Exit (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (Argument.Equals ("--help") || Argument.Equals ("-h")) {
|
if (Argument.Equals ("--help") || Argument.Equals ("-h")) {
|
||||||
|
|
||||||
ShowHelp ();
|
ShowHelp ();
|
||||||
Environment.Exit (0);
|
Environment.Exit (0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SparkleUI = new SparkleUI (HideUI);
|
SparkleUI = new SparkleUI (HideUI);
|
||||||
SparkleUI.Run();
|
SparkleUI.Run();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Prints the help output
|
// Prints the help output
|
||||||
public static void ShowHelp ()
|
public static void ShowHelp ()
|
||||||
{
|
{
|
||||||
Console.WriteLine (_("SparkleShare Copyright (C) 2010 Hylke Bons"));
|
|
||||||
|
Console.WriteLine (" ");
|
||||||
|
Console.WriteLine (_("SparkleShare, an instant update workflow to Git."));
|
||||||
|
Console.WriteLine (_("Copyright (C) 2010 Hylke Bons"));
|
||||||
Console.WriteLine (" ");
|
Console.WriteLine (" ");
|
||||||
Console.WriteLine (_("This program comes with ABSOLUTELY NO WARRANTY."));
|
Console.WriteLine (_("This program comes with ABSOLUTELY NO WARRANTY."));
|
||||||
|
Console.WriteLine (" ");
|
||||||
Console.WriteLine (_("This is free software, and you are welcome to redistribute it "));
|
Console.WriteLine (_("This is free software, and you are welcome to redistribute it "));
|
||||||
Console.WriteLine (_("under certain conditions. Please read the GNU GPLv3 for details."));
|
Console.WriteLine (_("under certain conditions. Please read the GNU GPLv3 for details."));
|
||||||
Console.WriteLine (" ");
|
Console.WriteLine (" ");
|
||||||
Console.WriteLine (_("SparkleShare syncs the ~/SparkleShare folder with remote repositories."));
|
Console.WriteLine (_("SparkleShare automatically syncs Git repositories in "));
|
||||||
|
Console.WriteLine (_("the ~/SparkleShare folder with their remote origins."));
|
||||||
Console.WriteLine (" ");
|
Console.WriteLine (" ");
|
||||||
Console.WriteLine (_("Usage: sparkleshare [start|stop|restart] [OPTION]..."));
|
Console.WriteLine (_("Usage: sparkleshare [start|stop|restart] [OPTION]..."));
|
||||||
Console.WriteLine (_("Sync SparkleShare folder with remote repositories."));
|
Console.WriteLine (_("Sync SparkleShare folder with remote repositories."));
|
||||||
Console.WriteLine (" ");
|
Console.WriteLine (" ");
|
||||||
Console.WriteLine (_("Arguments:"));
|
Console.WriteLine (_("Arguments:"));
|
||||||
Console.WriteLine (_("\t -d, --disable-gui\tDon't show the notification icon."));
|
Console.WriteLine (_("\t -d, --disable-gui\tDon't show the notification icon."));
|
||||||
Console.WriteLine (_("\t -h, --help\t\tDisplay this help text."));
|
Console.WriteLine (_("\t -h, --help\t\tShow this help text."));
|
||||||
|
Console.WriteLine (_("\t -v, --version\t\tPrint version information."));
|
||||||
Console.WriteLine (" ");
|
Console.WriteLine (" ");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Prints the version information
|
||||||
|
public static void PrintVersion ()
|
||||||
|
{
|
||||||
|
|
||||||
|
Console.WriteLine (_("SparkleShare " + Defines.VERSION));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,14 @@ namespace SparkleShare {
|
||||||
|
|
||||||
public int SyncingReposCount;
|
public int SyncingReposCount;
|
||||||
|
|
||||||
private Timer Timer;
|
|
||||||
private Menu Menu;
|
private Menu Menu;
|
||||||
private MenuItem StatusMenuItem;
|
private MenuItem StatusMenuItem;
|
||||||
private string StateText;
|
private string StateText;
|
||||||
|
|
||||||
|
private Timer Timer;
|
||||||
private Gdk.Pixbuf [] AnimationFrames;
|
private Gdk.Pixbuf [] AnimationFrames;
|
||||||
private int FrameNumber;
|
private int FrameNumber;
|
||||||
|
|
||||||
private Gtk.Action FolderAction;
|
private Gtk.Action FolderAction;
|
||||||
private double FolderSize;
|
private double FolderSize;
|
||||||
|
|
||||||
|
@ -50,8 +52,9 @@ namespace SparkleShare {
|
||||||
|
|
||||||
FolderSize = GetFolderSize (new DirectoryInfo (SparklePaths.SparklePath));
|
FolderSize = GetFolderSize (new DirectoryInfo (SparklePaths.SparklePath));
|
||||||
|
|
||||||
CreateAnimationFrames ();
|
FrameNumber = 0;
|
||||||
CreateTimer ();
|
AnimationFrames = CreateAnimationFrames ();
|
||||||
|
Timer = CreateTimer ();
|
||||||
|
|
||||||
SyncingReposCount = 0;
|
SyncingReposCount = 0;
|
||||||
|
|
||||||
|
@ -59,37 +62,42 @@ namespace SparkleShare {
|
||||||
StatusMenuItem = new MenuItem ();
|
StatusMenuItem = new MenuItem ();
|
||||||
|
|
||||||
CreateMenu ();
|
CreateMenu ();
|
||||||
|
|
||||||
|
// Primary mouse button
|
||||||
Activate += ShowMenu;
|
Activate += ShowMenu;
|
||||||
|
|
||||||
|
// Secondary mouse button
|
||||||
|
PopupMenu += ShowMenu;
|
||||||
|
|
||||||
SetIdleState ();
|
SetIdleState ();
|
||||||
ShowState ();
|
ShowState ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void CreateAnimationFrames ()
|
private Gdk.Pixbuf [] CreateAnimationFrames ()
|
||||||
{
|
{
|
||||||
|
|
||||||
FrameNumber = 0;
|
Gdk.Pixbuf [] animation_frames = new Gdk.Pixbuf [5];
|
||||||
|
|
||||||
AnimationFrames = new Gdk.Pixbuf [5];
|
|
||||||
Gdk.Pixbuf frames_pixbuf = SparkleHelpers.GetIcon ("process-syncing-sparkleshare", 24);
|
Gdk.Pixbuf frames_pixbuf = SparkleHelpers.GetIcon ("process-syncing-sparkleshare", 24);
|
||||||
|
|
||||||
for (int i = 0; i < AnimationFrames.Length; i++)
|
for (int i = 0; i < animation_frames.Length; i++)
|
||||||
AnimationFrames [i] = new Gdk.Pixbuf (frames_pixbuf, (i * 24), 0, 24, 24);
|
animation_frames [i] = new Gdk.Pixbuf (frames_pixbuf, (i * 24), 0, 24, 24);
|
||||||
|
|
||||||
|
return animation_frames;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Creates the timer that handles the syncing animation
|
// Creates the timer that handles the syncing animation
|
||||||
private void CreateTimer ()
|
private Timer CreateTimer ()
|
||||||
{
|
{
|
||||||
|
|
||||||
Timer = new Timer () {
|
Timer timer = new Timer () {
|
||||||
Interval = 35
|
Interval = 35
|
||||||
};
|
};
|
||||||
|
|
||||||
Timer.Elapsed += delegate {
|
timer.Elapsed += delegate {
|
||||||
|
|
||||||
if (FrameNumber < AnimationFrames.Length - 1)
|
if (FrameNumber < AnimationFrames.Length - 1)
|
||||||
FrameNumber++;
|
FrameNumber++;
|
||||||
|
@ -100,6 +108,8 @@ namespace SparkleShare {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,8 +118,8 @@ namespace SparkleShare {
|
||||||
|
|
||||||
return delegate {
|
return delegate {
|
||||||
|
|
||||||
SparkleWindow SparkleWindow = new SparkleWindow (repo);
|
SparkleLog log = new SparkleLog (repo);
|
||||||
SparkleWindow.ShowAll ();
|
log.ShowAll ();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,11 +131,18 @@ namespace SparkleShare {
|
||||||
|
|
||||||
double size = 0;
|
double size = 0;
|
||||||
|
|
||||||
FileInfo [] files = parent.GetFiles();
|
if (parent.Name.Equals ("rebase-apply"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
foreach (FileInfo file in parent.GetFiles()) {
|
||||||
|
|
||||||
|
if (!file.Exists)
|
||||||
|
return 0;
|
||||||
|
|
||||||
foreach (FileInfo file in files)
|
|
||||||
size += file.Length;
|
size += file.Length;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
foreach (DirectoryInfo directory in parent.GetDirectories())
|
foreach (DirectoryInfo directory in parent.GetDirectories())
|
||||||
size += GetFolderSize (directory);
|
size += GetFolderSize (directory);
|
||||||
|
|
||||||
|
@ -134,19 +151,29 @@ namespace SparkleShare {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private string GetSizeFormat (double byte_count)
|
private void UpdateFolderSize ()
|
||||||
|
{
|
||||||
|
|
||||||
|
FolderSize = GetFolderSize (new DirectoryInfo (SparklePaths.SparklePath));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Format a file size nicely.
|
||||||
|
// Example: 1048576 becomes "1 ᴍʙ"
|
||||||
|
private string FormatFileSize (double byte_count)
|
||||||
{
|
{
|
||||||
|
|
||||||
string size = "";
|
string size = "";
|
||||||
|
|
||||||
if (byte_count >= 1099511627776)
|
if (byte_count >= 1099511627776)
|
||||||
size = String.Format ("{0:##.##}", Math.Round (byte_count / 1099511627776, 1)) + " ᴛʙ";
|
size = String.Format (_("{0:##.##} ᴛʙ"), Math.Round (byte_count / 1099511627776, 1));
|
||||||
else if (byte_count >= 1073741824)
|
else if (byte_count >= 1073741824)
|
||||||
size = String.Format ("{0:##.##}", Math.Round (byte_count / 1073741824, 1)) + " ɢʙ";
|
size = String.Format (_("{0:##.##} ɢʙ"), Math.Round (byte_count / 1073741824, 1));
|
||||||
else if (byte_count >= 1048576)
|
else if (byte_count >= 1048576)
|
||||||
size = String.Format ("{0:##.##}", Math.Round (byte_count / 1048576, 1)) + " ᴍʙ";
|
size = String.Format (_("{0:##.##} ᴍʙ"), Math.Round (byte_count / 1048576, 1));
|
||||||
else if (byte_count >= 1024)
|
else if (byte_count >= 1024)
|
||||||
size = String.Format ("{0:##.##}", Math.Round (byte_count / 1024, 1)) + " ᴋʙ";
|
size = String.Format (_("{0:##.##} ᴋʙ"), Math.Round (byte_count / 1024, 1));
|
||||||
else
|
else
|
||||||
size = byte_count.ToString () + " bytes";
|
size = byte_count.ToString () + " bytes";
|
||||||
|
|
||||||
|
@ -216,8 +243,7 @@ namespace SparkleShare {
|
||||||
add_item.Activated += delegate {
|
add_item.Activated += delegate {
|
||||||
|
|
||||||
SparkleIntro intro = new SparkleIntro ();
|
SparkleIntro intro = new SparkleIntro ();
|
||||||
intro.ShowStepTwo (true);
|
intro.ShowServerForm (true);
|
||||||
intro.ShowAll ();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -246,7 +272,7 @@ namespace SparkleShare {
|
||||||
|
|
||||||
Menu.Add (new SeparatorMenuItem ());
|
Menu.Add (new SeparatorMenuItem ());
|
||||||
|
|
||||||
MenuItem about_item = new MenuItem (_("About"));
|
MenuItem about_item = new MenuItem (_("Visit Website"));
|
||||||
|
|
||||||
about_item.Activated += delegate {
|
about_item.Activated += delegate {
|
||||||
|
|
||||||
|
@ -295,6 +321,14 @@ namespace SparkleShare {
|
||||||
public void ShowState ()
|
public void ShowState ()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
UpdateFolderSize ();
|
||||||
|
|
||||||
|
if (SyncingReposCount < 0)
|
||||||
|
SyncingReposCount = 0;
|
||||||
|
|
||||||
|
if (SyncingReposCount > SparkleUI.Repositories.Count)
|
||||||
|
SyncingReposCount = SparkleUI.Repositories.Count;
|
||||||
|
|
||||||
if (SyncingReposCount > 0)
|
if (SyncingReposCount > 0)
|
||||||
SetSyncingState ();
|
SetSyncingState ();
|
||||||
else
|
else
|
||||||
|
@ -302,7 +336,7 @@ namespace SparkleShare {
|
||||||
|
|
||||||
UpdateStatusMenuItem ();
|
UpdateStatusMenuItem ();
|
||||||
|
|
||||||
Console.WriteLine ("Number of repos syncing: " + SyncingReposCount);
|
SparkleHelpers.DebugInfo ("Status", "Number of repos syncing: " + SyncingReposCount);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,8 +347,8 @@ namespace SparkleShare {
|
||||||
|
|
||||||
Timer.Stop ();
|
Timer.Stop ();
|
||||||
|
|
||||||
Pixbuf = SparkleHelpers.GetIcon ("folder-sparkleshare", 24);
|
Application.Invoke (delegate { SetPixbuf (AnimationFrames [0]); });
|
||||||
StateText = _("Up to date") + " (" + GetSizeFormat (FolderSize) + ")";
|
StateText = _("Up to date") + " (" + FormatFileSize (FolderSize) + ")";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace SparkleShare {
|
namespace SparkleShare {
|
||||||
|
|
||||||
|
@ -47,6 +49,10 @@ namespace SparkleShare {
|
||||||
BusG.Init ();
|
BusG.Init ();
|
||||||
Gtk.Application.Init ();
|
Gtk.Application.Init ();
|
||||||
|
|
||||||
|
// SparkleInvitation i = new SparkleInvitation ("/home/hbons/SparkleShare/sparkleshare.invitation");
|
||||||
|
|
||||||
|
SetProcessName ("sparkleshare");
|
||||||
|
|
||||||
Repositories = new List <SparkleRepo> ();
|
Repositories = new List <SparkleRepo> ();
|
||||||
|
|
||||||
Process = new Process () {
|
Process = new Process () {
|
||||||
|
@ -75,24 +81,21 @@ namespace SparkleShare {
|
||||||
Filter = "*"
|
Filter = "*"
|
||||||
};
|
};
|
||||||
|
|
||||||
watcher.Deleted += delegate {
|
watcher.Deleted += delegate (object o, FileSystemEventArgs args) {
|
||||||
|
|
||||||
foreach (SparkleRepo repo in Repositories)
|
RemoveRepository (args.FullPath);
|
||||||
repo.Stop ();
|
|
||||||
|
|
||||||
Application.Invoke (delegate { UpdateRepositories (); } );
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
watcher.Created += delegate {
|
watcher.Created += delegate (object o, FileSystemEventArgs args) {
|
||||||
|
|
||||||
Application.Invoke (delegate {UpdateRepositories (); } );
|
AddRepository (args.FullPath);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
CreateConfigurationFolders ();
|
CreateConfigurationFolders ();
|
||||||
UpdateRepositories ();
|
PopulateRepositories ();
|
||||||
|
|
||||||
// Don't create the window and status
|
// Don't create the window and status
|
||||||
// icon when --disable-gui was given
|
// icon when --disable-gui was given
|
||||||
|
@ -109,6 +112,7 @@ namespace SparkleShare {
|
||||||
NotificationIcon = new SparkleStatusIcon ();
|
NotificationIcon = new SparkleStatusIcon ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -323,57 +327,81 @@ namespace SparkleShare {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void AddRepository (string folder_path) {
|
||||||
|
|
||||||
|
// Check if the folder is a git repo
|
||||||
|
if (!Directory.Exists (SparkleHelpers.CombineMore (folder_path, ".git")))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SparkleRepo repo = new SparkleRepo (folder_path);
|
||||||
|
|
||||||
|
repo.NewCommit += delegate (object o, NewCommitArgs args) {
|
||||||
|
Application.Invoke (delegate { ShowNewCommitBubble (args.Author, args.Email, args.Message); });
|
||||||
|
};
|
||||||
|
|
||||||
|
repo.Commited += delegate (object o, SparkleEventArgs args) {
|
||||||
|
Application.Invoke (delegate { CheckForUnicorns (args.Message); });
|
||||||
|
};
|
||||||
|
|
||||||
|
repo.FetchingStarted += delegate {
|
||||||
|
Application.Invoke (UpdateStatusIconToSyncing);
|
||||||
|
};
|
||||||
|
|
||||||
|
repo.FetchingFinished += delegate {
|
||||||
|
Application.Invoke (UpdateStatusIconToIdle);
|
||||||
|
};
|
||||||
|
|
||||||
|
repo.PushingStarted += delegate {
|
||||||
|
Application.Invoke (UpdateStatusIconToSyncing);
|
||||||
|
};
|
||||||
|
|
||||||
|
repo.PushingFinished += delegate {
|
||||||
|
Application.Invoke (UpdateStatusIconToIdle);
|
||||||
|
};
|
||||||
|
|
||||||
|
repo.ConflictDetected += delegate {
|
||||||
|
Application.Invoke (ShowConflictBubble);
|
||||||
|
};
|
||||||
|
|
||||||
|
Repositories.Add (repo);
|
||||||
|
|
||||||
|
if (NotificationIcon != null)
|
||||||
|
Application.Invoke (delegate { NotificationIcon.CreateMenu (); });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RemoveRepository (string folder_path) {
|
||||||
|
|
||||||
|
string repo_name = Path.GetFileName (folder_path);
|
||||||
|
|
||||||
|
foreach (SparkleRepo repo in Repositories) {
|
||||||
|
|
||||||
|
if (repo.Name.Equals (repo_name)) {
|
||||||
|
|
||||||
|
repo.Stop ();
|
||||||
|
Repositories.Remove (repo);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NotificationIcon != null)
|
||||||
|
Application.Invoke (delegate { NotificationIcon.CreateMenu (); });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Updates the list of repositories with all the
|
// Updates the list of repositories with all the
|
||||||
// folders in the SparkleShare folder
|
// folders in the SparkleShare folder
|
||||||
public void UpdateRepositories ()
|
public void PopulateRepositories ()
|
||||||
{
|
{
|
||||||
|
|
||||||
Repositories = new List <SparkleRepo> ();
|
Repositories = new List <SparkleRepo> ();
|
||||||
|
|
||||||
foreach (string folder in Directory.GetDirectories (SparklePaths.SparklePath)) {
|
foreach (string folder_path in Directory.GetDirectories (SparklePaths.SparklePath))
|
||||||
|
AddRepository (folder_path);
|
||||||
// Check if the folder is a git repo
|
|
||||||
if (Directory.Exists (SparkleHelpers.CombineMore (folder, ".git"))) {
|
|
||||||
|
|
||||||
SparkleRepo repo = new SparkleRepo (folder);
|
|
||||||
|
|
||||||
repo.NewCommit += delegate (object o, NewCommitArgs args) {
|
|
||||||
Application.Invoke (delegate { ShowNewCommitBubble (args.Author, args.Email, args.Message); });
|
|
||||||
};
|
|
||||||
|
|
||||||
repo.Commited += delegate (object o, SparkleEventArgs args) {
|
|
||||||
Application.Invoke (delegate { CheckForUnicorns (args.Message); });
|
|
||||||
};
|
|
||||||
|
|
||||||
repo.FetchingStarted += delegate {
|
|
||||||
Application.Invoke (UpdateStatusIconToSyncing);
|
|
||||||
};
|
|
||||||
|
|
||||||
repo.FetchingFinished += delegate {
|
|
||||||
Application.Invoke (UpdateStatusIconToIdle);
|
|
||||||
};
|
|
||||||
|
|
||||||
repo.PushingStarted += delegate {
|
|
||||||
Application.Invoke (UpdateStatusIconToSyncing);
|
|
||||||
};
|
|
||||||
|
|
||||||
repo.PushingFinished += delegate {
|
|
||||||
Application.Invoke (UpdateStatusIconToIdle);
|
|
||||||
};
|
|
||||||
|
|
||||||
repo.ConflictDetected += delegate {
|
|
||||||
Application.Invoke (ShowConflictBubble);
|
|
||||||
};
|
|
||||||
|
|
||||||
Repositories.Add (repo);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the list in the statusicon
|
|
||||||
if (NotificationIcon != null)
|
|
||||||
NotificationIcon.CreateMenu ();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,6 +425,27 @@ namespace SparkleShare {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport ("libc")]
|
||||||
|
private static extern int prctl (int option, byte [] arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5);
|
||||||
|
|
||||||
|
|
||||||
|
private void SetProcessName (string name)
|
||||||
|
{
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (prctl (15, Encoding.ASCII.GetBytes (name + "\0"), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) != 0) {
|
||||||
|
|
||||||
|
throw new ApplicationException ("Error setting process name: " +
|
||||||
|
Mono.Unix.Native.Stdlib.GetLastError ());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (EntryPointNotFoundException) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,262 +28,87 @@ namespace SparkleShare {
|
||||||
|
|
||||||
public class SparkleWindow : Window {
|
public class SparkleWindow : Window {
|
||||||
|
|
||||||
// Short alias for the translations
|
private HBox HBox;
|
||||||
public static string _ (string s)
|
private VBox VBox;
|
||||||
{
|
private VBox Wrapper;
|
||||||
return Catalog.GetString (s);
|
private HButtonBox Buttons;
|
||||||
}
|
|
||||||
|
|
||||||
private SparkleRepo SparkleRepo;
|
|
||||||
private VBox LayoutVertical;
|
|
||||||
private ScrolledWindow ScrolledWindow;
|
|
||||||
|
|
||||||
public SparkleWindow (SparkleRepo sparkle_repo) : base ("")
|
public SparkleWindow () : base ("")
|
||||||
{
|
{
|
||||||
|
|
||||||
SparkleRepo = sparkle_repo;
|
BorderWidth = 0;
|
||||||
SetSizeRequest (540, 640);
|
IconName = "folder-sparkleshare";
|
||||||
SetPosition (WindowPosition.Center);
|
Resizable = true;
|
||||||
BorderWidth = 12;
|
WindowPosition = WindowPosition.Center;
|
||||||
|
|
||||||
// TRANSLATORS: {0} is a folder name, and {1} is a server address
|
SetDefaultSize (640, 480);
|
||||||
Title = String.Format(_("Recent Events in ‘{0}’"), SparkleRepo.Name);
|
|
||||||
IconName = "folder";
|
|
||||||
|
|
||||||
LayoutVertical = new VBox (false, 12);
|
Buttons = CreateButtonBox ();
|
||||||
|
|
||||||
LayoutVertical.PackStart (CreateEventLog (), true, true, 0);
|
HBox = new HBox (false, 6);
|
||||||
|
|
||||||
HButtonBox dialog_buttons = new HButtonBox {
|
string image_path = SparkleHelpers.CombineMore (Defines.PREFIX, "share", "pixmaps", "side-splash.png");
|
||||||
Layout = ButtonBoxStyle.Edge,
|
Image side_splash = new Image (image_path);
|
||||||
BorderWidth = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
Button open_folder_button = new Button (_("Open Folder"));
|
VBox = new VBox (false, 0);
|
||||||
open_folder_button.Clicked += delegate (object o, EventArgs args) {
|
|
||||||
Process process = new Process ();
|
Wrapper = new VBox (false, 0) {
|
||||||
process.StartInfo.FileName = "xdg-open";
|
BorderWidth = 30
|
||||||
string path = SparkleHelpers.CombineMore (SparklePaths.SparklePath,
|
|
||||||
SparkleRepo.Name);
|
|
||||||
process.StartInfo.Arguments = path.Replace(" ", "\\ ");
|
|
||||||
process.Start ();
|
|
||||||
Destroy ();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Button close_button = new Button (Stock.Close);
|
VBox.PackStart (Wrapper, true, true, 0);
|
||||||
close_button.Clicked += delegate (object o, EventArgs args) {
|
VBox.PackStart (Buttons, false, false, 0);
|
||||||
Destroy ();
|
|
||||||
};
|
|
||||||
|
|
||||||
dialog_buttons.Add (open_folder_button);
|
HBox.PackStart (side_splash, false, false, 0);
|
||||||
dialog_buttons.Add (close_button);
|
HBox.PackStart (VBox, true, true, 0);
|
||||||
|
|
||||||
LayoutVertical.PackStart (dialog_buttons, false, false, 0);
|
base.Add (HBox);
|
||||||
|
|
||||||
Add (LayoutVertical);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void UpdateEventLog ()
|
private HButtonBox CreateButtonBox ()
|
||||||
{
|
{
|
||||||
|
|
||||||
LayoutVertical.Remove (ScrolledWindow);
|
return new HButtonBox () {
|
||||||
ScrolledWindow = CreateEventLog ();
|
BorderWidth = 12,
|
||||||
LayoutVertical.PackStart (ScrolledWindow, true, true, 0);
|
Layout = ButtonBoxStyle.End,
|
||||||
LayoutVertical.ReorderChild (ScrolledWindow, 0);
|
Spacing = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void AddButton (Button button)
|
||||||
|
{
|
||||||
|
|
||||||
|
Buttons.Add (button);
|
||||||
ShowAll ();
|
ShowAll ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private ScrolledWindow CreateEventLog ()
|
new public void Add (Widget widget)
|
||||||
{
|
{
|
||||||
|
|
||||||
int number_of_events = 50;
|
Wrapper.PackStart (widget, true, true, 0);
|
||||||
|
ShowAll ();
|
||||||
Process process = new Process ();
|
|
||||||
process.EnableRaisingEvents = true;
|
|
||||||
process.StartInfo.RedirectStandardOutput = true;
|
|
||||||
process.StartInfo.UseShellExecute = false;
|
|
||||||
process.StartInfo.WorkingDirectory = SparkleRepo.LocalPath;
|
|
||||||
process.StartInfo.FileName = "git";
|
|
||||||
process.StartInfo.Arguments = "log --format=\"%at☃%an☃%ae☃%s\" -" + number_of_events;
|
|
||||||
|
|
||||||
process.Start ();
|
|
||||||
|
|
||||||
string output = process.StandardOutput.ReadToEnd ().Trim ();
|
|
||||||
|
|
||||||
output = output.TrimStart ("\n".ToCharArray ());
|
|
||||||
string [] lines = Regex.Split (output, "\n");
|
|
||||||
int linesLength = lines.Length;
|
|
||||||
if (output == "")
|
|
||||||
linesLength = 0;
|
|
||||||
|
|
||||||
// Sort by time and get the last 25
|
|
||||||
Array.Sort (lines);
|
|
||||||
Array.Reverse (lines);
|
|
||||||
|
|
||||||
List <ActivityDay> activity_days = new List <ActivityDay> ();
|
|
||||||
|
|
||||||
for (int i = 0; i < number_of_events && i < linesLength; i++) {
|
|
||||||
|
|
||||||
string line = lines [i];
|
|
||||||
|
|
||||||
// Look for the snowman!
|
|
||||||
string [] parts = Regex.Split (line, "☃");
|
|
||||||
|
|
||||||
int unix_timestamp = int.Parse (parts [0]);
|
|
||||||
string user_name = parts [1];
|
|
||||||
string user_email = parts [2];
|
|
||||||
string message = parts [3];
|
|
||||||
|
|
||||||
DateTime date_time = UnixTimestampToDateTime (unix_timestamp);
|
|
||||||
|
|
||||||
message = message.Replace ("/", " ‣ ");
|
|
||||||
message = message.Replace ("\n", " ");
|
|
||||||
|
|
||||||
ChangeSet change_set = new ChangeSet (user_name, user_email, message, date_time);
|
|
||||||
|
|
||||||
bool change_set_inserted = false;
|
|
||||||
foreach (ActivityDay stored_activity_day in activity_days) {
|
|
||||||
|
|
||||||
if (stored_activity_day.DateTime.Year == change_set.DateTime.Year &&
|
|
||||||
stored_activity_day.DateTime.Month == change_set.DateTime.Month &&
|
|
||||||
stored_activity_day.DateTime.Day == change_set.DateTime.Day) {
|
|
||||||
|
|
||||||
stored_activity_day.Add (change_set);
|
|
||||||
change_set_inserted = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!change_set_inserted) {
|
|
||||||
|
|
||||||
ActivityDay activity_day = new ActivityDay (change_set.DateTime);
|
|
||||||
activity_day.Add (change_set);
|
|
||||||
activity_days.Add (activity_day);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
VBox layout_vertical = new VBox (false, 0);
|
|
||||||
|
|
||||||
foreach (ActivityDay activity_day in activity_days) {
|
|
||||||
|
|
||||||
TreeIter iter = new TreeIter ();
|
|
||||||
ListStore list_store = new ListStore (typeof (Gdk.Pixbuf),
|
|
||||||
typeof (string),
|
|
||||||
typeof (string));
|
|
||||||
|
|
||||||
foreach (ChangeSet change_set in activity_day) {
|
|
||||||
|
|
||||||
iter = list_store.Append ();
|
|
||||||
list_store.SetValue (iter, 0, SparkleHelpers.GetAvatar (change_set.UserEmail , 32));
|
|
||||||
list_store.SetValue (iter, 1, "<b>" + change_set.UserName + "</b>\n" +
|
|
||||||
"<span fgcolor='#777'>" + change_set.Message + "</span>");
|
|
||||||
list_store.SetValue (iter, 2, change_set.UserEmail);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Label date_label = new Label ("") {
|
|
||||||
UseMarkup = true,
|
|
||||||
Xalign = 0,
|
|
||||||
Xpad = 9,
|
|
||||||
Ypad = 9
|
|
||||||
};
|
|
||||||
|
|
||||||
DateTime today = DateTime.Now;
|
|
||||||
DateTime yesterday = DateTime.Now.AddDays (-1);
|
|
||||||
|
|
||||||
if (today.Day == activity_day.DateTime.Day &&
|
|
||||||
today.Month == activity_day.DateTime.Month &&
|
|
||||||
today.Year == activity_day.DateTime.Year) {
|
|
||||||
|
|
||||||
date_label.Markup = "<b>Today</b>";
|
|
||||||
|
|
||||||
} else if (yesterday.Day == activity_day.DateTime.Day &&
|
|
||||||
yesterday.Month == activity_day.DateTime.Month &&
|
|
||||||
yesterday.Year == activity_day.DateTime.Year) {
|
|
||||||
|
|
||||||
date_label.Markup = "<b>Yesterday</b>";
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
date_label.Markup = "<b>" + activity_day.DateTime.ToString ("ddd MMM d, yyyy") + "</b>";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
layout_vertical.PackStart (date_label, false, false, 0);
|
|
||||||
|
|
||||||
IconView icon_view = new IconView (list_store) {
|
|
||||||
ItemWidth = 470,
|
|
||||||
MarkupColumn = 1,
|
|
||||||
Orientation = Orientation.Horizontal,
|
|
||||||
PixbufColumn = 0,
|
|
||||||
Spacing = 9
|
|
||||||
};
|
|
||||||
|
|
||||||
icon_view.SelectionChanged += delegate {
|
|
||||||
icon_view.UnselectAll ();
|
|
||||||
};
|
|
||||||
|
|
||||||
layout_vertical.PackStart (icon_view, false, false, 0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ScrolledWindow = new ScrolledWindow ();
|
|
||||||
ScrolledWindow.ShadowType = ShadowType.None;
|
|
||||||
ScrolledWindow.AddWithViewport (layout_vertical);
|
|
||||||
|
|
||||||
return ScrolledWindow;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Converts a UNIX timestamp to a more usable time object
|
public void Reset ()
|
||||||
public DateTime UnixTimestampToDateTime (int timestamp)
|
|
||||||
{
|
{
|
||||||
DateTime unix_epoch = new DateTime (1970, 1, 1, 0, 0, 0, 0);
|
|
||||||
return unix_epoch.AddSeconds (timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (Wrapper.Children.Length > 0)
|
||||||
|
Wrapper.Remove (Wrapper.Children [0]);
|
||||||
|
|
||||||
}
|
foreach (Button button in Buttons)
|
||||||
|
Buttons.Remove (button);
|
||||||
|
|
||||||
|
ShowAll ();
|
||||||
|
|
||||||
public class ActivityDay : List <ChangeSet>
|
|
||||||
{
|
|
||||||
|
|
||||||
public DateTime DateTime;
|
|
||||||
|
|
||||||
public ActivityDay (DateTime date_time)
|
|
||||||
{
|
|
||||||
DateTime = date_time;
|
|
||||||
DateTime = new DateTime (DateTime.Year, DateTime.Month, DateTime.Day);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public class ChangeSet
|
|
||||||
{
|
|
||||||
|
|
||||||
public string UserName;
|
|
||||||
public string UserEmail;
|
|
||||||
public string Message;
|
|
||||||
public DateTime DateTime;
|
|
||||||
|
|
||||||
public ChangeSet (string user_name, string user_email, string message, DateTime date_time)
|
|
||||||
{
|
|
||||||
UserName = user_name;
|
|
||||||
UserEmail = user_email;
|
|
||||||
Message = message;
|
|
||||||
DateTime = date_time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,69 +2,59 @@
|
||||||
|
|
||||||
pidfile=/tmp/sparkleshare/sparkleshare.pid
|
pidfile=/tmp/sparkleshare/sparkleshare.pid
|
||||||
|
|
||||||
# Create a directory to save the pid to
|
start() {
|
||||||
|
if [ -e "${pidfile}" ]; then
|
||||||
|
sparklepid=`cat ${pidfile}`
|
||||||
|
if [ -n "`ps -p ${sparklepid} | grep ${sparklepid}`" ]; then
|
||||||
|
echo "SparkleShare is already running."
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "SparkleShare stale pid file found, starting a new instance."
|
||||||
|
rm -f $pidfile
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -n "Starting SparkleShare... "
|
||||||
|
mkdir -p /tmp/sparkleshare/
|
||||||
|
# Start SparkleShare in the background and save the pid
|
||||||
|
mono "@expanded_libdir@/@PACKAGE@/SparkleShare.exe" $2 &
|
||||||
|
echo $! > ${pidfile}
|
||||||
|
echo "Done."
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
if [ -e "${pidfile}" ]; then
|
||||||
|
sparklepid=`cat ${pidfile}`
|
||||||
|
if [ -n "`ps -p ${sparklepid} | grep ${sparklepid}`" ]; then
|
||||||
|
echo -n "Stopping SparkleShare... "
|
||||||
|
kill ${sparklepid}
|
||||||
|
rm -f ${pidfile}
|
||||||
|
echo "Done."
|
||||||
|
else
|
||||||
|
echo "SparkleShare is not running, removing stale pid file."
|
||||||
|
rm -f ${pidfile}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "SparkleShare is not running."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
case $1 in
|
case $1 in
|
||||||
start)
|
start|--start)
|
||||||
if [ -e "${pidfile}" ]; then
|
start
|
||||||
sparklepid=`cat ${pidfile}`
|
;;
|
||||||
if [ -n "`ps -p ${sparklepid} | grep ${sparklepid}`" ]
|
stop|--stop)
|
||||||
then
|
stop
|
||||||
echo "SparkleShare is already running"
|
;;
|
||||||
exit 0
|
restart|--restart)
|
||||||
else
|
stop
|
||||||
echo "SparkleShare stale pid file found, starting a new instance"
|
start
|
||||||
rm -f $pidfile
|
;;
|
||||||
fi
|
help|--help)
|
||||||
fi
|
mono "@expanded_libdir@/@PACKAGE@/SparkleShare.exe" --help
|
||||||
|
;;
|
||||||
echo -n "Starting SparkleShare..."
|
|
||||||
mkdir -p /tmp/sparkleshare/
|
|
||||||
# Start SparkleShare in the background and save the pid
|
|
||||||
mono "@expanded_libdir@/@PACKAGE@/SparkleShare.exe" $2 &
|
|
||||||
PID=$!
|
|
||||||
echo $PID > /tmp/sparkleshare/sparkleshare.pid
|
|
||||||
echo " Done."
|
|
||||||
;;
|
|
||||||
|
|
||||||
stop)
|
|
||||||
if [ -e "/tmp/sparkleshare/sparkleshare.pid" ]; then
|
|
||||||
echo -n "Stopping SparkleShare..."
|
|
||||||
kill `cat /tmp/sparkleshare/sparkleshare.pid`
|
|
||||||
rm -f /tmp/sparkleshare/sparkleshare.pid
|
|
||||||
echo " Done."
|
|
||||||
else
|
|
||||||
echo "SparkleShare isn't running."
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
restart)
|
|
||||||
if [ -e "/tmp/sparkleshare/sparkleshare.pid" ]; then
|
|
||||||
echo -n "Stopping SparkleShare..."
|
|
||||||
kill `cat /tmp/sparkleshare/sparkleshare.pid`
|
|
||||||
rm -f /tmp/sparkleshare/sparkleshare.pid
|
|
||||||
echo " Done."
|
|
||||||
else
|
|
||||||
echo "SparkleShare isn't running."
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -e "/tmp/sparkleshare/sparkleshare.pid" ]; then
|
|
||||||
echo "SparkleShare is already running."
|
|
||||||
else
|
|
||||||
echo -n "Starting SparkleShare..."
|
|
||||||
|
|
||||||
# Start SparkleShare in the background and save the pid
|
|
||||||
mono "@expanded_libdir@/@PACKAGE@/SparkleShare.exe" $2 &
|
|
||||||
PID=$!
|
|
||||||
echo $PID > /tmp/sparkleshare/sparkleshare.pid
|
|
||||||
echo " Done."
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
|
|
||||||
--help | help)
|
|
||||||
mono "@expanded_libdir@/@PACKAGE@/SparkleShare.exe" --help
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
*)
|
||||||
echo "Usage: sparkleshare {start|stop|restart|help}"
|
echo "Usage: sparkleshare {start|stop|restart|help}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
7
data/gnome-design.sparkleshare-invitation
Normal file
7
data/gnome-design.sparkleshare-invitation
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<sparkleshare_invitation>
|
||||||
|
<server="git.gnome.org" />
|
||||||
|
<repository="gnome-design" />
|
||||||
|
<key="a22bc6f4b9ffe8e5acd4be0838d41aa10a1187dd" />
|
||||||
|
<email="hylkebons@gmail.com" />
|
||||||
|
</sparkleshare_invitation>
|
6
data/sparkleshare.invitation
Normal file
6
data/sparkleshare.invitation
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<sparkleshare_invitation>
|
||||||
|
<server>git.gnome.org</server>
|
||||||
|
<repository>gnome-design</repository>
|
||||||
|
<key>a22bc6f4b9ffe8e5acd4be0838d41aa10a1187dd</key>
|
||||||
|
</sparkleshare_invitation>
|
Loading…
Reference in a new issue