Merge remote-tracking branch 'upstream/master' into windows
Conflicts: SparkleLib/SparkleHelpers.cs
This commit is contained in:
commit
da5e79f217
1
AUTHORS
1
AUTHORS
|
@ -37,6 +37,7 @@ Contributors:
|
|||
Simon Pither <simon@pither.com>
|
||||
Steven Harms <sharms@ubuntu.com>
|
||||
Sven Mueller <thelightmaker@gmail.com>
|
||||
Travis Glenn Hansen <travisghansen@yahoo.com>
|
||||
Vincent Untz <vuntz@gnome.org>
|
||||
Will Thompson <will@willthompson.co.uk>
|
||||
|
||||
|
|
2
README
2
README
|
@ -88,7 +88,7 @@ Just double-click the SparkleShare bundle.
|
|||
|
||||
# Build on Mac
|
||||
|
||||
Install the Mono Framework, MonoDevelop and the MonoMac plugin (you find it in Add-in Manager).
|
||||
Install Xcode, the Mono Framework, MonoDevelop and the MonoMac plugin (you find it in Add-in Manager).
|
||||
|
||||
You may need to adjust some environment variables to let the build environment tools find mono:
|
||||
|
||||
|
|
|
@ -226,6 +226,24 @@ namespace SparkleLib {
|
|||
writer.WriteLine ("Thumbs.db");
|
||||
writer.WriteLine ("Desktop.ini");
|
||||
|
||||
// MS Office
|
||||
writer.WriteLine ("~*.tmp");
|
||||
writer.WriteLine ("~*.TMP");
|
||||
writer.WriteLine ("*~*.tmp");
|
||||
writer.WriteLine ("*~*.TMP");
|
||||
writer.WriteLine ("~*.ppt");
|
||||
writer.WriteLine ("~*.pptx");
|
||||
writer.WriteLine ("~*.PPT");
|
||||
writer.WriteLine ("~*.PPTX");
|
||||
writer.WriteLine ("~*.xls");
|
||||
writer.WriteLine ("~*.xlsx");
|
||||
writer.WriteLine ("~*.XLS");
|
||||
writer.WriteLine ("~*.XLSX");
|
||||
writer.WriteLine ("~*.doc");
|
||||
writer.WriteLine ("~*.docx");
|
||||
writer.WriteLine ("~*.DOC");
|
||||
writer.WriteLine ("~*.DOCX");
|
||||
|
||||
// CVS
|
||||
writer.WriteLine ("*/CVS/*");
|
||||
writer.WriteLine (".cvsignore");
|
||||
|
|
|
@ -70,15 +70,16 @@ namespace SparkleLib {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if a file is a symbolic link
|
||||
public static bool IsSymlink (string file)
|
||||
{
|
||||
FileAttributes attr = File.GetAttributes (file);
|
||||
|
||||
return ((attr & FileAttributes.ReparsePoint) ==
|
||||
FileAttributes.ReparsePoint);
|
||||
return ((attr & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint);
|
||||
}
|
||||
|
||||
|
||||
// Converts a UNIX timestamp to a more usable time object
|
||||
public static DateTime UnixTimestampToDateTime (int timestamp)
|
||||
{
|
||||
|
@ -86,9 +87,12 @@ namespace SparkleLib {
|
|||
return unix_epoch.AddSeconds (timestamp);
|
||||
}
|
||||
|
||||
// Gets the relative path of two hirarchical absolute paths
|
||||
public static string DiffPaths(string target, string source) {
|
||||
return target.Replace(source + Path.DirectorySeparatorChar, "");
|
||||
|
||||
// Gets the relative path of two hierarchical absolute paths
|
||||
public static string DiffPaths (string target, string source)
|
||||
{
|
||||
return target.Replace (source + Path.DirectorySeparatorChar, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,9 +49,8 @@ namespace SparkleLib {
|
|||
|
||||
// Option to allow access to channel when no password is defined
|
||||
try {
|
||||
this.allow_passwordless_join = Convert.ToBoolean (
|
||||
SparkleConfig.DefaultConfig.GetConfigOption ("allow_passwordless_join"));
|
||||
|
||||
string option = SparkleConfig.DefaultConfig.GetConfigOption ("allow_passwordless_join");
|
||||
this.allow_passwordless_join = (option == null || Convert.ToBoolean (option));
|
||||
} catch (Exception) {
|
||||
this.allow_passwordless_join = true;
|
||||
}
|
||||
|
@ -136,11 +135,14 @@ namespace SparkleLib {
|
|||
|
||||
} else {
|
||||
if (this.allow_passwordless_join) {
|
||||
SparkleHelpers.DebugInfo ("ListenerIrc", "Accessing a dangerous channel, change the setting to not access");
|
||||
SparkleHelpers.DebugInfo ("ListenerIrc", "Accessing unprotected channel, change the setting to not access");
|
||||
this.client.RfcJoin (channel);
|
||||
|
||||
} else {
|
||||
SparkleHelpers.DebugInfo ("ListenerIrc", "Dangerous channel, change the setting to access");
|
||||
SparkleHelpers.DebugInfo ("ListenerIrc", "Unprotected channel, change the setting to access");
|
||||
base.is_connecting = false;
|
||||
OnDisconnected ();
|
||||
throw new ConnectionException ("Unprotected channel, change the setting to access");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -51,14 +51,34 @@ namespace SparkleShare {
|
|||
if (image_path != null && File.Exists (image_path)) {
|
||||
NSData image_data = NSData.FromFile (image_path);
|
||||
GrowlApplicationBridge.Notify (title, subtext,
|
||||
"Event", image_data, 0, false, null);
|
||||
"Event", image_data, 0, false, new NSString (""));
|
||||
|
||||
} else {
|
||||
GrowlApplicationBridge.Notify (title, subtext,
|
||||
"Event", null, 0, false, null);
|
||||
"Event", null, 0, false, new NSString (""));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SparkleGrowlDelegate : GrowlDelegate {
|
||||
|
||||
[Export("growlNotificationWasClicked")]
|
||||
public override void GrowlNotificationWasClicked (NSObject o)
|
||||
{
|
||||
InvokeOnMainThread (delegate {
|
||||
NSApplication.SharedApplication.ActivateIgnoringOtherApps (true);
|
||||
|
||||
if (SparkleUI.EventLog == null)
|
||||
SparkleUI.EventLog = new SparkleEventLog ();
|
||||
|
||||
SparkleUI.EventLog.Controller.SelectedFolder = null;
|
||||
|
||||
SparkleUI.EventLog.OrderFrontRegardless ();
|
||||
SparkleUI.EventLog.MakeKeyAndOrderFront (this);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace SparkleShare {
|
|||
|
||||
public class SparkleEventLog : NSWindow {
|
||||
|
||||
private SparkleEventLogController controller = new SparkleEventLogController ();
|
||||
public SparkleEventLogController Controller = new SparkleEventLogController ();
|
||||
|
||||
private WebView web_view = new WebView (new RectangleF (0, 0, 480, 579), "", "") {
|
||||
PolicyDelegate = new SparkleWebPolicyDelegate ()
|
||||
|
@ -83,19 +83,19 @@ namespace SparkleShare {
|
|||
|
||||
|
||||
// Hook up the controller events
|
||||
this.controller.UpdateChooserEvent += delegate (string [] folders) {
|
||||
Controller.UpdateChooserEvent += delegate (string [] folders) {
|
||||
InvokeOnMainThread (delegate {
|
||||
UpdateChooser (folders);
|
||||
});
|
||||
};
|
||||
|
||||
this.controller.UpdateContentEvent += delegate (string html) {
|
||||
Controller.UpdateContentEvent += delegate (string html) {
|
||||
InvokeOnMainThread (delegate {
|
||||
UpdateContent (html);
|
||||
});
|
||||
};
|
||||
|
||||
this.controller.ContentLoadingEvent += delegate {
|
||||
Controller.ContentLoadingEvent += delegate {
|
||||
InvokeOnMainThread (delegate {
|
||||
if (this.web_view.Superview == ContentView)
|
||||
this.web_view.RemoveFromSuperview ();
|
||||
|
@ -109,7 +109,7 @@ namespace SparkleShare {
|
|||
public void UpdateChooser (string [] folders)
|
||||
{
|
||||
if (folders == null)
|
||||
folders = this.controller.Folders;
|
||||
folders = Controller.Folders;
|
||||
|
||||
if (this.popup_button != null)
|
||||
this.popup_button.RemoveFromSuperview ();
|
||||
|
@ -129,9 +129,9 @@ namespace SparkleShare {
|
|||
|
||||
this.popup_button.Activated += delegate {
|
||||
if (this.popup_button.IndexOfSelectedItem == 0)
|
||||
this.controller.SelectedFolder = null;
|
||||
Controller.SelectedFolder = null;
|
||||
else
|
||||
this.controller.SelectedFolder = this.popup_button.SelectedItem.Title;
|
||||
Controller.SelectedFolder = this.popup_button.SelectedItem.Title;
|
||||
};
|
||||
|
||||
ContentView.AddSubview (this.popup_button);
|
||||
|
@ -143,7 +143,7 @@ namespace SparkleShare {
|
|||
using (NSAutoreleasePool pool = new NSAutoreleasePool ()) {
|
||||
Thread thread = new Thread (new ThreadStart (delegate {
|
||||
if (html == null)
|
||||
html = this.controller.HTML;
|
||||
html = Controller.HTML;
|
||||
|
||||
html = html.Replace ("<!-- $body-font-family -->", "Lucida Grande");
|
||||
html = html.Replace ("<!-- $day-entry-header-font-size -->", "13.6px");
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace SparkleShare {
|
|||
|
||||
// Needed for Growl
|
||||
GrowlApplicationBridge.WeakDelegate = this;
|
||||
GrowlApplicationBridge.Delegate = new SparkleGrowlDelegate ();
|
||||
|
||||
NSApplication.SharedApplication.ApplicationIconImage
|
||||
= NSImage.ImageNamed ("sparkleshare.icns");
|
||||
|
|
|
@ -38,11 +38,9 @@ SOURCES = \
|
|||
SparkleEntry.cs \
|
||||
SparkleEventLog.cs \
|
||||
SparkleEventLogController.cs \
|
||||
SparkleLinController.cs \
|
||||
SparkleSetup.cs \
|
||||
SparkleSetupController.cs \
|
||||
SparkleSetupWindow.cs \
|
||||
Program.cs \
|
||||
SparkleSpinner.cs \
|
||||
SparkleStatusIcon.cs \
|
||||
SparkleStatusIconController.cs \
|
||||
|
|
199
SparkleShare/Nautilus/sparkleshare-nautilus3-extension.py
Executable file
199
SparkleShare/Nautilus/sparkleshare-nautilus3-extension.py
Executable file
|
@ -0,0 +1,199 @@
|
|||
# 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/>.
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
import urllib
|
||||
|
||||
# http://projects.gnome.org/nautilus-python/documentation/html/
|
||||
from gi.repository import Nautilus, GObject, Gtk, Gdk
|
||||
|
||||
SPARKLESHARE_PATH = os.path.join (os.path.expanduser ('~'), "SparkleShare")
|
||||
|
||||
import gettext
|
||||
gettext.bindtextdomain('sparkleshare', '/usr/share/locale')
|
||||
gettext.textdomain('sparkleshare')
|
||||
_ = gettext.gettext
|
||||
|
||||
class SparkleShareExtension (GObject.GObject, Nautilus.MenuProvider):
|
||||
|
||||
|
||||
def __init__ (self):
|
||||
pass
|
||||
|
||||
def checkout_version (self, menu, file_path, commit_hash, username, timestamp):
|
||||
|
||||
file_name = os.path.basename (file_path)
|
||||
tmp_file_path = os.path.join (SPARKLESHARE_PATH, ".tmp", file_name)
|
||||
|
||||
# Move the current version to a temporary path
|
||||
shutil.move (file_path, tmp_file_path)
|
||||
|
||||
# Check out the earlier version
|
||||
os.chdir (os.path.dirname (file_path))
|
||||
os.popen ("git checkout " + commit_hash + " '" + file_name + "'")
|
||||
|
||||
new_tmp_file_name = file_name + " (" + username + ", "
|
||||
new_tmp_file_name += time.strftime ("%H:%M %d %b %Y", timestamp).replace (" 0", " ") + ") "
|
||||
|
||||
# Rename the checked out file
|
||||
shutil.move (file_name, new_tmp_file_name)
|
||||
|
||||
# Move the original file back
|
||||
shutil.move (tmp_file_path, file_path)
|
||||
|
||||
return True
|
||||
|
||||
def format_web_link (self, path):
|
||||
# Get the remote url used for the repo
|
||||
self.chdir_to_repo_base(path)
|
||||
url_command = os.popen ("git config --get remote.origin.url")
|
||||
origin_url = url_command.readline ().strip ()
|
||||
if not origin_url:
|
||||
return
|
||||
|
||||
# Get components
|
||||
# TODO use regex here or something not so ugly
|
||||
protocol, remaining = origin_url.split ("://", 1)
|
||||
host, origin_path = remaining.split("@")[1].split("/", 1);
|
||||
# Format the right web url depending on the service
|
||||
repo_base = self.get_repo_base_path(path)
|
||||
relative_path = path.split(repo_base, 1)[1].lstrip("/")
|
||||
|
||||
#url = url.rstrip (".git")
|
||||
if "gitorious.org" in host:
|
||||
# ssh://git@gitorious.org/gnome-design/gnome-design.git
|
||||
# http://gitorious.org/gnome-design/gnome-design/blobs/raw/master/COPYING
|
||||
url = "http://" + host + "/" + urllib.quote(origin_path.rstrip(".git")) + "/blobs/master/" + urllib.quote(relative_path)
|
||||
elif "github.com" in host:
|
||||
# ssh://git@github.com/hbons/SparkleShare.git
|
||||
# https://raw.github.com/hbons/SparkleShare/master/README
|
||||
url = "http://raw.github.com/" + urllib.quote(origin_path.rstrip(".git")) + "/raw/master/" + urllib.quote(relative_path)
|
||||
else:
|
||||
# https://git.one-gear.com/?p=thansen/Public.git;a=blob;f=SparkleShare.txt;hb=HEAD
|
||||
url = "http://" + host + "/?p=" + urllib.quote(origin_path) +";a=blob;f=" + urllib.quote(relative_path) + ";hb=HEAD"
|
||||
|
||||
return url
|
||||
|
||||
def copy_web_link (self, menu, path):
|
||||
url = self.format_web_link(path)
|
||||
clipboard = Gtk.Clipboard.get (Gdk.Atom.intern ("CLIPBOARD", False))
|
||||
clipboard.set_text (url, -1)
|
||||
clipboard.store ()
|
||||
|
||||
return
|
||||
|
||||
def chdir_to_repo_base(self, file_path):
|
||||
base_path = self.get_repo_base_path(file_path)
|
||||
os.chdir(base_path)
|
||||
|
||||
def get_repo_base_path(self, path):
|
||||
path = os.path.abspath(path)
|
||||
parts = path.split(SPARKLESHARE_PATH, 1)[1].split("/")
|
||||
if len(parts) > 1:
|
||||
sub_folder = parts[1]
|
||||
else:
|
||||
sub_folder = parts[0]
|
||||
return SPARKLESHARE_PATH + "/" + sub_folder
|
||||
|
||||
def get_file_items (self, window, files):
|
||||
|
||||
# Only work if one file is selected
|
||||
if len (files) != 1:
|
||||
return
|
||||
|
||||
file_reference = files [0]
|
||||
|
||||
# Only work if we're in a SparkleShare repository folder
|
||||
if file_reference.is_directory ():
|
||||
return
|
||||
if not (file_reference.get_parent_uri ().startswith ('file://' + SPARKLESHARE_PATH)):
|
||||
return
|
||||
if file_reference.get_parent_uri () == 'file://' + SPARKLESHARE_PATH:
|
||||
return
|
||||
|
||||
file_path = urllib.unquote ('/' + file_reference.get_uri ().lstrip('file:/'))
|
||||
url = self.format_web_link (file_path)
|
||||
parent_path = os.path.dirname (os.path.abspath (file_path))
|
||||
|
||||
top_menuitem = Nautilus.MenuItem (name="Nautilus::SparkleShare",
|
||||
label="SparkleShare")
|
||||
|
||||
top_submenu = Nautilus.Menu ()
|
||||
top_menuitem.set_submenu (top_submenu)
|
||||
|
||||
web_link_menu_item_copy = Nautilus.MenuItem (name="Nautilus::CopyWebLink",
|
||||
label=_("Copy Web Link"),
|
||||
tip=_("Copy the web address of this file to the clipboard"))
|
||||
|
||||
web_link_menu_item_copy.connect ("activate", self.copy_web_link, file_path)
|
||||
|
||||
|
||||
epochs = ["", "", "", "", "", "", "", "", "", ""]
|
||||
commit_hashes = ["", "", "", "", "", "", "", "", "", ""]
|
||||
|
||||
|
||||
time_command = os.popen ("git log -10 --format='%at' '" + file_path + "'")
|
||||
|
||||
author_command = os.popen ("git log -10 --format='%an' '" + file_path + "'")
|
||||
|
||||
hash_command = os.popen ("git log -10 --format='%H' '" + file_path + "'")
|
||||
|
||||
i = 0
|
||||
for line in time_command.readlines ():
|
||||
epochs [i] = line.strip ("\n")
|
||||
i += 1
|
||||
|
||||
|
||||
# Only work if there is history
|
||||
if i < 2:
|
||||
top_submenu.append_item (web_link_menu_item_copy)
|
||||
return [top_menuitem]
|
||||
|
||||
i = 0
|
||||
for line in hash_command.readlines ():
|
||||
commit_hashes [i] = line.strip ("\n")
|
||||
i += 1
|
||||
|
||||
earlier_version_menu_item = Nautilus.MenuItem (name="Nautilus::OpenOlderVersion",
|
||||
label=_("Get Earlier Version"),
|
||||
tip=_("Make a copy of an earlier version in this folder"))
|
||||
version_submenu = Nautilus.Menu ()
|
||||
|
||||
i = 0
|
||||
for line in author_command.readlines ():
|
||||
|
||||
if i > 0:
|
||||
|
||||
timestamp = time.strftime ("%d %b\t%H:%M", time.localtime (float (epochs [i])))
|
||||
username = line.strip ("\n")
|
||||
|
||||
menu_item = Nautilus.MenuItem (name="Nautilus::Version" + epochs [i],
|
||||
label=timestamp + "\t" + username,
|
||||
tip=_("Select to get a copy of this version"))
|
||||
|
||||
menu_item.connect ("activate", self.checkout_version, file_path, commit_hashes [i],
|
||||
username, time.localtime (float (epochs [i])))
|
||||
version_submenu.append_item (menu_item)
|
||||
|
||||
i += 1
|
||||
|
||||
earlier_version_menu_item.set_submenu (version_submenu)
|
||||
top_submenu.append_item (earlier_version_menu_item)
|
||||
top_submenu.append_item (web_link_menu_item_copy)
|
||||
|
||||
return [top_menuitem]
|
|
@ -41,6 +41,18 @@ namespace SparkleShare {
|
|||
else
|
||||
notification.IconName = "folder-sparkleshare";
|
||||
|
||||
notification.Closed += delegate {
|
||||
Application.Invoke (delegate {
|
||||
if (SparkleUI.EventLog == null)
|
||||
SparkleUI.EventLog = new SparkleEventLog ();
|
||||
|
||||
SparkleUI.EventLog.Controller.SelectedFolder = null;
|
||||
|
||||
SparkleUI.EventLog.ShowAll ();
|
||||
SparkleUI.EventLog.Present ();
|
||||
});
|
||||
};
|
||||
|
||||
notification.Show ();
|
||||
|
||||
} catch (Exception) {
|
||||
|
|
4
SparkleShare/SparkleShare.csproj
Executable file → Normal file
4
SparkleShare/SparkleShare.csproj
Executable file → Normal file
|
@ -9,7 +9,6 @@
|
|||
<AssemblyName>SparkleShare</AssemblyName>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<RootNamespace>SparkleShare</RootNamespace>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
|
@ -37,6 +36,9 @@
|
|||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Mono.Posix" />
|
||||
<Reference Include="notify-sharp, Version=0.4.0.0, Culture=neutral, PublicKeyToken=2df29c54e245917a">
|
||||
<Private>False</Private>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ProjectExtensions>
|
||||
<MonoDevelop>
|
||||
|
|
|
@ -88,7 +88,7 @@ dnl package checks, common for all configs
|
|||
SPARKLESHARE_CHECK_GTK_SHARP
|
||||
|
||||
SPARKLESHARE_SMARTIRC4NET
|
||||
PKG_CHECK_MODULES([SMARTIRC4NET], [smartirc4net],
|
||||
PKG_CHECK_MODULES([SMARTIRC4NET], [smartirc4net >= 0.5],
|
||||
SMARTIRC4NET_ASSEMBLY=""
|
||||
AC_SUBST(SMARTIRC4NET_ASSEMBLY)
|
||||
,
|
||||
|
|
Loading…
Reference in a new issue