Merge lp:~dobey/ubuntuone-client/nautilus-no-python into lp:ubuntuone-client

Proposed by dobey
Status: Merged
Approved by: dobey
Approved revision: 49
Merged at revision: not available
Proposed branch: lp:~dobey/ubuntuone-client/nautilus-no-python
Merge into: lp:ubuntuone-client
Diff against target: None lines
To merge this branch: bzr merge lp:~dobey/ubuntuone-client/nautilus-no-python
Reviewer Review Type Date Requested Status
Ken VanDine Approve
Elliot Murphy (community) Approve
Rick McBride (community) Approve
Review via email: mp+7565@code.launchpad.net

Commit message

[r=rmcbride, r=statik] Switch to autotools by default and update packaging for the changes

To post a comment you must log in.
Revision history for this message
dobey (dobey) wrote :

This is a fairly large diff, but I didn't really see any good way to do it in smaller atomic changes. After running ./autogen.sh, doing 'make dist' will give a tarball, which we can use for packaging. The setup.py is generated now (so that we get the same version number in it and the autotools bits), and is very minimal at this point. The rest of the pieces will be moved out as well, at a later time, but for now we need it to run pylint, install the icons, and build u1fsfsm when it needs to be rebuilt. Tests can be run with 'make check', though are disabled during distcheck, because I didn't want to waste time fixing all the tests to load stuff from $(srcdir) properly when $(builddir) is different. The distcheck command also currently fails, because setup.py doesn't have an uninstall command, and we use it to install the icons, so files end up getting left around.

After landing this, I want to tag 0.90.2 for storage-protocol and client both, and get tarballs on our launchpad downloads page, and the 0.90.2 version up on REVU for inclusion in karmic.

Revision history for this message
Rick McBride (rmcbride) wrote :

This looks great!

review: Approve
Revision history for this message
Elliot Murphy (statik) wrote :

I get this error from running ./autogen.sh:

checking for NAUTILUS... configure: error: Package requirements (libnautilus-extension >= 2.6.0 libsoup-2.4 >= 2.3.0) were not met:

Package @GDK_PRIVATE_PACKAGES@ was not found in the pkg-config search path.
Perhaps you should add the directory containing `@GDK_PRIVATE_PACKAGES@.pc'
to the PKG_CONFIG_PATH environment variable
Package '@GDK_PRIVATE_PACKAGES@', required by 'GDK', not found

Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.

Alternatively, you may set the environment variables NAUTILUS_CFLAGS
and NAUTILUS_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.

I have:
libnautilus-extension-dev:
  Installed: 1:2.27.2-0ubuntu1

libsoup2.4-dev:
  Installed: 2.27.1-0ubuntu1

This is with current Karmic.

Revision history for this message
Elliot Murphy (statik) wrote :

Great work. Thanks for suffering all my questions on IRC.

review: Approve
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Please add entries to the changelog for dropping the nautlus-python dep and the deps that have been added. Also include LP bug numbers like (LP: #SOMENUMBER) in the changelog

47. By dobey

 Fix a thinko with creating the protocol symlink

48. By dobey

 Remove dependency on libsoup and code using it
 Update debian/changelog with more info as per Ken's review

49. By dobey

 Rename all to all-local
 Add depenedncy on all-local rule to check rule

Revision history for this message
dobey (dobey) wrote :

> Please add entries to the changelog for dropping the nautlus-python dep and
> the deps that have been added. Also include LP bug numbers like (LP:
> #SOMENUMBER) in the changelog

I've updated changelog as per this comment, and fixed a few other small issues as well. In the interest of getting things done, I'm going to get this landed with Rick and Elliot's prior approvals. If small issues continue to crop up (like test -e failing for you), we can look at those individually and resolve with smaller branches.

Revision history for this message
Ken VanDine (ken-vandine) wrote :

I am having some issues testing it here, but it seems to work for others. The packaging looks good to me, lets send it to REVU. Approved!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file '.bzrignore'
--- .bzrignore 2009-06-03 20:30:50 +0000
+++ .bzrignore 2009-06-17 16:08:17 +0000
@@ -4,13 +4,22 @@
4POTFILES4POTFILES
5build5build
6dist6dist
7m4
8ubuntuone-client-[0-9]+.*
7_trial_temp9_trial_temp
8libtool10libtool
9ltmain.sh11ltmain.sh
12setup.py
10stamp-it13stamp-it
14*.desktop
11*.gmo15*.gmo
16*.icon
12*.la17*.la
13*.lo18*.lo
14*_pb2.py19*_pb2.py
15*.pot20*.pot
16*.pyc21*.pyc
22*.rendercache
23*.service
24.intltool-merge-cache
25
1726
=== modified file 'Makefile.am'
--- Makefile.am 2009-06-03 20:30:50 +0000
+++ Makefile.am 2009-06-17 16:46:42 +0000
@@ -1,15 +1,106 @@
1SUBDIRS = nautilus po1DISTCHECK_CONFIGURE_FLAGS = --disable-rendering
22
3MAINTAINERCLEANFILES = \3SUBDIRS = data nautilus po
4 Makefile.in \4
5 aclocal.m4 \5# Shut libtoolize up
6 config.guess \6ACLOCAL_AMFLAGS = -I m4
7 config.h.in \7
8 config.sub \8# PYTHONPATH for setup.py and stuff
9 configure \9PYTHONPATH="$(top_srcdir):$(top_builddir)"
10 depcomp \10
11 install-sh \11# Python packages we want to install
12 libtool \12pyshareddir = $(datadir)/pyshared
13 ltmain.sh \13pypackages = \
14 missing \14 canonical/ubuntuone/oauthdesktop \
15 canonical/ubuntuone/storage/syncdaemon/fsm \
16 canonical/ubuntuone/storage/syncdaemon \
17 canonical/ubuntuone/storage/u1sync
18
19# Install our scripts and extra data here
20bin_SCRIPTS = \
21 bin/ubuntuone-client-applet \
22 bin/u1sdtool \
23 bin/u1sync
24
25libexec_SCRIPTS = bin/ubuntuone-syncdaemon
26
27manfilesdir = $(mandir)/man1
28manfiles_DATA = \
29 docs/man/ubuntuone-client-applet.1 \
30 docs/man/u1sdtool.1 \
31 docs/man/u1sync.1
32
33apportdir = $(datadir)/apport/package-hooks
34apport_DATA = apport/source_ubuntuone-client.py
35
36# Don't end up pulling in storage-protocol source as well
37pyfiles = $(shell SRCDIR="$(top_srcdir)/canonical"; for i in `find $$SRCDIR -type f`; do printf "$$i "; done)
38
39check: setup.py Makefile
40 if test "x$(builddir)" == "x$(srcdir)"; then \
41 PYTHONPATH="$(PYTHONPATH)" $(PYTHON) setup.py check --config-file=$(top_srcdir)/pylintrc; \
42 PYTHONPATH="$(PYTHONPATH)" $(PYTHON) $(srcdir)/contrib/test; \
43 fi
44 rm -rf _trial_temp
45
46all: all-recursive
47 if test "x$(builddir)" == "x$(srcdir)"; then \
48 if [ ! -e canonical/ubuntuone/storage/protocol ]; then \
49 $(LN_S) $(USP_PATH) canonical/ubuntuone/storage/protocol; \
50 fi; \
51 fi
52
53install-data-local: setup.py
54 for package in $(pypackages); do \
55 $(mkdir_p) $(DESTDIR)$(pyshareddir)/$$package; \
56 for module in $(top_srcdir)/$$package/*.py; do \
57 $(install_sh_DATA) $$module $(DESTDIR)$(pyshareddir)/$$package; \
58 done; \
59 done
60 if test -z "$(DESTDIR)"; then \
61 PYTHONPATH="$(PYTHONPATH)" $(PYTHON) setup.py install --prefix=$(prefix) --no-compile -O0 --install-layout=deb; \
62 else \
63 PYTHONPATH="$(PYTHONPATH)" $(PYTHON) setup.py install --root=$(DESTDIR) --prefix=$(prefix) --no-compile -O0 --install-layout=deb; \
64 fi
65
66uninstall-local:
67 for package in $(pypackages); do \
68 for module in $(top_srcdir)/$$package/*.py; do \
69 modname=`basename $$module`; \
70 rm -f $(DESTDIR)$(pyshareddir)/$$package/$$modname; \
71 done; \
72 rmdir -p --ignore-fail-on-non-empty $(DESTDIR)$(pyshareddir)/$$package; \
73 done
74
75clean-local:
76 PYTHONPATH="$(PYTHONPATH)" $(PYTHON) setup.py clean
77 for i in `find $(builddir) -name "*.pyc"`; do \
78 rm -f $$i; \
79 done
80 rm -f canonical/ubuntuone/storage/protocol
81 rm -rf build dist _trial_temp
82
83EXTRA_DIST = \
84 $(pyfiles) \
85 COPYING.icons \
86 apport \
87 bin \
88 contrib \
89 docs \
90 tests \
91 pylintrc \
92 setup.cfg
93
94MAINTAINERCLEANFILES = \
95 Makefile.in \
96 aclocal.m4 \
97 config.guess \
98 config.h.in \
99 config.sub \
100 configure \
101 depcomp \
102 install-sh \
103 libtool \
104 ltmain.sh \
105 missing \
15 mkinstalldirs106 mkinstalldirs
16107
=== modified file 'autogen.sh'
--- autogen.sh 2009-05-30 12:08:32 +0000
+++ autogen.sh 2009-06-17 16:08:17 +0000
@@ -4,7 +4,7 @@
4srcdir=`dirname $0`4srcdir=`dirname $0`
5test -z "$srcdir" && srcdir=.5test -z "$srcdir" && srcdir=.
66
7PKG_NAME="central-services"7PKG_NAME="ubuntuone-client"
8REQUIRED_AUTOMAKE_VERSION="1.6"8REQUIRED_AUTOMAKE_VERSION="1.6"
99
10(test -f $srcdir/configure.ac) || {10(test -f $srcdir/configure.ac) || {
@@ -14,7 +14,7 @@
14}14}
1515
16which gnome-autogen.sh || {16which gnome-autogen.sh || {
17 echo "You need to install gnome-common from the GNOME CVS"17 echo "You need to install gnome-common from the GNOME source repository"
18 exit 118 exit 1
19}19}
2020
2121
=== removed directory 'canonical/ubuntuone/nautilus'
=== removed file 'canonical/ubuntuone/nautilus/__init__.py'
--- canonical/ubuntuone/nautilus/__init__.py 2009-05-12 13:36:05 +0000
+++ canonical/ubuntuone/nautilus/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,16 +0,0 @@
1# canonical.ubuntuone.nautilus - Ubuntu One integration with Nautilus
2#
3# Copyright 2009 Canonical Ltd.
4#
5# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranties of
11# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12# PURPOSE. See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program. If not, see <http://www.gnu.org/licenses/>.
16"""Ubuntu One Nautilus integration."""
170
=== removed file 'canonical/ubuntuone/nautilus/dummy_nautilus.py'
--- canonical/ubuntuone/nautilus/dummy_nautilus.py 2009-05-12 13:36:05 +0000
+++ canonical/ubuntuone/nautilus/dummy_nautilus.py 1970-01-01 00:00:00 +0000
@@ -1,36 +0,0 @@
1# canonical.ubuntuone.nautilus.dummy_nautilus - stub Nautilus API
2#
3# Author: Tim Cole <tim.cole@canonical.com>
4#
5# Copyright 2009 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18"""Replacement stubs for the Nautilus extension API."""
19
20class LocationWidgetProvider(object):
21 """Stub base class for location widget providers."""
22 pass
23
24
25class InfoProvider(object):
26 """Stub base class for file info providers."""
27 pass
28
29class MenuProvider(object):
30 """Stub base class for menu providers."""
31 pass
32
33
34class MenuItem(object):
35 """Stub base class for menu items."""
36 pass
370
=== removed file 'canonical/ubuntuone/nautilus/nautilus_api.py'
--- canonical/ubuntuone/nautilus/nautilus_api.py 2009-05-12 13:36:05 +0000
+++ canonical/ubuntuone/nautilus/nautilus_api.py 1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
1# canonical.ubuntuone.nautilus.nautilus_api - provide Nautilus API
2#
3# Author: Tim Cole <tim.cole@canonical.com>
4#
5# Copyright 2009 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18"""A wrapper module to conditionally import the Nautilus extension API
19when it is available; otherwise, import stubs for it.
20
21"""
22
23from __future__ import absolute_import
24
25try:
26 # pylint: disable-msg=W0403,W0611,F0401
27 from nautilus import LocationWidgetProvider
28except ImportError:
29 from canonical.ubuntuone.nautilus.dummy_nautilus import \
30 LocationWidgetProvider
31
32
33try:
34 # pylint: disable-msg=W0403,W0611,F0401
35 from nautilus import InfoProvider
36except ImportError:
37 from canonical.ubuntuone.nautilus.dummy_nautilus import InfoProvider
38
39
40try:
41 # pylint: disable-msg=W0403,W0611,F0401
42 from nautilus import MenuProvider
43except ImportError:
44 from canonical.ubuntuone.nautilus.dummy_nautilus import MenuProvider
45
46
47try:
48 # pylint: disable-msg=W0403,W0611,F0401
49 from nautilus import MenuItem
50except ImportError:
51 from canonical.ubuntuone.nautilus.dummy_nautilus import MenuItem
520
=== removed file 'canonical/ubuntuone/nautilus/storage.py'
--- canonical/ubuntuone/nautilus/storage.py 2009-05-18 02:04:33 +0000
+++ canonical/ubuntuone/nautilus/storage.py 1970-01-01 00:00:00 +0000
@@ -1,499 +0,0 @@
1# canonical.ubuntuone.nautilus.storage - storage extension for Nautilus
2#
3# Authors: Tim Cole <tim.cole@canonical.com>
4# Rodney Dawes <rodney.dawes@canonical.com>
5#
6# Copyright 2009 Canonical Ltd.
7#
8# This program is free software: you can redistribute it and/or modify it
9# under the terms of the GNU General Public License version 3, as published
10# by the Free Software Foundation.
11#
12# This program is distributed in the hope that it will be useful, but
13# WITHOUT ANY WARRANTY; without even the implied warranties of
14# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15# PURPOSE. See the GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License along
18# with this program. If not, see <http://www.gnu.org/licenses/>.
19"""Storage extension for Nautilus."""
20
21from __future__ import with_statement
22
23import os
24import gtk
25import gnomekeyring
26from urlparse import urlparse
27from urllib import url2pathname, urlencode
28from urllib2 import urlopen, Request, HTTPError
29from twisted.internet import defer
30from twisted.python import failure
31from threading import Thread
32import canonical.ubuntuone.nautilus.nautilus_api as nautilus
33import dbus.service
34from dbus.exceptions import DBusException
35from dbus.mainloop.glib import DBusGMainLoop
36from gettext import gettext as _
37
38from canonical.ubuntuone.storage.protocol import oauth
39from canonical.ubuntuone.storage.syncdaemon.dbus_interface import (
40 DBUS_IFACE_NAME, DBUS_IFACE_SYNC_NAME, DBUS_IFACE_STATUS_NAME,
41 DBUS_IFACE_SHARES_NAME, DBUS_IFACE_FS_NAME)
42from canonical.ubuntuone.storage.syncdaemon import states
43
44DBusGMainLoop(set_as_default=True)
45
46class StorageBar(gtk.HBox):
47 """The storage bar widget."""
48
49 def __init__(self, path, *args, **kw):
50 """Initialize the widget."""
51 super(StorageBar, self).__init__(*args, **kw)
52 self.__label = gtk.Label()
53 self.__label.set_markup("<b>Ubuntu One</b> " + _("File Sharing"))
54 self.__label.set_alignment(0.0, 0.5)
55 self.__label.show()
56 self.add(self.__label)
57 self.__button = gtk.Button()
58 self.__button.connect("clicked", self.__toggle_state)
59 self.__button.show()
60 self.pack_end(self.__button, expand=False, fill=False)
61 self.__path = path
62 self.__connected = False
63 self.__bus = dbus.SessionBus()
64 self.__update_status({'name':states.INIT.name})
65
66 self.__bus.add_signal_receiver(
67 handler_function=self.__update_status,
68 signal_name="StatusChanged",
69 dbus_interface=DBUS_IFACE_STATUS_NAME)
70
71 # Now get the current status
72 def status_error(error):
73 """Handle status error."""
74 return
75
76 # pylint: disable-msg=W0704
77 try:
78 client = self.__bus.get_object(DBUS_IFACE_NAME, "/status")
79 iface = dbus.Interface(client, DBUS_IFACE_STATUS_NAME)
80 iface.current_status(reply_handler=self.__update_status,
81 error_handler=status_error)
82 except DBusException:
83 pass
84
85
86 def __toggle_state(self, button):
87 """Toggle the connectivity state."""
88 def handler():
89 """Simple handler to make dbus do stuff async."""
90 return
91
92 try:
93 client = self.__bus.get_object(DBUS_IFACE_NAME, "/")
94 iface = dbus.Interface(client, DBUS_IFACE_SYNC_NAME)
95 if self.__connected:
96 iface.disconnect(reply_handler=handler, error_handler=handler)
97 else:
98 iface.connect(reply_handler=handler, error_handler=handler)
99 except DBusException:
100 return
101
102 def __update_status(self, status):
103 """Update the label, and button when connection status changes."""
104 if not status.get('is_online', False) or \
105 not status.get('is_connected', False) or \
106 status['name'].startswith("INIT") or \
107 status['name'].startswith("READY"):
108 self.__button.set_label(_("Connect"))
109 self.__connected = False
110 else:
111 self.__button.set_label(_("Disconnect"))
112 self.__connected = True
113
114
115managed = None
116def is_storagefs(path):
117 """Returns True if the given path is a directory in a mounted
118 storagefs filesystem.
119
120 @param path: the path to test
121 @return: True if the path is a directory in storagefs
122 """
123 # pylint: disable-msg=W0602
124 global managed
125 if not managed:
126 bus = dbus.SessionBus()
127 try:
128 client = bus.get_object(DBUS_IFACE_NAME, "/")
129 iface = dbus.Interface(client, DBUS_IFACE_SYNC_NAME)
130 def got_root(root):
131 """Got the managed root dir."""
132 # pylint: disable-msg=W0603
133 global managed
134 managed = root
135
136 def got_error(error):
137 """Simple handler to make dbus to stuff async."""
138 raise DBusException(error)
139
140 iface.get_rootdir(reply_handler=got_root, error_handler=got_error)
141 except DBusException:
142 return False
143
144 if not managed:
145 return False
146
147 return path == managed or path.startswith(managed + "/")
148
149
150class StorageBarProvider(nautilus.LocationWidgetProvider):
151 """An extension class providing a location widget for storage
152 directories.
153
154 """
155 # pylint: disable-msg=W0231
156 def __init__(self, widget_class=StorageBar,
157 is_storagefs=is_storagefs):
158 """Initializes a new instance of the extension class."""
159 self.__widget_class = widget_class
160 self.__storagefs_test = is_storagefs
161
162 def _get_storage_dir_path(self, url):
163 """Gets the local filesystem path corresponding to the given URL,
164 or otherwise None if it does not refer to a storage directory.
165
166 @param url: the directory URL
167 @return: the local filesystem path, or else None
168
169 """
170 parsed_url = urlparse(url)
171 if parsed_url.scheme == "file" and parsed_url.path:
172 path = url2pathname(parsed_url.path)
173 if self.__storagefs_test(path):
174 return path
175 else:
176 return None
177 else:
178 return None
179
180 def get_widget(self, url, window):
181 """Returns either None or a Gtk widget to decorate the Nautilus
182 window with, based on whether the current directory is a storage
183 directory.
184
185 @param url: the URL of the currently viewed directory
186 @param window: the Nautilus window
187 @return: a Gtk widget or None
188
189 """
190 path = self._get_storage_dir_path(url)
191 if path is not None:
192 widget = self.__widget_class(path=path)
193 widget.show()
194 return widget
195 else:
196 return None
197
198
199class StorageInfoProvider(nautilus.InfoProvider):
200 """An extension class providing info for storage files."""
201
202 # pylint: disable-msg=W0231
203 def __init__(self, *args, **kw):
204 """Initializes the StorageInfoProvider class."""
205 self.__shared = []
206 self.__downloads = []
207 self.__uploads = []
208
209 self.__bus = dbus.SessionBus()
210
211 self.__bus.add_signal_receiver(
212 handler_function=self.__share_created,
213 signal_name="ShareCreated",
214 dbus_interface=DBUS_IFACE_SHARES_NAME)
215
216 self.__bus.add_signal_receiver(
217 handler_function=self.__dl_started,
218 signal_name="DownloadStarted",
219 dbus_interface=DBUS_IFACE_STATUS_NAME)
220 self.__bus.add_signal_receiver(
221 handler_function=self.__dl_finished,
222 signal_name="DownloadFinished",
223 dbus_interface=DBUS_IFACE_STATUS_NAME)
224 self.__bus.add_signal_receiver(
225 handler_function=self.__ul_started,
226 signal_name="UploadStarted",
227 dbus_interface=DBUS_IFACE_STATUS_NAME)
228 self.__bus.add_signal_receiver(
229 handler_function=self.__ul_finished,
230 signal_name="UploadFinished",
231 dbus_interface=DBUS_IFACE_STATUS_NAME)
232
233 def __share_created(self, share):
234 """Share was created, add it to our list"""
235 self.__shares.append(share['path'])
236
237 def __dl_started(self, path):
238 """Download started."""
239 if os.path.isdir(path):
240 self.__downloads.append(path)
241 else:
242 self.__downloads.append(path + ".partial")
243 if not os.path.exists(path + ".partial"):
244 with open(path + ".partial", "w") as f:
245 pass
246 os.utime(path + ".partial", None)
247
248 def __dl_finished(self, path):
249 """Download finished."""
250 if self.__downloads:
251 try:
252 if os.path.isdir(path):
253 self.__downloads.remove(path)
254 else:
255 self.__downloads.remove(path + ".partial")
256 except ValueError:
257 return
258
259 def __ul_started(self, path):
260 """Upload started."""
261 self.__uploads.append(path)
262 os.utime(path, None)
263
264 def __ul_finished(self, path):
265 """Upload finished."""
266 os.utime(path, None)
267 if self.__uploads:
268 try:
269 self.__uploads.remove(path)
270 except ValueError:
271 return
272
273 def update_file_info(self, file):
274 """Returns either None or an int to update the file information.
275
276 @param file: the file to update the status of
277 @return: int or None
278 """
279 path = url2pathname(urlparse(file.get_uri()).path)
280
281 if not is_storagefs(os.path.dirname(path)):
282 return 0
283
284 # We need to get the status from the sync daemon and assign emblems
285 # here, like we used to do for fuse before stuff started crashing :)
286 # We also need some useful pretty emblems to use here
287 def got_error(error):
288 """DBus async error handler."""
289 raise DBusException(error)
290
291 if not self.__shared:
292 try:
293 client = self.__bus.get_object(DBUS_IFACE_NAME, "/shares")
294 iface = dbus.Interface(client, DBUS_IFACE_SHARES_NAME)
295 def got_shared(shared):
296 """Got the managed root dir."""
297 self.__shared = [share['path'] for share in shared]
298
299 iface.get_shared(reply_handler=got_shared,
300 error_handler=got_error)
301 except DBusException:
302 return False
303
304 if path in self.__shared:
305 file.add_emblem("shared")
306
307 if path in self.__downloads:
308 file.add_emblem("ubuntuone-downloading")
309
310 if path in self.__uploads:
311 file.add_emblem("ubuntuone-uploading")
312
313
314class OfferCancelled(Exception):
315 """The cancel button was clicked."""
316 pass
317
318def show_create_share_dialog(folder, window):
319 """Create the share offer dialog and present it to the user."""
320 d = defer.Deferred()
321
322 def create_share(*args, **kwargs):
323 """Create the share."""
324 path = kwargs.get("path", None)
325 user = kwargs.get("user", None)
326 name = kwargs.get("name", None)
327 modify = kwargs.get("modify", False)
328
329 if path == None or user == None or name == None:
330 d.errback(failure.Failure(Exception("Invalid arguments.")))
331 return
332
333 bus = dbus.SessionBus()
334 node = None
335 failed = False
336 try:
337 client = bus.get_object(DBUS_IFACE_NAME, "/filesystem")
338 iface = dbus.Interface(client, DBUS_IFACE_FS_NAME)
339 node = iface.get_metadata(path)["node_id"]
340 except DBusException, e:
341 d.errback(failure.Failure(e))
342 return
343
344 if failed:
345 return
346
347 consumer = oauth.OAuthConsumer("ubuntuone", "hammertime")
348 items = []
349 try:
350 items = gnomekeyring.find_items_sync(
351 gnomekeyring.ITEM_GENERIC_SECRET,
352 {'ubuntuone-realm': "https://ubuntuone.com",
353 'oauth-consumer-key': consumer.key})
354 except (gnomekeyring.NoMatchError,
355 gnomekeyring.DeniedError), e:
356 d.errback(failure.Failure(e))
357 return
358
359 url = "https://ubuntuone.com/files/api/offer_share/"
360 token = oauth.OAuthToken.from_string(items[0].secret)
361 method = oauth.OAuthSignatureMethod_PLAINTEXT()
362 request = oauth.OAuthRequest.from_consumer_and_token(
363 http_url=url,
364 http_method="POST",
365 oauth_consumer=consumer,
366 token=token)
367 request.sign_request(method, consumer, token)
368 data = dict(offer_to_email = user,
369 read_only = modify != True,
370 node_id = node,
371 share_name = name)
372 pdata = urlencode(data)
373 headers = request.to_header()
374 req = Request(url, pdata, headers)
375 try:
376 resp = urlopen(req)
377 d.callback(path)
378 except HTTPError, e:
379 d.errback(failure.Failure(e))
380
381
382 def dialog_response(dialog, response, path,
383 user_entry, name_entry, modify):
384 """Handle the response on the dialog."""
385 if response == gtk.RESPONSE_ACCEPT:
386 create_args = dict(path = path,
387 user = user_entry.get_text(),
388 name = name_entry.get_text(),
389 modify = modify.get_active())
390 Thread(target=create_share, kwargs=create_args).start()
391 else:
392 d.errback(failure.Failure(OfferCancelled()))
393
394 # Always destroy the dialog
395 dialog.destroy()
396
397 dialog = gtk.Dialog(title=_("Share on Ubuntu One"), parent=window,
398 flags=gtk.DIALOG_DESTROY_WITH_PARENT | \
399 gtk.DIALOG_NO_SEPARATOR,
400 buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
401 _("_Share"), gtk.RESPONSE_ACCEPT))
402 dialog.set_default_response(gtk.RESPONSE_ACCEPT)
403 dialog.set_icon_name("ubuntuone-client")
404
405 area = dialog.get_content_area()
406
407 table = gtk.Table(rows=3, columns=2)
408 table.set_row_spacings(12)
409 table.set_col_spacings(6)
410 table.set_border_width(7)
411 table.show()
412 area.add(table)
413
414 label = gtk.Label(_("Share _with (e-mail):"))
415 label.set_alignment(0.0, 0.5)
416 label.set_use_underline(True)
417 table.attach(label, 0, 1, 0, 1)
418 label.show()
419 user_entry = gtk.Entry()
420 label.set_mnemonic_widget(user_entry)
421 table.attach(user_entry, 1, 2, 0, 1)
422 user_entry.show()
423
424 label = gtk.Label(_("Share _Name:"))
425 label.set_alignment(0.0, 0.5)
426 label.set_use_underline(True)
427 table.attach(label, 0, 1, 1, 2)
428 label.show()
429 name_entry = gtk.Entry()
430 label.set_mnemonic_widget(name_entry)
431 name_entry.set_text(os.path.basename(folder))
432 name_entry.set_activates_default(True)
433 table.attach(name_entry, 1, 2, 1, 2)
434 name_entry.show()
435
436 modify = gtk.CheckButton(label=_("_Allow Modification"), use_underline=True)
437 table.attach(modify, 0, 2, 2, 3)
438 modify.show()
439
440 dialog.connect('close', dialog_response, gtk.RESPONSE_CANCEL,
441 folder, user_entry, name_entry, modify)
442 dialog.connect('response', dialog_response,
443 folder, user_entry, name_entry, modify)
444
445 dialog.show()
446
447 return d
448
449class StorageMenuProvider(nautilus.MenuProvider):
450 """An extension class providing menu items for Ubuntu One folders."""
451 # pylint: disable-msg=W0231
452 def __init__(self, *args, **kw):
453 pass
454
455 def __share_succeeded(self, path):
456 """Share offer was successful."""
457 os.utime(path, None)
458
459 def __share_failed(self, error):
460 """Share offer failed."""
461 if isinstance(error, OfferCancelled):
462 return
463 else:
464 # XXX Should notify the user of the problem
465 return
466
467 def __share_folder(self, widget, folder, window):
468 """Share the folder already."""
469 d = show_create_share_dialog(folder, window)
470 d.addCallbacks(self.__share_succeeded, self.__share_failed)
471
472 def get_file_items(self, window, files):
473 """Give ourselves some nice menu items for Ubuntu One."""
474 if len(files) != 1:
475 return
476
477 file = files[0]
478 path = url2pathname(urlparse(file.get_uri()).path)
479
480 if not is_storagefs(os.path.dirname(path)):
481 return
482
483 if path.startswith(os.path.join(managed, "Shared with Me")):
484 return
485
486 if file.is_directory():
487 item = nautilus.MenuItem("ubuntuone-share",
488 _("Share on Ubuntu One"),
489 _("Share this folder on Ubuntu One"),
490 icon="ubuntuone-client")
491 item.connect('activate', self.__share_folder, path, window)
492 return item,
493
494 return
495
496 def get_background_items(self, window, file):
497 """Give ourselves a menu item for Ubuntu One folders."""
498 files = [file]
499 return self.get_file_items(window, files)
5000
=== modified file 'configure.ac'
--- configure.ac 2009-06-14 21:30:07 +0000
+++ configure.ac 2009-06-17 16:08:17 +0000
@@ -10,6 +10,7 @@
10AC_ISC_POSIX10AC_ISC_POSIX
11AC_PROG_CC11AC_PROG_CC
12AC_PROG_LIBTOOL12AC_PROG_LIBTOOL
13PKG_PROG_PKG_CONFIG([0.19])
13IT_PROG_INTLTOOL([0.40.0])14IT_PROG_INTLTOOL([0.40.0])
1415
15GETTEXT_PACKAGE="${PACKAGE}"16GETTEXT_PACKAGE="${PACKAGE}"
@@ -20,6 +21,49 @@
20localedir='${prefix}/${DATADIRNAME}/locale'21localedir='${prefix}/${DATADIRNAME}/locale'
21AC_SUBST(localedir)22AC_SUBST(localedir)
2223
24# Workaround to make aclocal get the right flags
25AC_CONFIG_MACRO_DIR([m4])
26AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS} -I m4")
27
28# Need lndir for builddir != srcdir builds, because Python is not sane
29AC_PATH_PROG([LNDIR], [lndir], [false])
30
31# Icon sizes we want to install
32AC_SUBST([render_sizes], ["16x16 24x24 32x32 48x48"])
33
34# Do we want to enable rendering?
35AC_ARG_ENABLE([rendering],
36 AC_HELP_STRING([--enable-rendering],
37 [Enable icon rendering [default=auto]]),
38 [enable_rendering=$enableval],
39 [enable_rendering=yes])
40
41if test "x$enable_rendering" = "xyes"; then
42 AC_PATH_PROG([ICONTOOL_RENDER], [icontool-render], [false])
43 if test "x$ICONTOOL_RENDER" = "xfalse"; then
44 AC_MSG_WARN([icontool is required to generate icons])
45 enable_rendering=no
46 fi
47fi
48AM_CONDITIONAL(ENABLE_RENDERING, test "x$enable_rendering" = "xyes")
49
50# Check for python 2.5
51AM_PATH_PYTHON([2.5])
52
53# Specify the path for ubuntuone-storage-protocol source
54AC_ARG_WITH([protocol],
55 AC_HELP_STRING([--with-protocol],
56 [Specify path to storage protocol [default=auto]]),
57 [with_protocol=$withval],
58 [with_protocol=auto])
59USP_PATH=""
60if test "x$with_protocol" = "xauto"; then
61 USP_PATH="/usr/share/pyshared"
62fi
63AC_SUBST(USP_PATH)
64AM_CONDITIONAL(USE_PROTOCOL, test "x$with_protocol" != "xno")
65
66# Stuff we need to build the extension shlib
23PKG_CHECK_MODULES(NAUTILUS, [libnautilus-extension >= 2.6.0 libsoup-2.4 >= 2.3.0])67PKG_CHECK_MODULES(NAUTILUS, [libnautilus-extension >= 2.6.0 libsoup-2.4 >= 2.3.0])
24AC_SUBST(NAUTILUS_CFLAGS)68AC_SUBST(NAUTILUS_CFLAGS)
25AC_SUBST(NAUTILUS_LIBS)69AC_SUBST(NAUTILUS_LIBS)
@@ -44,8 +88,10 @@
4488
45AC_CONFIG_FILES([89AC_CONFIG_FILES([
46Makefile90Makefile
91data/Makefile
47nautilus/Makefile92nautilus/Makefile
48po/Makefile.in93po/Makefile.in
94setup.py
49])95])
5096
51AC_OUTPUT97AC_OUTPUT
5298
=== added file 'data/Makefile.am'
--- data/Makefile.am 1970-01-01 00:00:00 +0000
+++ data/Makefile.am 2009-06-17 16:08:17 +0000
@@ -0,0 +1,115 @@
1
2configdir = $(sysconfdir)/xdg/ubuntuone
3config_DATA = oauth_urls syncdaemon.conf
4
5oauthdir = $(configdir)/oauth_registration.d
6oauth_DATA = oauth_registration.d/ubuntuone
7
8desktopdir = $(datadir)/applications
9desktop_in_files = ubuntuone-client-applet.desktop.in
10desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
11
12@INTLTOOL_DESKTOP_RULE@
13
14emblemthemedir = $(datadir)/icons/hicolor
15emblem_in_files = \
16 emblem-ubuntuone-downloading.icon.in \
17 emblem-ubuntuone-unsynchronized.icon.in \
18 emblem-ubuntuone-uploading.icon.in
19emblem_files = $(emblem_in_files:.icon.in=.icon)
20
21%.icon: %.icon.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
22
23servicedir = $(DBUS_SERVICES_DIR)
24service_in_files = \
25 com.ubuntuone.Authentication.service.in \
26 com.ubuntuone.SyncDaemon.service.in
27service_DATA = $(service_in_files:.service.in=.service)
28
29%.service: %.service.in
30 @sed -e "s|\@libexecdir\@|$(libexecdir)|" \
31 -e "s|\@bindir\@|$(bindir)|" $< > $@
32
33icon_in_files = ubuntuone-icons.svg ubuntuone-animations.svg
34icon_cache = $(icon_in_files:.svg=.rendercache)
35icon_files = $(shell BUILDDIR="$(builddir)"; for i in `find $$BUILDDIR -name "*.rendercache"`; do cat $$i|sort|uniq; done)
36
37hicolor:
38 if [ ! -h hicolor -a -d icons ]; then \
39 $(LN_S) icons hicolor; \
40 fi
41
42if ENABLE_RENDERING
43
44%.rendercache: %.svg hicolor
45 for size in $(render_sizes); do \
46 $(ICONTOOL_RENDER) -s $$size -o $(builddir)/icons $< > $@; \
47 done
48
49dist-hook: $(icon_cache)
50 $(mkdir_p) $(distdir)/icons
51 for size in $(render_sizes); do \
52 cp -a $(builddir)/icons/$$size $(distdir)/icons/$$size; \
53 done
54 for i in $(icon_cache); do \
55 touch $(distdir)/$$i; \
56 done
57
58else
59
60%.rendercache: %.svg hicolor
61 if test "x$(builddir)" != "x$(srcdir)" -a ! -f stamp-render; then \
62 $(mkdir_p) $(builddir)/icons; \
63 for size in $(render_sizes); do \
64 cp -a $(srcdir)/icons/$$size icons/$$size; \
65 done; \
66 touch stamp-render; \
67 fi
68
69dist-hook: $(icon_cache)
70 $(mkdir_p) $(distdir)/icons
71 for size in $(render_sizes); do \
72 cp -a $(srcdir)/icons/$$size $(distdir)/icons/$$size; \
73 done
74
75endif
76
77all: $(icon_cache) $(emblem_files)
78$(render_sizes): $(icon_cache)
79
80install-data-local: $(emblem_files)
81 for size in $(render_sizes); do \
82 for file in $(emblem_files); do \
83 $(mkdir_p) $(DESTDIR)$(emblemthemedir)/$$size/emblems; \
84 $(install_sh_DATA) $(builddir)/$$file $(DESTDIR)$(emblemthemedir)/$$size/emblems/$$file; \
85 done; \
86 done
87
88uninstall-local:
89 for size in $(render_sizes); do \
90 for file in $(emblem_files); do \
91 rm -f $(DESTDIR)$(emblemthemedir)/$$size/emblems/$$file; \
92 done; \
93 done
94
95maintainer-clean-local:
96 rm -rf icons
97
98EXTRA_DIST = \
99 $(desktop_in_files) \
100 $(service_in_files) \
101 $(emblem_in_files) \
102 $(icon_in_files) \
103 $(icon_cache) \
104 $(config_DATA) \
105 oauth_registration.d
106
107CLEANFILES = \
108 $(desktop_DATA) \
109 $(service_DATA) \
110 $(emblem_files) \
111 hicolor
112
113MAINTAINERCLEANFILES = \
114 Makefile.in \
115 $(icon_cache)
0116
=== renamed file 'data/com.ubuntuone.Authentication.service' => 'data/com.ubuntuone.Authentication.service.in'
--- data/com.ubuntuone.Authentication.service 2009-05-12 13:36:05 +0000
+++ data/com.ubuntuone.Authentication.service.in 2009-06-17 16:08:17 +0000
@@ -1,3 +1,3 @@
1[D-BUS Service]1[D-BUS Service]
2Name=com.ubuntuone.Authentication2Name=com.ubuntuone.Authentication
3Exec=/usr/bin/ubuntuone-client-applet3Exec=@bindir@/ubuntuone-client-applet
44
=== renamed file 'data/com.ubuntuone.SyncDaemon.service' => 'data/com.ubuntuone.SyncDaemon.service.in'
--- data/com.ubuntuone.SyncDaemon.service 2009-05-12 13:36:05 +0000
+++ data/com.ubuntuone.SyncDaemon.service.in 2009-06-17 16:08:17 +0000
@@ -1,4 +1,4 @@
1[D-BUS Service]1[D-BUS Service]
2Name=com.ubuntuone.SyncDaemon2Name=com.ubuntuone.SyncDaemon
3Exec=/usr/bin/ubuntuone-syncdaemon3Exec=@libexecdir@/ubuntuone-syncdaemon
44
55
=== renamed directory 'oauth_registration.d' => 'data/oauth_registration.d'
=== modified file 'debian/changelog'
--- debian/changelog 2009-05-13 18:19:40 +0000
+++ debian/changelog 2009-06-17 16:46:42 +0000
@@ -1,3 +1,9 @@
1ubuntuone-client (0.90.2-0) jaunty; urgency=low
2
3 * New upstream release
4
5 -- Rodney Dawes <rodney.dawes@canonical.com> Wed, 17 Jun 2009 12:18:54 -0400
6
1ubuntuone-client (0.90.1-0) jaunty; urgency=low7ubuntuone-client (0.90.1-0) jaunty; urgency=low
28
3 * Fix the icon cache issue9 * Fix the icon cache issue
410
=== modified file 'debian/control'
--- debian/control 2009-06-10 19:03:10 +0000
+++ debian/control 2009-06-17 16:46:42 +0000
@@ -5,17 +5,23 @@
5Maintainer: Rick McBride <rick.mcbride@canonical.com>5Maintainer: Rick McBride <rick.mcbride@canonical.com>
6Build-Depends: debhelper (>= 5),6Build-Depends: debhelper (>= 5),
7 cdbs,7 cdbs,
8 autotools-dev,
8 python-central,9 python-central,
9 python-all-dev,10 python-all-dev,
11 intltool,
10 icontool,12 icontool,
13 pkg-config,
11 inkscape,14 inkscape,
12 libxml-simple-perl,15 python-distutils-extra,
13 python-distutils-extra16 libdbus-glib-1-dev,
14Standards-Version: 3.8.017 libsoup2.4-dev,
18 libnautilus-extension-dev,
19 xutils-dev
20Standards-Version: 3.8.1
15Homepage: https://ubuntuone.com21Homepage: https://ubuntuone.com
1622
17Package: ubuntuone-client23Package: ubuntuone-client
18Architecture: all24Architecture: any
19XB-Python-Version: ${python:Versions}25XB-Python-Version: ${python:Versions}
20Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends},26Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends},
21 python-pycurl,27 python-pycurl,
@@ -30,8 +36,7 @@
30 python-pyinotify,36 python-pyinotify,
31 python-notify,37 python-notify,
32 python-apport,38 python-apport,
33 python-twisted-names,39 python-twisted-names
34 python-nautilus
35Provides: ${python:Provides}40Provides: ${python:Provides}
36Replaces: ubuntuone-oauth-login, nautilus-ubuntuone, ubuntuone-storagefs41Replaces: ubuntuone-oauth-login, nautilus-ubuntuone, ubuntuone-storagefs
37Conflicts: ubuntuone-oauth-login, nautilus-ubuntuone, ubuntuone-storagefs42Conflicts: ubuntuone-oauth-login, nautilus-ubuntuone, ubuntuone-storagefs
3843
=== modified file 'debian/rules'
--- debian/rules 2009-05-15 14:18:30 +0000
+++ debian/rules 2009-06-17 16:46:42 +0000
@@ -1,8 +1,14 @@
1#!/usr/bin/make -f1#!/usr/bin/make -f
22
3DEB_PYTHON_SYSTEM = pycentral
4
3include /usr/share/cdbs/1/rules/debhelper.mk5include /usr/share/cdbs/1/rules/debhelper.mk
4DEB_PYTHON_SYSTEM = pycentral
5include /usr/share/cdbs/1/class/python-distutils.mk6include /usr/share/cdbs/1/class/python-distutils.mk
67include /usr/share/cdbs/1/rules/utils.mk
7binary-install/ubuntuone-client::8include /usr/share/cdbs/1/class/autotools.mk
8 dh_icons -pubuntuone-client9include /usr/share/cdbs/1/class/gnome.mk
10
11binary-post-install/ubuntuone-client::
12 find debian/ubuntuone-client/usr/lib -name \*.la -exec rm {} \;
13 find debian/ubuntuone-client/usr/lib -name \*.a -exec rm {} \;
14
915
=== removed file 'nautilus/ubuntuone.py'
--- nautilus/ubuntuone.py 2009-05-12 13:36:05 +0000
+++ nautilus/ubuntuone.py 1970-01-01 00:00:00 +0000
@@ -1,24 +0,0 @@
1# ubuntuone.py - Nautilus extensions for Ubuntu One
2#
3# Author: Tim Cole <tim.cole@canonical.com>
4#
5# Copyright 2009 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18
19"""Top-level extension script for Nautilus. Imports extension classes
20from extension modules."""
21
22# pylint: disable-msg=W0611
23from canonical.ubuntuone.nautilus.storage import StorageBarProvider, \
24 StorageInfoProvider, StorageMenuProvider
250
=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2009-05-13 14:21:08 +0000
+++ po/POTFILES.in 2009-06-17 16:08:17 +0000
@@ -1,6 +1,7 @@
1bin/ubuntuone-client-applet
1data/emblem-ubuntuone-downloading.icon.in2data/emblem-ubuntuone-downloading.icon.in
2data/emblem-ubuntuone-unsynchronized.icon.in3data/emblem-ubuntuone-unsynchronized.icon.in
3data/emblem-ubuntuone-uploading.icon.in4data/emblem-ubuntuone-uploading.icon.in
4data/ubuntuone-client-applet.desktop.in5data/ubuntuone-client-applet.desktop.in
5bin/ubuntuone-client-applet6nautilus/ubuntuone-nautilus.c
6canonical/ubuntuone/nautilus/storage.py7
78
=== added file 'po/POTFILES.skip'
--- po/POTFILES.skip 1970-01-01 00:00:00 +0000
+++ po/POTFILES.skip 2009-06-17 16:08:17 +0000
@@ -0,0 +1,2 @@
1contrib/mocker.py
2
03
=== modified file 'setup.cfg'
--- setup.cfg 2009-05-12 13:36:05 +0000
+++ setup.cfg 2009-06-17 16:08:17 +0000
@@ -3,24 +3,8 @@
3# theme implementation requires the .icon files to be in the same size as3# theme implementation requires the .icon files to be in the same size as
4# the loaded icon. Therefore we have to install the same file to all the4# the loaded icon. Therefore we have to install the same file to all the
5# different sizes, so that our translations show up in the UI properly.5# different sizes, so that our translations show up in the UI properly.
6[build_i18n]6[check]
7domain="ubuntuone-client"7exclude-files=[
8desktop_files=[8 'contrib/build_icons.py',
9 ('share/applications', ['data/ubuntuone-client-applet.desktop.in']),9 'contrib/check.py',
10 ('share/icons/hicolor/48x48/emblems',10 'contrib/mocker.py']
11 ['data/emblem-ubuntuone-downloading.icon.in',
12 'data/emblem-ubuntuone-unsynchronized.icon.in',
13 'data/emblem-ubuntuone-uploading.icon.in']),
14 ('share/icons/hicolor/32x32/emblems',
15 ['data/emblem-ubuntuone-downloading.icon.in',
16 'data/emblem-ubuntuone-unsynchronized.icon.in',
17 'data/emblem-ubuntuone-uploading.icon.in']),
18 ('share/icons/hicolor/24x24/emblems',
19 ['data/emblem-ubuntuone-downloading.icon.in',
20 'data/emblem-ubuntuone-unsynchronized.icon.in',
21 'data/emblem-ubuntuone-uploading.icon.in']),
22 ('share/icons/hicolor/16x16/emblems',
23 ['data/emblem-ubuntuone-downloading.icon.in',
24 'data/emblem-ubuntuone-unsynchronized.icon.in',
25 'data/emblem-ubuntuone-uploading.icon.in'])
26 ]
2711
=== renamed file 'setup.py' => 'setup.py.in' (properties changed: +x to -x)
--- setup.py 2009-05-15 21:11:04 +0000
+++ setup.py.in 2009-06-17 16:08:17 +0000
@@ -3,93 +3,13 @@
33
4import os, sys4import os, sys
5from distutils.core import setup, Command5from distutils.core import setup, Command
6from distutils.spawn import find_executable6from distutils.command import clean
7# pylint: disable-msg=F04017# pylint: disable-msg=F0401
8from DistUtilsExtra.command import (build_extra,8from DistUtilsExtra.command import build_extra
9 build_i18n, clean_i18n)
10from contrib import build_icons, check9from contrib import build_icons, check
1110
12import subprocess11import subprocess
1312
14class NotFoundError(Exception):
15 """Failed to find the program in the path."""
16 pass
17
18class RenderFailed(Exception):
19 """Failed to render the icons with icontool."""
20 pass
21
22class DBusLaunchError(Exception):
23 """Failed to launch our dbus session daemon."""
24 pass
25
26class UbuntuOneBuild(build_extra.build_extra):
27 """Class to build our stuff."""
28
29 description = "generate our icons and some other things"
30
31 user_options = [("protocol-source=", None,
32 "path to ubuntuone-storage-protocol source tree")
33 ] + build_extra.build_extra.user_options
34
35 def initialize_options(self):
36 """Do build-extra options initialization."""
37 self.protocol_source = None
38 build_extra.build_extra.initialize_options(self)
39
40 def finalize_options(self):
41 """Do build-extra options finalization."""
42 if self.protocol_source is None:
43 self.protocol_source = "/usr/share/pyshared"
44 build_extra.build_extra.finalize_options(self)
45
46 def run(self):
47 """Do the build"""
48 if not find_executable("icontool-render"):
49 raise NotFoundError("You need icontool to generate the icons " +
50 "for Ubuntu One.")
51
52 print "generating icons"
53 sizes = [ "16x16", "24x24", "32x32", "48x48" ]
54 icons = [ "data/ubuntuone-icons.svg", "data/ubuntuone-animations.svg" ]
55
56 iconpath = os.path.join("data", "icons")
57 if not os.path.exists(iconpath):
58 os.mkdir(iconpath)
59
60 for icon in icons:
61 for size in sizes:
62 p = subprocess.Popen(["icontool-render",
63 "-o", "data/icons",
64 "-s", size,
65 icon],
66 bufsize=4096, stdout=subprocess.PIPE)
67 built = p.stdout
68 p.wait()
69
70 if p.returncode != 0:
71 raise RenderFailed("Failed to render icons")
72
73 hicolor = os.path.join("data", "hicolor")
74 if not os.path.exists(hicolor):
75 os.symlink("icons", hicolor)
76
77 localprotocol = os.path.join("canonical", "ubuntuone",
78 "storage", "protocol")
79 if not os.path.exists(localprotocol):
80 protopath = os.path.join(self.protocol_source, localprotocol)
81 try:
82 os.symlink(protopath, localprotocol)
83 except (IOError, os.error), e:
84 if hasattr(e, 'filename') and e.filename:
85 print "%s: %s" % (e.filename, e.strerror)
86 else:
87 print "%s: %s" % (localprotocol, e.strerror)
88
89
90 build_extra.build_extra.run(self)
91
92
93class UbuntuOneBuildu1fsfsm(Command):13class UbuntuOneBuildu1fsfsm(Command):
94 """Class to build u1fsfsm.py from the ods file."""14 """Class to build u1fsfsm.py from the ods file."""
9515
@@ -131,81 +51,15 @@
131 sys.stderr.write("[ERROR] Failed to build u1fsfsm.py.\n")51 sys.stderr.write("[ERROR] Failed to build u1fsfsm.py.\n")
132 sys.exit(1)52 sys.exit(1)
13353
134
135class UbuntuOneClean(clean_i18n.clean_i18n):
136 """Class to clean up after ourselves."""
137
138 description = "clean up built files"
139
140 def run(self):
141 """Do the cleanup"""
142 hicolor = os.path.join("data", "hicolor")
143 if os.path.exists(hicolor):
144 os.unlink(hicolor)
145
146 iconpath = os.path.join("data", "icons")
147 subprocess.call(["rm", "-rf", iconpath])
148
149 protocol = os.path.join("canonical", "ubuntuone",
150 "storage", "protocol")
151 if os.path.exists(protocol):
152 os.unlink(protocol)
153
154 clean_i18n.clean_i18n.run(self)
155
156
157class UbuntuOneCheck(check.check):
158 """Class to run unit tests and lint checks."""
159
160 description = "validate code with pylint and unit tests"
161
162 def run(self):
163 """Do the checks."""
164 check.check.run(self)
165
166 print "\nrunning tests"
167 returncode = subprocess.call([os.path.join('contrib', 'test')])
168 if returncode:
169 sys.exit(returncode)
170
171
172setup(name='ubuntuone-client',54setup(name='ubuntuone-client',
173 version='0.90.1',55 version = '@VERSION@',
17456
175 packages=['canonical.ubuntuone.oauthdesktop',57 data_files = [],
176 'canonical.ubuntuone.nautilus',
177 'canonical.ubuntuone.storage.syncdaemon',
178 'canonical.ubuntuone.storage.u1sync',
179 'canonical.ubuntuone.storage.syncdaemon.fsm'],
180
181 scripts=['bin/ubuntuone-client-applet',
182 'bin/ubuntuone-syncdaemon',
183 'bin/u1sync',
184 'bin/u1sdtool'],
185
186 data_files=[('share/dbus-1/services',
187 ['data/com.ubuntuone.Authentication.service',
188 'data/com.ubuntuone.SyncDaemon.service']),
189 ('/etc/xdg/ubuntuone',
190 ['data/oauth_urls', 'data/syncdaemon.conf']),
191 ('/etc/xdg/ubuntuone/oauth_registration.d',
192 ['oauth_registration.d/ubuntuone']),
193 ('lib/nautilus/extensions-2.0/python',
194 ['nautilus/ubuntuone.py']),
195 ('share/apport/package-hooks',
196 ['apport/source_ubuntuone-client.py']),
197 ('share/man/man1',
198 ['docs/man/u1sdtool.1',
199 'docs/man/u1sync.1',
200 'docs/man/ubuntuone-client-applet.1']),
201 ],
20258
203 cmdclass = {59 cmdclass = {
204 'build' : UbuntuOneBuild,60 'build' : build_extra.build_extra,
205 'build_i18n' : build_i18n.build_i18n,
206 'build_icons' : build_icons.build_icons,61 'build_icons' : build_icons.build_icons,
207 'clean' : UbuntuOneClean,62 'check' : check.check,
208 'check' : UbuntuOneCheck,
209 'build_u1fsfsm' : UbuntuOneBuildu1fsfsm,63 'build_u1fsfsm' : UbuntuOneBuildu1fsfsm,
210 }64 }
211 )65 )
21266
=== removed directory 'tests/nautilus'
=== removed file 'tests/nautilus/__init__.py'
--- tests/nautilus/__init__.py 2009-05-12 13:36:05 +0000
+++ tests/nautilus/__init__.py 1970-01-01 00:00:00 +0000
@@ -1,14 +0,0 @@
1# Copyright 2009 Canonical Ltd.
2#
3# This program is free software: you can redistribute it and/or modify it
4# under the terms of the GNU General Public License version 3, as published
5# by the Free Software Foundation.
6#
7# This program is distributed in the hope that it will be useful, but
8# WITHOUT ANY WARRANTY; without even the implied warranties of
9# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
10# PURPOSE. See the GNU General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License along
13# with this program. If not, see <http://www.gnu.org/licenses/>.
14"""Tests for the nautilus extension."""
150
=== removed file 'tests/nautilus/test_storage.py'
--- tests/nautilus/test_storage.py 2009-05-12 13:36:05 +0000
+++ tests/nautilus/test_storage.py 1970-01-01 00:00:00 +0000
@@ -1,70 +0,0 @@
1# canonical.ubuntuone.nautilus.tests.test_storage
2#
3# Author: Tim Cole <tim.cole@canonical.com>
4#
5# Copyright 2009 Canonical Ltd.
6#
7# This program is free software: you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
11# This program is distributed in the hope that it will be useful, but
12# WITHOUT ANY WARRANTY; without even the implied warranties of
13# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14# PURPOSE. See the GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License along
17# with this program. If not, see <http://www.gnu.org/licenses/>.
18"""Tests for the storage-related nautilus extension classes."""
19
20from __future__ import with_statement
21from unittest import TestCase
22from canonical.ubuntuone.nautilus.storage import StorageBarProvider
23from contrib.mocker import Mocker, expect
24
25
26class TestStorageBarProvider(TestCase):
27 """Test the Storage location bar provider."""
28
29 def setUp(self):
30 """Sets up the test."""
31 self.mocker = Mocker()
32 self.window = self.mocker.mock()
33 self.storagefs_test = self.mocker.mock()
34 self.provider = None
35
36 def tearDown(self):
37 """Tears down a test."""
38 self.mocker.restore()
39 self.mocker.verify()
40
41 def replay(self):
42 """Starts replay phase and creates the storage bar provider."""
43 self.mocker.replay()
44 self.provider = StorageBarProvider(is_storagefs=self.storagefs_test)
45
46 def testInstantiation(self):
47 """Make sure that instantiation works."""
48 self.replay()
49
50 def testNoWidgetForNonFileURIs(self):
51 """Make sure that we don't return a widget for non-file URIs."""
52 url = "http://www.google.com/"
53 self.replay()
54 self.assert_(self.provider.get_widget(url, self.window) is None,
55 "Should not return a widget for a non-file URI")
56
57 def testNoWidgetOutsideStorageFS(self):
58 """Make sure that we don't return a widget for regular directories."""
59 url = "file:///etc/"
60 expect(self.storagefs_test("/etc/")).result(False)
61 self.replay()
62 self.assert_(self.provider.get_widget(url, self.window) is None,
63 "Should not return a widget outside storagefs")
64
65 def testWidgetInsideStorageFS(self):
66 """Make sure that we do return a widget for storagefs directories."""
67 url = "file:///blah/"
68 expect(self.storagefs_test("/blah/")).result(True)
69 self.replay()
70 self.assert_(self.provider.get_widget(url, self.window) is not None)

Subscribers

People subscribed via source and target branches