Merge remote-tracking branch 'upstream/master' into windows

Conflicts:
	SparkleLib/SparkleHelpers.cs
This commit is contained in:
wimh 2011-10-27 19:12:04 +02:00
commit da5e79f217
13 changed files with 283 additions and 26 deletions

View file

@ -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
View file

@ -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:

View file

@ -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");

View file

@ -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, "");
}
}
}

View file

@ -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");
}
}

View file

@ -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);
});
}
}
}

View file

@ -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");

View file

@ -61,6 +61,7 @@ namespace SparkleShare {
// Needed for Growl
GrowlApplicationBridge.WeakDelegate = this;
GrowlApplicationBridge.Delegate = new SparkleGrowlDelegate ();
NSApplication.SharedApplication.ApplicationIconImage
= NSImage.ImageNamed ("sparkleshare.icns");

View file

@ -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 \

View 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]

View file

@ -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
View 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>

View file

@ -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)
,