Merge lp:~dobey/ubuntuone-control-panel/update-4-2 into lp:ubuntuone-control-panel/stable-4-2

Proposed by dobey
Status: Merged
Merged at revision: 377
Proposed branch: lp:~dobey/ubuntuone-control-panel/update-4-2
Merge into: lp:ubuntuone-control-panel/stable-4-2
Diff against target: 1230 lines (+763/-157)
13 files modified
bin/ubuntuone-updater (+184/-0)
setup.py (+1/-1)
ubuntuone/controlpanel/__init__.py (+0/-1)
ubuntuone/controlpanel/gui/__init__.py (+8/-10)
ubuntuone/controlpanel/gui/qt/gui.py (+1/-1)
ubuntuone/controlpanel/gui/qt/main/__init__.py (+3/-1)
ubuntuone/controlpanel/utils/__init__.py (+5/-3)
ubuntuone/controlpanel/utils/common.py (+128/-0)
ubuntuone/controlpanel/utils/darwin.py (+59/-8)
ubuntuone/controlpanel/utils/tests/test_common.py (+233/-0)
ubuntuone/controlpanel/utils/tests/test_darwin.py (+105/-16)
ubuntuone/controlpanel/utils/tests/test_windows.py (+22/-79)
ubuntuone/controlpanel/utils/windows.py (+14/-37)
To merge this branch: bzr merge lp:~dobey/ubuntuone-control-panel/update-4-2
Reviewer Review Type Date Requested Status
Brian Curtin (community) Approve
Review via email: mp+142744@code.launchpad.net

Commit message

[Mike McCracken]
    - Remove a debug print statement in the tests that snuck through.
    - Use new SSO API to get platform-appropriate translation function. (LP: 1074116)
    - Add u1 folder to OS X Finder favorites sidebar on first launch.

[Brian Curtin]

    - Add common updater script for mac and windows. (LP: #1087262)

To post a comment you must log in.
Revision history for this message
Brian Curtin (brian.curtin) :
review: Approve
Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (7.3 KiB)

The attempt to merge lp:~dobey/ubuntuone-control-panel/update-4-2 into lp:ubuntuone-control-panel/stable-4-2 failed. Below is the output from the failed tests.

*** Running DBus test suite ***
ubuntuone.controlpanel.dbustests.test_dbus_service
  BaseTestCase
    runTest ... [OK]
  DBusServiceMainTestCase
    test_dbus_service_cant_register ... Control panel backend already running.
                                   [OK]
    test_dbus_service_main ... [OK]
  DBusServiceTestCase
    test_cant_register_twice ... [SKIPPED]
    test_dbus_busname_created ... [OK]
    test_error_handler_default ... [OK]
    test_error_handler_with_exception ... [OK]
    test_error_handler_with_failure ... [OK]
    test_error_handler_with_non_string_dict ... [OK]
    test_error_handler_with_string_dict ... [OK]
    test_register_service ... [OK]
  FileSyncTestCase
    test_file_sync_status_changed ... [OK]
    test_file_sync_status_disabled ... [OK]
    test_file_sync_status_disconnected ... [OK]
    test_file_sync_status_error ... [OK]
    test_file_sync_status_idle ... [OK]
    test_file_sync_status_starting ... [OK]
    test_file_sync_status_stopped ... [OK]
    test_file_sync_status_syncing ... [OK]
    test_file_sync_status_unknown ... [OK]
    test_status_changed_handler ... [OK]
    test_status_changed_handler_after_status_requested ... [OK]
    test_status_changed_handler_after_status_requested_twice ... [OK]
  OperationsAuthErrorTestCase
    test_account_info_returned ... [OK]
    test_change_device_settings ... [OK]
    test_change_replication_settings ... [OK]
    test_change_volume_settings ... [OK]
    test_connect_files ... [OK]
    test_devices_info_returned ... [OK]
    test_disable_files ... [OK]
    test_disconnect_files ... [OK]
    test_enable_files ... [OK]
    test_remove_device ... [OK]
    test_replications_info ... [OK]
    test_restart_files ... [OK]
    t...

Read more...

Revision history for this message
Ubuntu One Auto Pilot (otto-pilot) wrote :
Download full text (168.2 KiB)

The attempt to merge lp:~dobey/ubuntuone-control-panel/update-4-2 into lp:ubuntuone-control-panel/stable-4-2 failed. Below is the output from the failed tests.

*** Running DBus test suite ***
ubuntuone.controlpanel.dbustests.test_dbus_service
  BaseTestCase
    runTest ... [OK]
  DBusServiceMainTestCase
    test_dbus_service_cant_register ... Control panel backend already running.
                                   [OK]
    test_dbus_service_main ... [OK]
  DBusServiceTestCase
    test_cant_register_twice ... [SKIPPED]
    test_dbus_busname_created ... [OK]
    test_error_handler_default ... [OK]
    test_error_handler_with_exception ... [OK]
    test_error_handler_with_failure ... [OK]
    test_error_handler_with_non_string_dict ... [OK]
    test_error_handler_with_string_dict ... [OK]
    test_register_service ... [OK]
  FileSyncTestCase
    test_file_sync_status_changed ... [OK]
    test_file_sync_status_disabled ... [OK]
    test_file_sync_status_disconnected ... [OK]
    test_file_sync_status_error ... [OK]
    test_file_sync_status_idle ... [OK]
    test_file_sync_status_starting ... [OK]
    test_file_sync_status_stopped ... [OK]
    test_file_sync_status_syncing ... [OK]
    test_file_sync_status_unknown ... [OK]
    test_status_changed_handler ... [OK]
    test_status_changed_handler_after_status_requested ... [OK]
    test_status_changed_handler_after_status_requested_twice ... [OK]
  OperationsAuthErrorTestCase
    test_account_info_returned ... [OK]
    test_change_device_settings ... [OK]
    test_change_replication_settings ... [OK]
    test_change_volume_settings ... [OK]
    test_connect_files ... [OK]
    test_devices_info_returned ... [OK]
    test_disable_files ... [OK]
    test_disconnect_files ... [OK]
    test_enable_files ... [OK]
    test_remove_device ... [OK]
    test_replications_info ... [OK]
    test_restart_files ... [OK]
    t...

377. By dobey

[Mike McCracken]
    - Remove a debug print statement in the tests that snuck through.
    - Use new SSO API to get platform-appropriate translation function. (LP: 1074116)
    - Add u1 folder to OS X Finder favorites sidebar on first launch.

[Brian Curtin]

    - Add common updater script for mac and windows. (LP: #1087262)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'bin/ubuntuone-updater'
2--- bin/ubuntuone-updater 1970-01-01 00:00:00 +0000
3+++ bin/ubuntuone-updater 2013-01-10 18:07:21 +0000
4@@ -0,0 +1,184 @@
5+#!/usr/bin/python
6+# -*- coding: utf-8 -*-
7+#
8+# Copyright 2012 Canonical Ltd.
9+#
10+# This program is free software: you can redistribute it and/or modify it
11+# under the terms of the GNU General Public License version 3, as published
12+# by the Free Software Foundation.
13+#
14+# This program is distributed in the hope that it will be useful, but
15+# WITHOUT ANY WARRANTY; without even the implied warranties of
16+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
17+# PURPOSE. See the GNU General Public License for more details.
18+#
19+# You should have received a copy of the GNU General Public License along
20+# with this program. If not, see <http://www.gnu.org/licenses/>.
21+
22+"""A script to check the website for new versions of Ubuntu One."""
23+
24+from __future__ import print_function
25+
26+try:
27+ from urllib.request import urlopen, URLError
28+ from urllib.parse import urljoin
29+except ImportError:
30+ from urllib2 import urlopen, URLError
31+ from urlparse import urljoin
32+
33+import argparse
34+import hashlib
35+import json
36+import os
37+import subprocess
38+import sys
39+import tempfile
40+
41+from dirspec.utils import get_program_path
42+
43+
44+U1SDTOOL_EXECUTABLE = 'u1sdtool'
45+DARWIN_APP_NAMES = {U1SDTOOL_EXECUTABLE: 'U1SDTool.app'}
46+
47+
48+if sys.platform == "darwin":
49+ from Cocoa import NSRunningApplication, NSLog
50+ # IDs to terminate: Leave syncdaemon off this list, it is
51+ # terminated separately.
52+ BUNDLE_IDS = ["com.ubuntu.sso.login-qt",
53+ "com.ubuntu.sso.ssl-cert",
54+ "com.ubuntu.sso.login",
55+ "com.ubuntu.one.proxy-tunnel",
56+ "com.ubuntu.one.u1sdtool",
57+ "com.ubuntu.one.updater",
58+ "com.ubuntu.one.controlpanel",
59+ "com.ubuntu.one.menu"]
60+
61+
62+def _do_download(url):
63+ """Download a URL and return the data it contains."""
64+ resource = urlopen(url)
65+ if resource:
66+ data = resource.read()
67+ return data
68+
69+
70+def _save_download(url, checksum):
71+ """Given URL data, save it to a file and return the file name.
72+
73+ The resource is saved to a file which is the responsibility of callers
74+ to cleanup. It was created with tempfile.mkstemp."""
75+ data = _do_download(url)
76+
77+ md5 = hashlib.md5()
78+ md5.update(data)
79+ if checksum != md5.hexdigest():
80+ raise Exception("Checksum mismatch")
81+
82+ fd, name = tempfile.mkstemp()
83+ with os.fdopen(fd, "wb") as fobj:
84+ fobj.write(data)
85+
86+ return name
87+
88+
89+def run_install(url, checksum):
90+ try:
91+ args = [_save_download(url, checksum)]
92+ if sys.platform == 'darwin':
93+ args.insert(0, 'open')
94+ subprocess.Popen(args)
95+ except Exception as exc:
96+ print("Unable to install {}: {}".format(url, exc))
97+ return False
98+ return True
99+
100+
101+def check(args):
102+ """Check a URL and return True if a new version is available."""
103+ error = (False, "", "") # Default to no new release.
104+
105+ try:
106+ data = _do_download(args.url)
107+ except URLError as err:
108+ print("Download failed: {}".format(err))
109+ return error
110+
111+ try:
112+ info = json.loads(data)
113+ available = info[args.platform][args.release]
114+ avail_ver = available["version"]
115+ upgrade_available = avail_ver > args.current
116+ if upgrade_available:
117+ msg = "A new {} version is available at {}."
118+ print(msg.format(args.release, available["url"]))
119+ elif avail_ver == args.current:
120+ print("Version {} is the latest {}.".format(args.current,
121+ args.release))
122+ else:
123+ print("Warning: installed version {} newer than advertised"
124+ " available version {} somehow.".format(args.current,
125+ avail_ver))
126+
127+ except Exception as exc:
128+ # Catch everything here.
129+ # KeyError is most likely, but we can't let this take us down.
130+ print("Exception while reading {}:".format(args.url),
131+ exc.__class__, exc.message)
132+ return error
133+
134+ return upgrade_available, available["url"], available["checksum"]
135+
136+
137+def kill_running_processes():
138+ """Kill any running u1 processes."""
139+ if sys.platform != "darwin":
140+ return
141+ NSLog("in kill")
142+
143+ try:
144+ u1sdtoolpath = get_program_path(U1SDTOOL_EXECUTABLE,
145+ app_names=DARWIN_APP_NAMES)
146+
147+ out = subprocess.check_output([u1sdtoolpath, '-q'])
148+ NSLog("u1sdtool said: {}".format(out))
149+ except Exception as e:
150+ NSLog("exception running {} -q: {}".format(u1sdtoolpath, e))
151+
152+ for id in BUNDLE_IDS:
153+ NSRA = NSRunningApplication
154+ apps = NSRA.runningApplicationsWithBundleIdentifier_(id)
155+ NSLog("id: {} apps: {}".format(id, apps))
156+
157+ for app in apps:
158+ app.terminate()
159+
160+
161+def main(*args):
162+ """Return 1 if the action was successful, 0 if not.
163+
164+ The default option is to check that an update is available.
165+ Adding the --install option will download and run
166+ the update if available."""
167+ parser = argparse.ArgumentParser()
168+ parser.add_argument("--install", action="store_true")
169+ parser.add_argument("--platform", type=str, default=sys.platform)
170+ parser.add_argument("--release", type=str, required=True)
171+ parser.add_argument("--current", type=int, required=True)
172+ parser.add_argument("--url", type=str, required=True)
173+
174+ args = parser.parse_args()
175+
176+ new_available, file, checksum = check(args)
177+ if not args.install:
178+ return 1 if new_available else 0
179+
180+ if args.install and new_available:
181+ installer = urljoin(args.url, file)
182+ print("Downloading and installing", installer)
183+ kill_running_processes()
184+ return 1 if run_install(installer, checksum) else 0
185+
186+
187+if __name__ == "__main__":
188+ sys.exit(main(sys.argv[:]))
189
190=== modified file 'setup.py'
191--- setup.py 2012-12-05 22:58:30 +0000
192+++ setup.py 2013-01-10 18:07:21 +0000
193@@ -193,7 +193,7 @@
194
195 DistUtilsExtra.auto.setup(
196 name='ubuntuone-control-panel',
197- version='4.1',
198+ version='4.1.0',
199 license='GPL v3',
200 author='Natalia Bidart',
201 author_email='natalia.bidart@canonical.com',
202
203=== modified file 'ubuntuone/controlpanel/__init__.py'
204--- ubuntuone/controlpanel/__init__.py 2011-09-06 17:21:56 +0000
205+++ ubuntuone/controlpanel/__init__.py 2013-01-10 18:07:21 +0000
206@@ -30,4 +30,3 @@
207 DBUS_PREFERENCES_IFACE = "com.ubuntuone.controlpanel.Preferences"
208
209 WEBSERVICE_BASE_URL = u"https://one.ubuntu.com/api/"
210-TRANSLATION_DOMAIN = 'ubuntuone-control-panel'
211
212=== modified file 'ubuntuone/controlpanel/gui/__init__.py'
213--- ubuntuone/controlpanel/gui/__init__.py 2012-11-02 13:10:20 +0000
214+++ ubuntuone/controlpanel/gui/__init__.py 2013-01-10 18:07:21 +0000
215@@ -16,23 +16,21 @@
216
217 """The control panel UI for Ubuntu One."""
218
219-import gettext
220-import sys
221+import os
222
223 # pylint: disable=W0611
224 from ubuntuone.clientdefs import APP_NAME
225 # pylint: enable=W0611
226
227-from ubuntuone.controlpanel import TRANSLATION_DOMAIN
228+from ubuntu_sso.utils.translation import get_gettext
229+
230 from ubuntuone.controlpanel.backend import UBUNTUONE_LINK
231
232-
233-TRANSLATION = gettext.translation(TRANSLATION_DOMAIN, fallback=True)
234-if sys.version_info < (3,):
235- _ = TRANSLATION.ugettext
236-else:
237- _ = TRANSLATION.gettext
238-
239+source_path = os.path.join(os.path.dirname(__file__),
240+ os.path.pardir, os.path.pardir,
241+ os.path.pardir, 'build', 'mo')
242+_ = get_gettext('ubuntuone-control-panel',
243+ fallback_path=os.path.abspath(source_path))
244
245 ERROR_COLOR = u'red'
246 KILOBYTES = 1024
247
248=== modified file 'ubuntuone/controlpanel/gui/qt/gui.py'
249--- ubuntuone/controlpanel/gui/qt/gui.py 2012-11-01 19:33:57 +0000
250+++ ubuntuone/controlpanel/gui/qt/gui.py 2013-01-10 18:07:21 +0000
251@@ -123,7 +123,7 @@
252 logger.info('Performing auto-update.')
253 utils.perform_update()
254 else:
255- logger.info('User do not want to update.')
256+ logger.info('User does not want to update.')
257
258
259 def start(close_callback, minimized=False, with_icon=False, installer=False):
260
261=== modified file 'ubuntuone/controlpanel/gui/qt/main/__init__.py'
262--- ubuntuone/controlpanel/gui/qt/main/__init__.py 2012-11-30 18:06:22 +0000
263+++ ubuntuone/controlpanel/gui/qt/main/__init__.py 2013-01-10 18:07:21 +0000
264@@ -50,7 +50,8 @@
265
266 # pylint: enable=C0103
267
268-from ubuntuone.controlpanel.utils import install_config_and_daemons
269+from ubuntuone.controlpanel.utils import (install_config_and_daemons,
270+ add_u1_folder_to_favorites)
271
272
273 def parser_options():
274@@ -136,6 +137,7 @@
275 app.setStyleSheet('\n'.join(data))
276
277 install_config_and_daemons()
278+ add_u1_folder_to_favorites()
279
280 if sys.platform == 'darwin':
281 with_icon = False
282
283=== modified file 'ubuntuone/controlpanel/utils/__init__.py'
284--- ubuntuone/controlpanel/utils/__init__.py 2012-08-03 23:36:46 +0000
285+++ ubuntuone/controlpanel/utils/__init__.py 2013-01-10 18:07:21 +0000
286@@ -21,7 +21,6 @@
287
288 from ubuntuone.controlpanel.logger import setup_logging
289
290-
291 logger = setup_logging('utils')
292
293 DATA_SUFFIX = 'data'
294@@ -38,6 +37,7 @@
295 if sys.platform == 'win32':
296 from ubuntuone.controlpanel.utils import windows
297 add_to_autostart = windows.add_to_autostart
298+ add_u1_folder_to_favorites = no_op
299 are_updates_present = windows.are_updates_present
300 default_folders = windows.default_folders
301 install_config_and_daemons = no_op
302@@ -46,14 +46,16 @@
303 elif sys.platform == 'darwin':
304 from ubuntuone.controlpanel.utils import darwin
305 add_to_autostart = no_op
306- are_updates_present = no_op
307+ add_u1_folder_to_favorites = darwin.add_u1_folder_to_favorites
308+ are_updates_present = darwin.are_updates_present
309 default_folders = darwin.default_folders
310 install_config_and_daemons = darwin.install_config_and_daemons
311- perform_update = no_op
312+ perform_update = darwin.perform_update
313 uninstall_application = no_op
314 else:
315 from ubuntuone.controlpanel.utils import linux
316 add_to_autostart = no_op
317+ add_u1_folder_to_favorites = no_op
318 are_updates_present = no_op
319 default_folders = linux.default_folders
320 install_config_and_daemons = no_op
321
322=== added file 'ubuntuone/controlpanel/utils/common.py'
323--- ubuntuone/controlpanel/utils/common.py 1970-01-01 00:00:00 +0000
324+++ ubuntuone/controlpanel/utils/common.py 2013-01-10 18:07:21 +0000
325@@ -0,0 +1,128 @@
326+# -*- coding: utf-8 -*-
327+#
328+# Copyright 2012 Canonical Ltd.
329+#
330+# This program is free software: you can redistribute it and/or modify it
331+# under the terms of the GNU General Public License version 3, as published
332+# by the Free Software Foundation.
333+#
334+# This program is distributed in the hope that it will be useful, but
335+# WITHOUT ANY WARRANTY; without even the implied warranties of
336+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
337+# PURPOSE. See the GNU General Public License for more details.
338+#
339+# You should have received a copy of the GNU General Public License along
340+# with this program. If not, see <http://www.gnu.org/licenses/>.
341+
342+"""Platform - independent support code for utils."""
343+
344+import os
345+import sys
346+
347+try:
348+ from configparser import (SafeConfigParser, NoSectionError, NoOptionError)
349+except ImportError:
350+ from ConfigParser import (SafeConfigParser, NoSectionError, NoOptionError)
351+
352+from twisted.internet import defer
353+from twisted.internet.utils import getProcessValue
354+from twisted.python import procutils
355+
356+from dirspec.basedir import load_config_paths
357+from dirspec.utils import get_program_path
358+
359+from ubuntuone.controlpanel.utils import logger
360+
361+UPDATE_BIN_NAME = 'ubuntuone-updater'
362+UPDATE_CONFIG_NAME = 'update.conf'
363+DARWIN_APP_NAMES = {UPDATE_BIN_NAME: 'UbuntuOne Updater.app'}
364+
365+
366+def get_bin_cmd(exe_name):
367+ """Return list of cmds for an exe from the control panel project."""
368+ fallback_dir = os.path.join(os.path.dirname(__file__),
369+ os.pardir, os.pardir, os.pardir,
370+ "bin")
371+
372+ cmd_args = [get_program_path(exe_name,
373+ fallback_dirs=[fallback_dir],
374+ app_names=DARWIN_APP_NAMES)]
375+
376+ # procutils.which('python') returns python.exe on windows:
377+ if getattr(sys, 'frozen', None) is None:
378+ cmd_args.insert(0, procutils.which('python')[0])
379+
380+ return cmd_args
381+
382+
383+def get_update_config():
384+ """Read the update.conf file and return a triple of
385+ the URL, version, and whether updates should be checked."""
386+ no_config = (None, None, None, False)
387+ url, version, channel, check = no_config
388+
389+ files = [os.path.join(dir, UPDATE_CONFIG_NAME)
390+ for dir in load_config_paths("ubuntuone")]
391+
392+ conf = SafeConfigParser()
393+ read_files = conf.read(files)
394+
395+ if not read_files:
396+ logger.debug(
397+ "Unable to find an update.conf file - not checking for updates")
398+ return no_config
399+
400+ try:
401+ url = conf.get("Update", "url")
402+ version = conf.get("Update", "version_id")
403+ channel = conf.get("Update", "channel")
404+ check = conf.getint("Update", "check_for_updates")
405+ except (NoSectionError, NoOptionError) as e:
406+ logger.debug("could not read update.conf - not checking for updates")
407+ logger.debug(" (exception was %r)" % e)
408+ return no_config
409+
410+ return url, version, channel, check
411+
412+
413+@defer.inlineCallbacks
414+def call_updater(custom_call=None, install=False):
415+ """Call the Ubuntu One updater."""
416+ result = False
417+ retcode = None
418+ try:
419+ updater_cmd = get_bin_cmd(UPDATE_BIN_NAME)
420+ except OSError, e:
421+ logger.debug("Could not find updater command: %r" % e)
422+ defer.returnValue(result)
423+
424+ url, local_version, channel, should_check = get_update_config()
425+
426+ if not should_check:
427+ logger.debug("ignoring update check")
428+ defer.returnValue(result)
429+
430+ args = ["--url", url,
431+ "--current", str(local_version),
432+ "--release", channel]
433+ if install:
434+ args.append("--install")
435+
436+ exe = updater_cmd[0]
437+ args = updater_cmd[1:] + args
438+
439+ logger.debug("calling %s update process: %r args %r",
440+ "custom" if custom_call else "regular",
441+ exe, args)
442+
443+ if custom_call:
444+ custom_call(exe, args)
445+ else:
446+ # updater returns 1 if available, zero if not
447+ retcode = yield getProcessValue(exe, args)
448+ result = retcode == 1
449+
450+ logger.debug('call_updater: %s, updater cmd: %r, return code: %r,'
451+ ' result: %r', "installing" if install else "checking",
452+ updater_cmd, retcode, result)
453+ defer.returnValue(result)
454
455=== modified file 'ubuntuone/controlpanel/utils/darwin.py'
456--- ubuntuone/controlpanel/utils/darwin.py 2012-11-29 20:15:08 +0000
457+++ ubuntuone/controlpanel/utils/darwin.py 2013-01-10 18:07:21 +0000
458@@ -20,6 +20,14 @@
459 import shutil
460 import sys
461
462+from Cocoa import (NSURL, NSUserDefaults)
463+from LaunchServices import (
464+ kLSSharedFileListFavoriteItems,
465+ kLSSharedFileListItemBeforeFirst,
466+ LSSharedFileListCreate,
467+ LSSharedFileListInsertItemURL,
468+ LSSharedFileListItemRef)
469+
470 from ctypes import (
471 byref,
472 CDLL,
473@@ -39,10 +47,15 @@
474
475 from dirspec.basedir import save_config_path
476 from ubuntuone.controlpanel.logger import setup_logging
477+from ubuntuone.controlpanel.utils.common import call_updater
478 from ubuntuone.platform import expand_user
479
480 logger = setup_logging('utils.darwin')
481
482+ADDED_TO_FINDER_SIDEBAR_ONCE = "ADDED_TO_FINDER_SIDEBAR_ONCE"
483+
484+LOGO_ICON = "ubuntuone_logo.png"
485+
486 AUTOUPDATE_BIN_NAME = 'autoupdate-darwin'
487 UNINSTALL_BIN_NAME = 'uninstall-darwin'
488
489@@ -343,11 +356,37 @@
490 # TODO
491
492
493+def _get_userdefaults():
494+ """Testable wrapper for NSUserDefaults"""
495+ # HACK: This is required to avoid trial complaining on tear down
496+ # that assigning to native selectors is not supported.
497+ return NSUserDefaults.standardUserDefaults()
498+
499+
500+def add_u1_folder_to_favorites():
501+ """Add the u1 folder to the favorites sidebar in Finder."""
502+ sud = _get_userdefaults()
503+ if sud.boolForKey_(ADDED_TO_FINDER_SIDEBAR_ONCE):
504+ return
505+ else:
506+ sud.setBool_forKey_(True, ADDED_TO_FINDER_SIDEBAR_ONCE)
507+
508+ u1_path = os.path.expanduser("~/Ubuntu%20One/")
509+ u1_url = NSURL.URLWithString_("file://localhost" + "%s" % u1_path)
510+
511+ lst = LSSharedFileListCreate(None,
512+ kLSSharedFileListFavoriteItems,
513+ None)
514+ item = LSSharedFileListInsertItemURL(lst, kLSSharedFileListItemBeforeFirst,
515+ None, None, u1_url, {}, [])
516+ if not isinstance(item, LSSharedFileListItemRef):
517+ logger.debug("Error adding ~/Ubuntu One to finder favorites")
518+
519+
520 @defer.inlineCallbacks
521 def are_updates_present():
522 """Return if there are updates for Ubuntu One."""
523- result = False
524- # TODO
525+ result = yield call_updater(install=False)
526 defer.returnValue(result)
527
528
529@@ -448,23 +487,35 @@
530
531 config_path = save_config_path('ubuntuone')
532
533- conf_filenames = ['syncdaemon.conf',
534- 'logging.conf']
535- for conf_filename in conf_filenames:
536+ # Always copy missing files, and for update.conf, overwrite
537+ # existing file to reflect current version ID, but only if bundled
538+ # version is newer, so we can change the file for testing.
539+ conf_filenames = [('syncdaemon.conf', False),
540+ ('logging.conf', False),
541+ ('update.conf', True)]
542+ for conf_filename, overwrite_old in conf_filenames:
543 src_path = os.path.join(main_app_resources_dir,
544 conf_filename)
545 dest_path = os.path.join(config_path,
546 conf_filename)
547-
548+ do_copy = False
549 if not os.path.exists(dest_path):
550+ do_copy = True
551+ else:
552+ src_mtime = os.stat(src_path).st_mtime
553+ dest_mtime = os.stat(dest_path).st_mtime
554+ if overwrite_old and src_mtime >= dest_mtime:
555+ do_copy = True
556+
557+ if do_copy:
558 shutil.copyfile(src_path, dest_path)
559
560 check_and_install_fsevents_daemon(main_app_dir)
561
562
563 def perform_update():
564- """Spawn the autoupdate process and call the stop function."""
565- # TODO
566+ """Spawn the autoupdate process, which will eventually kill us."""
567+ call_updater(install=True)
568
569
570 def uninstall_application():
571
572=== added file 'ubuntuone/controlpanel/utils/tests/test_common.py'
573--- ubuntuone/controlpanel/utils/tests/test_common.py 1970-01-01 00:00:00 +0000
574+++ ubuntuone/controlpanel/utils/tests/test_common.py 2013-01-10 18:07:21 +0000
575@@ -0,0 +1,233 @@
576+# -*- coding: utf-8 -*-
577+#
578+# Copyright 2012 Canonical Ltd.
579+#
580+# This program is free software: you can redistribute it and/or modify it
581+# under the terms of the GNU General Public License version 3, as published
582+# by the Free Software Foundation.
583+#
584+# This program is distributed in the hope that it will be useful, but
585+# WITHOUT ANY WARRANTY; without even the implied warranties of
586+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
587+# PURPOSE. See the GNU General Public License for more details.
588+#
589+# You should have received a copy of the GNU General Public License along
590+# with this program. If not, see <http://www.gnu.org/licenses/>.
591+
592+"""Tests for utility code that's common between darwin and windows."""
593+
594+from twisted.internet import defer
595+
596+try:
597+ from configparser import SafeConfigParser
598+except ImportError:
599+ from ConfigParser import SafeConfigParser
600+
601+from ubuntuone.controlpanel import utils
602+from ubuntuone.controlpanel.tests import TestCase
603+from ubuntuone.controlpanel.utils import common
604+assert(common)
605+
606+UPDATE_KEY = 'Update'
607+URL_KEY = 'url'
608+TEST_URL = 'test-url'
609+VERSION_ID_KEY = 'version_id'
610+TEST_VERSION_ID = '100'
611+CHANNEL_KEY = 'channel'
612+TEST_CHANNEL = 'test-channel'
613+CHECK_KEY = 'check_for_updates'
614+TEST_CHECK = '1'
615+
616+
617+class GetPathsTestCase(TestCase):
618+ """Test case for get_update_config and get_bin_cmd."""
619+
620+ TEST_EXE_NAME = 'test-exe'
621+ TEST_BIN_CMD_NAME = 'test-bin-cmd-name'
622+ TEST_PYTHON_BIN_NAME = 'test-python-bin-name'
623+
624+ def _run_get_bin_cmd(self, frozen):
625+ """Helper func to test get_bin_cmd."""
626+ self.patch(utils.common, "get_program_path",
627+ lambda x, **kwargs: self.TEST_BIN_CMD_NAME)
628+ self.patch(utils.common, '__file__',
629+ "fake/path/to/utils/common.py")
630+ return utils.common.get_bin_cmd(self.TEST_EXE_NAME)
631+
632+ def test_get_bin_cmd_frozen(self):
633+ """Test that we append 'python' from procutils when frozen."""
634+ self.patch(utils.common.procutils, "which",
635+ lambda x: [self.TEST_PYTHON_BIN_NAME])
636+ rv = self._run_get_bin_cmd(True)
637+ self.assertEqual(rv, [self.TEST_PYTHON_BIN_NAME,
638+ self.TEST_BIN_CMD_NAME])
639+
640+
641+class GetUpdateConfigTestCase(TestCase):
642+ """Test reading the config file"""
643+
644+ @defer.inlineCallbacks
645+ def setUp(self):
646+ yield super(GetUpdateConfigTestCase, self).setUp()
647+
648+ self.blank_conf = SafeConfigParser()
649+ self.good_conf = SafeConfigParser()
650+ self.good_conf.add_section(UPDATE_KEY)
651+ self.good_conf.set(UPDATE_KEY, URL_KEY, TEST_URL)
652+ self.good_conf.set(UPDATE_KEY, VERSION_ID_KEY,
653+ TEST_VERSION_ID)
654+ self.good_conf.set(UPDATE_KEY, CHANNEL_KEY,
655+ TEST_CHANNEL)
656+ self.good_conf.set(UPDATE_KEY, CHECK_KEY, TEST_CHECK)
657+
658+ self.patch(utils.common, 'load_config_paths',
659+ lambda x: 'test/confpath')
660+
661+ def test_cant_read(self):
662+ """Test that we return no_config when we can't read the cfg"""
663+ rv = utils.common.get_update_config()
664+ self.assertEqual(rv, (None, None, None, False))
665+
666+ def test_read_bad_file(self):
667+ """Test that we return no_config when we read a bad cfg file"""
668+ self.patch(utils.common, "SafeConfigParser",
669+ lambda: self.blank_conf)
670+
671+ self.patch(self.blank_conf, "read", lambda path: True)
672+ rv = utils.common.get_update_config()
673+ self.assertEqual(rv, (None, None, None, False))
674+
675+ def test_read_good_file(self):
676+ """test that we correctly read a good cfg file"""
677+ self.patch(utils.common, "SafeConfigParser",
678+ lambda: self.good_conf)
679+
680+ self.patch(self.good_conf, "read", lambda path: True)
681+ rv = utils.common.get_update_config()
682+ self.assertEqual(rv,
683+ (TEST_URL, TEST_VERSION_ID, TEST_CHANNEL, 1))
684+
685+
686+class CallUpdaterTestCase(TestCase):
687+ """Test calling the updater."""
688+
689+ UPDATE_BIN_CMD = ['path/to/updater']
690+ BUILDOUT_UPDATE_BIN_CMD = ['python', 'path/to/updater']
691+
692+ @defer.inlineCallbacks
693+ def setUp(self):
694+ """Set up common data"""
695+ yield super(CallUpdaterTestCase, self).setUp()
696+
697+ self.getProcessValueArgs = []
698+ self.custom_call_args = []
699+
700+ self.call_retval = 0
701+
702+ def fake_getProcessValue(exe, args):
703+ self.getProcessValueArgs.append((exe, args))
704+ return self.call_retval
705+
706+ self.patch(utils.common, 'getProcessValue',
707+ fake_getProcessValue)
708+
709+ def fake_custom_call(self, exe, args):
710+ """Mock custom call"""
711+ self.custom_call_args.append((exe, args))
712+
713+ @defer.inlineCallbacks
714+ def _call_call_updater(self, should_check, custom_call, install, frozen):
715+ """Helper to test call_udpater"""
716+
717+ self.patch(utils.common, 'get_update_config',
718+ lambda: (TEST_URL, TEST_VERSION_ID, TEST_CHANNEL,
719+ should_check))
720+
721+ self.patch(utils.common, 'get_bin_cmd',
722+ lambda x: self.UPDATE_BIN_CMD if frozen
723+ else self.BUILDOUT_UPDATE_BIN_CMD)
724+
725+ rv = yield utils.common.call_updater(custom_call, install)
726+ defer.returnValue(rv)
727+
728+ @defer.inlineCallbacks
729+ def test_do_not_check(self):
730+ """Test that we return False when config says don't check """
731+
732+ rv = yield self._call_call_updater(should_check=False,
733+ custom_call=None,
734+ install=False,
735+ frozen=False)
736+ self.assertEqual(rv, False)
737+
738+ @defer.inlineCallbacks
739+ def test_no_updater_cmd(self):
740+ """Test that we return False when get_bin_cmd fails."""
741+ def raise_in_get_bin_cmd(name):
742+ raise OSError()
743+
744+ self.patch(utils.common, 'get_bin_cmd', raise_in_get_bin_cmd)
745+ rv = yield utils.common.call_updater()
746+
747+ self.assertEqual(rv, False)
748+
749+ @defer.inlineCallbacks
750+ def test_update_check_frozen_nocustom_noinstall(self):
751+ """Test update check when frozen."""
752+ self.call_retval = 1
753+ rv = yield self._call_call_updater(should_check=True,
754+ custom_call=None,
755+ install=False,
756+ frozen=True)
757+ self.assertEqual(rv, True)
758+ self.assertEqual(self.getProcessValueArgs,
759+ [(self.UPDATE_BIN_CMD[0],
760+ ['--url', TEST_URL,
761+ '--current', TEST_VERSION_ID,
762+ '--release', TEST_CHANNEL])])
763+
764+ @defer.inlineCallbacks
765+ def test_update_check_unfrozen_nocustom_noinstall(self):
766+ """Test update check when not frozen."""
767+ self.call_retval = 1
768+ rv = yield self._call_call_updater(should_check=True,
769+ custom_call=None,
770+ install=False,
771+ frozen=False)
772+ self.assertEqual(rv, True)
773+ self.assertEqual(self.getProcessValueArgs,
774+ [(self.BUILDOUT_UPDATE_BIN_CMD[0],
775+ [self.BUILDOUT_UPDATE_BIN_CMD[1],
776+ '--url', TEST_URL,
777+ '--current', TEST_VERSION_ID,
778+ '--release', TEST_CHANNEL])])
779+
780+ @defer.inlineCallbacks
781+ def test_update_check_nocustom_install(self):
782+ """Test that we send --install when install=True"""
783+
784+ yield self._call_call_updater(should_check=True,
785+ custom_call=None,
786+ install=True,
787+ frozen=True)
788+ self.assertEqual(self.getProcessValueArgs,
789+ [(self.UPDATE_BIN_CMD[0],
790+ ['--url', TEST_URL,
791+ '--current', TEST_VERSION_ID,
792+ '--release', TEST_CHANNEL,
793+ '--install'])])
794+
795+ @defer.inlineCallbacks
796+ def test_update_check_custom_install(self):
797+ """Test that we send --install when install=True to the custom call"""
798+
799+ yield self._call_call_updater(should_check=True,
800+ custom_call=self.fake_custom_call,
801+ install=True,
802+ frozen=True)
803+ self.assertEqual(self.custom_call_args,
804+ [(self.UPDATE_BIN_CMD[0],
805+ ['--url', TEST_URL,
806+ '--current', TEST_VERSION_ID,
807+ '--release', TEST_CHANNEL,
808+ '--install'])])
809
810=== modified file 'ubuntuone/controlpanel/utils/tests/test_darwin.py'
811--- ubuntuone/controlpanel/utils/tests/test_darwin.py 2012-10-17 17:28:43 +0000
812+++ ubuntuone/controlpanel/utils/tests/test_darwin.py 2013-01-10 18:07:21 +0000
813@@ -19,7 +19,9 @@
814 import os
815 import sys
816
817-from collections import defaultdict
818+from Cocoa import NSURL
819+
820+from collections import defaultdict, namedtuple
821 from functools import partial
822
823 from twisted.internet import defer
824@@ -56,12 +58,28 @@
825 class InstallConfigTestCase(TestCase):
826 """Test install_config_and_daemons."""
827
828+ APP_PATH = "/path/to/Main.app/"
829+ TARGET_PATH = "TARGET_PATH"
830+
831 @defer.inlineCallbacks
832 def setUp(self):
833 """Set up multi-call checker."""
834 yield super(InstallConfigTestCase, self).setUp()
835 self._called = []
836
837+ self.non_overwrite_args = [((os.path.join(self.APP_PATH, 'Contents',
838+ 'Resources',
839+ 'syncdaemon.conf'),
840+ os.path.join(self.TARGET_PATH,
841+ 'syncdaemon.conf')), {}),
842+ ((os.path.join(self.APP_PATH, 'Contents',
843+ 'Resources', 'logging.conf'),
844+ os.path.join(self.TARGET_PATH,
845+ 'logging.conf')), {})]
846+ self.overwrite_args = [((os.path.join(self.APP_PATH, 'Contents',
847+ 'Resources', 'update.conf'),
848+ os.path.join(self.TARGET_PATH,
849+ 'update.conf')), {})]
850 self.patch(utils.darwin,
851 'check_and_install_fsevents_daemon',
852 lambda _: None)
853@@ -78,34 +96,45 @@
854 utils.install_config_and_daemons()
855 self.assertEqual(self._called, [])
856
857- def _test_copying_conf_files(self, exists):
858+ def _test_copying_conf_files(self, exists, src_mtime=0, dest_mtime=0):
859 """Call install_config_and_daemons, parameterize os.path.exists."""
860 sys.frozen = 'macosx_app'
861 self.addCleanup(delattr, sys, 'frozen')
862- self.patch(utils.darwin, 'save_config_path', lambda x: "TARGET_PATH")
863- self.patch(utils.darwin, '__file__', "/path/to/Main.app/ignore")
864+ self.patch(utils.darwin, 'save_config_path',
865+ lambda x: self.TARGET_PATH)
866+ self.patch(utils.darwin, '__file__',
867+ os.path.join(self.APP_PATH, "ignore"))
868 self.patch(os.path, "exists", lambda x: exists)
869 self.patch(utils.darwin.shutil, 'copyfile',
870 self._set_called)
871+
872+ def fake_stat(path):
873+ fakestat = namedtuple('fakestat', ['st_mtime'])
874+ if path.startswith(self.APP_PATH):
875+ return fakestat(src_mtime)
876+ else:
877+ return fakestat(dest_mtime)
878+
879+ self.patch(utils.os, 'stat', fake_stat)
880+
881 utils.install_config_and_daemons()
882
883- def test_copies_conf_files(self):
884+ def test_copies_conf_files_same(self):
885 """When frozen, we copy the conf files if they don't exist."""
886 self._test_copying_conf_files(False)
887- self.assertEqual(self._called,
888- [(('/path/to/Main.app/Contents/'
889- 'Resources/syncdaemon.conf',
890- 'TARGET_PATH/syncdaemon.conf'), {}),
891- (('/path/to/Main.app/Contents/'
892- 'Resources/logging.conf',
893- 'TARGET_PATH/logging.conf'),
894- {})])
895+ self.assertEqual(self._called, self.non_overwrite_args +
896+ self.overwrite_args)
897
898- def test_does_not_copy_conf_files(self):
899- """When frozen, we do not copy the conf files if they do exist."""
900- self._test_copying_conf_files(True)
901+ def test_does_not_copy_conf_files_same(self):
902+ """frozen: do not copy any files that exist if their mtime is new."""
903+ self._test_copying_conf_files(True, src_mtime=0, dest_mtime=1)
904 self.assertEqual(self._called, [])
905
906+ def test_only_copy_update_exist_same(self):
907+ """frz: only copy update.conf if files exist but src mtime newer."""
908+ self._test_copying_conf_files(True, src_mtime=1, dest_mtime=0)
909+ self.assertEqual(self._called, self.overwrite_args)
910+
911
912 class InstallDaemonTestCase(CallRecordingTestCase):
913 """Test fsevents daemon installation."""
914@@ -326,3 +355,63 @@
915 """Paths should be bytes, not unicode."""
916 is_bytes = [type(n) == type(b'') for n in self.folders]
917 self.assertNotIn(False, is_bytes)
918+
919+
920+class MockStandardUserDefaults(object):
921+ """Fake user defaults"""
922+
923+ def __init__(self, keyval):
924+ self.keyval = keyval
925+ self.setBool_args = []
926+
927+ def boolForKey_(self, key):
928+ return self.keyval
929+
930+ def setBool_forKey_(self, bval, key):
931+ self.setBool_args.append((bval, key))
932+
933+
934+class AddU1FolderToFavoritesTestCase(CallRecordingTestCase):
935+ """Test adding folder to favorites."""
936+
937+ @defer.inlineCallbacks
938+ def setUp(self):
939+ yield super(AddU1FolderToFavoritesTestCase, self).setUp()
940+ self.path = "/Users/a/Ubuntu%20One"
941+ self.testurl = NSURL.URLWithString_("file://localhost" +
942+ self.path)
943+
944+ self.patch(utils.darwin.os.path, "expanduser",
945+ lambda x: self.path)
946+ self.patch(utils.darwin, "LSSharedFileListCreate",
947+ lambda x, y, z: "fake-list")
948+ self.patch(utils.darwin, "kLSSharedFileListItemBeforeFirst", 1)
949+ self._patch_and_track(utils.darwin, [("LSSharedFileListInsertItemURL",
950+ None)])
951+
952+ def test_call_with_home_url_noflag(self):
953+ """Test adding correct URL when we haven't before."""
954+
955+ mock_sud = MockStandardUserDefaults(False)
956+ self.patch(utils.darwin, '_get_userdefaults',
957+ lambda: mock_sud)
958+
959+ utils.darwin.add_u1_folder_to_favorites()
960+ self.assertEqual(mock_sud.setBool_args,
961+ [(True, utils.darwin.ADDED_TO_FINDER_SIDEBAR_ONCE)])
962+ self.assertEqual(self._called['LSSharedFileListInsertItemURL'],
963+ [(("fake-list", 1, None, None, self.testurl, {}, []),
964+ {})])
965+
966+ def test_call_with_home_url_yesflag(self):
967+ """Test not re-adding URL when we've done it once before."""
968+
969+ mock_sud = MockStandardUserDefaults(True)
970+ self.patch(utils.darwin, '_get_userdefaults',
971+ lambda: mock_sud)
972+
973+ utils.darwin.add_u1_folder_to_favorites()
974+
975+ self.assertEqual(mock_sud.setBool_args, [])
976+
977+ self.assertEqual(self._called['LSSharedFileListInsertItemURL'], [])
978
979=== modified file 'ubuntuone/controlpanel/utils/tests/test_windows.py'
980--- ubuntuone/controlpanel/utils/tests/test_windows.py 2012-05-16 14:01:27 +0000
981+++ ubuntuone/controlpanel/utils/tests/test_windows.py 2013-01-10 18:07:21 +0000
982@@ -23,7 +23,7 @@
983
984 from ubuntuone.controlpanel import utils
985 from ubuntuone.controlpanel.tests import TestCase
986-from ubuntuone.devtools.testcases import skipIfJenkins
987+from ubuntuone.devtools.testcases import skipIfJenkins, skipIf
988
989 # let me use protected methods
990 # pylint: disable=W0212
991@@ -65,8 +65,6 @@
992 """Prepare for the diff tests."""
993 yield super(AutoupdaterTestCase, self).setUp()
994 self._base_path = r'path\to\exe'
995- self.auto_update_path = os.path.join(self._base_path,
996- utils.windows.AUTOUPDATE_EXE_NAME)
997 self.return_from_call = 0
998 self.command = None
999 self.args = []
1000@@ -77,9 +75,11 @@
1001 self.args = args
1002 return self.return_from_call
1003
1004- self.patch(utils.windows, 'getProcessValue', fake_execute_process)
1005- self.patch(utils.windows, 'get_exe_path',
1006+ self.patch(utils.common, 'getProcessValue', fake_execute_process)
1007+ self.patch(utils.windows, 'get_bin_cmd',
1008 lambda exe_name: os.path.join(self._base_path, exe_name))
1009+ self.patch(utils.common, 'get_update_config',
1010+ lambda: ("URL", "VERSION", "CHANNEL", "CHECK"))
1011
1012 @defer.inlineCallbacks
1013 def test_are_updates_present_true(self):
1014@@ -87,13 +87,15 @@
1015 # the idea is simple, set the value to be returned from
1016 # the fake call, assert that we get true and also that
1017 # we did use the correct parameters.
1018- self.return_from_call = 0
1019+ self.return_from_call = 1
1020 are_present = yield utils.are_updates_present()
1021 self.assertTrue(are_present, 'Updates should be present.')
1022 # lets assert that we did use the correct args
1023- expected_args = ('--mode', 'unattended')
1024+ expected_args = [
1025+ utils.common.get_bin_cmd(utils.common.UPDATE_BIN_NAME)[1],
1026+ '--url', 'URL', '--current', 'VERSION',
1027+ '--release', 'CHANNEL']
1028 self.assertEqual(expected_args, self.args)
1029- self.assertEqual(self.command, self.auto_update_path)
1030
1031 @defer.inlineCallbacks
1032 def test_are_updates_present_false(self):
1033@@ -103,16 +105,22 @@
1034 are_present = yield utils.are_updates_present()
1035 self.assertFalse(are_present, 'Updates should NOT be present.')
1036 # lets assert that we did use the correct args
1037- expected_args = ('--mode', 'unattended')
1038+ expected_args = [
1039+ utils.common.get_bin_cmd(utils.common.UPDATE_BIN_NAME)[1],
1040+ '--url', 'URL', '--current', 'VERSION',
1041+ '--release', 'CHANNEL']
1042 self.assertEqual(expected_args, self.args)
1043- self.assertEqual(self.command, self.auto_update_path)
1044
1045 def test_perform_update(self):
1046 """Test the method that performs the update."""
1047 self.patch(utils.windows.win32api, 'ShellExecute', self._set_called)
1048 utils.perform_update()
1049- args = (None, 'runas', self.auto_update_path,
1050- '--unattendedmodeui none', '', 0)
1051+ args = [utils.common.get_bin_cmd(utils.common.UPDATE_BIN_NAME)[1],
1052+ '--url', 'URL', '--current', 'VERSION',
1053+ '--release', 'CHANNEL', '--install']
1054+ args = (None, 'runas',
1055+ utils.common.get_bin_cmd(utils.common.UPDATE_BIN_NAME)[0],
1056+ ' '.join(args), '', 0)
1057 self.assertEqual(self._called, (args, {}))
1058
1059
1060@@ -247,72 +255,7 @@
1061 self.test_special_folders(names=('PERSONAL', 'MYMUSIC', 'MYPICTURES'))
1062
1063
1064-class GetExePathTestCase(FrozenTestCase):
1065- """Test the path calculator when sys is frozen."""
1066-
1067- @defer.inlineCallbacks
1068- def setUp(self):
1069- """Set the different tests."""
1070- yield super(GetExePathTestCase, self).setUp()
1071- self.called = []
1072- self.exists = True
1073-
1074- def fake_abspath(path):
1075- """Fake os.path.abspath."""
1076- self.called.append('os.path.abspath')
1077- return path
1078-
1079- def fake_dirname(path):
1080- """Fake os.path.dirname."""
1081- self.called.append('os.path.dirname')
1082- return path
1083-
1084- def fake_exists(path):
1085- """Fake os.path.exists."""
1086- self.called.append('os.path.exists')
1087- return self.exists
1088-
1089- # patch the os.path functions used
1090- self.patch(utils.windows.os.path, 'abspath', fake_abspath)
1091- self.patch(utils.windows.os.path, 'dirname', fake_dirname)
1092- self.patch(utils.windows.os.path, 'exists', fake_exists)
1093-
1094- def test_get_exe_path(self):
1095- """Test the method used to get the autoupdate."""
1096- path = utils.windows.get_exe_path(exe_name=SOME_EXE_NAME)
1097-
1098- self.assertEqual(os.path.join(self.executable, SOME_EXE_NAME), path)
1099-
1100- expected = ['os.path.abspath', 'os.path.dirname', 'os.path.dirname',
1101- 'os.path.exists']
1102- self.assertEqual(expected, self.called)
1103-
1104- def test_get_exe_path_not_present(self):
1105- """Test the method used to get the autoupdate."""
1106- self.exists = False
1107-
1108- # called method and assert that we have the correct result
1109- path = utils.windows.get_exe_path(exe_name=SOME_EXE_NAME)
1110- self.assertTrue(path is None)
1111-
1112-
1113-class GetExePathNotFrozenTestCase(GetExePathTestCase):
1114- """Test the path calculator when sys is not frozen."""
1115-
1116- frozen = None
1117-
1118- def test_get_exe_path(self):
1119- """Test the method used to get the autoupdate."""
1120- self.patch(utils.windows, '__file__', self.executable)
1121-
1122- path = utils.windows.get_exe_path(exe_name=SOME_EXE_NAME)
1123- self.assertEqual(os.path.join(self.executable, SOME_EXE_NAME), path)
1124-
1125- expected = ['os.path.dirname', 'os.path.dirname', 'os.path.dirname',
1126- 'os.path.exists']
1127- self.assertEqual(expected, self.called)
1128-
1129-
1130+@skipIf(not getattr(sys, "frozen", False), "Only applicable when frozen")
1131 class UninstallApplicationTestCase(FrozenTestCase):
1132 """Test the uninstall_application helper when sys is frozen."""
1133
1134@@ -327,7 +270,7 @@
1135 utils.uninstall_application()
1136
1137 exe_name = utils.windows.UNINSTALL_EXE_NAME
1138- uninstall_path = utils.windows.get_exe_path(exe_name=exe_name)
1139+ uninstall_path = utils.common.get_bin_cmd(exe_name=exe_name)[0]
1140 self.assertEqual(self._called,
1141 ((None, '', uninstall_path, '--mode win32', '', 0), {}))
1142
1143
1144=== modified file 'ubuntuone/controlpanel/utils/windows.py'
1145--- ubuntuone/controlpanel/utils/windows.py 2012-04-05 14:52:55 +0000
1146+++ ubuntuone/controlpanel/utils/windows.py 2013-01-10 18:07:21 +0000
1147@@ -27,32 +27,15 @@
1148 from win32com.shell import shell, shellcon
1149 # pylint: enable=F0401
1150 from twisted.internet import defer
1151-from twisted.internet.utils import getProcessValue
1152
1153+from ubuntuone.controlpanel.utils.common import (call_updater, get_bin_cmd)
1154 from ubuntuone.controlpanel.logger import setup_logging
1155
1156 logger = setup_logging('utils.windows')
1157-AUTOUPDATE_EXE_NAME = 'autoupdate-windows.exe'
1158 AUTORUN_KEY = r"Software\Microsoft\Windows\CurrentVersion\Run"
1159 UNINSTALL_EXE_NAME = 'uninstall.exe'
1160
1161
1162-def get_exe_path(exe_name):
1163- """Return the path in which the autoupdate command is found."""
1164- if getattr(sys, 'frozen', False):
1165- exec_path = os.path.abspath(sys.executable)
1166- else:
1167- exec_path = os.path.dirname(__file__)
1168-
1169- result = None
1170- folder = os.path.dirname(os.path.dirname(exec_path))
1171- exe_path = os.path.join(folder, exe_name)
1172- if os.path.exists(exe_path):
1173- result = exe_path
1174-
1175- return result
1176-
1177-
1178 def add_to_autostart():
1179 """Add syncdaemon to the session's autostart."""
1180 if getattr(sys, "frozen", False):
1181@@ -74,19 +57,15 @@
1182 @defer.inlineCallbacks
1183 def are_updates_present():
1184 """Return if there are updates for Ubuntu One."""
1185- result = False
1186- retcode = None
1187- update_path = get_exe_path(exe_name=AUTOUPDATE_EXE_NAME)
1188- if update_path is not None:
1189- # If there is an update present we will get 0, non-zero otherwise
1190- retcode = yield getProcessValue(update_path, args=('--mode',
1191- 'unattended'), path=os.path.dirname(update_path))
1192- result = retcode == 0
1193- logger.debug('are_updates_present: update path: %r, return code: %r,'
1194- ' result: %r', update_path, retcode, result)
1195+ result = yield call_updater(install=False)
1196 defer.returnValue(result)
1197
1198
1199+def call_elevated(exe, args):
1200+ """ShellExecute wrapper that uses 'runas' to elevate."""
1201+ win32api.ShellExecute(None, "runas", exe, " ".join(args), "", 0)
1202+
1203+
1204 def default_folders(user_home=None):
1205 """Return a list of the folders to add by default."""
1206 # as per http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181,
1207@@ -112,16 +91,14 @@
1208
1209
1210 def perform_update():
1211- """Spawn the autoupdate process and call the stop function."""
1212- update_path = get_exe_path(exe_name=AUTOUPDATE_EXE_NAME)
1213- if update_path is not None:
1214- # lets call the updater with the commands that are required,
1215- win32api.ShellExecute(None, 'runas', update_path,
1216- '--unattendedmodeui none', '', 0)
1217+ """Spawn the autoupdate process, which will eventually kill us."""
1218+ call_updater(call_elevated, install=True)
1219
1220
1221 def uninstall_application():
1222 """Uninstall Ubuntu One."""
1223- uninstall_path = get_exe_path(exe_name=UNINSTALL_EXE_NAME)
1224- if uninstall_path is not None:
1225- win32api.ShellExecute(None, '', uninstall_path, '--mode win32', '', 0)
1226+ if getattr(sys, "frozen", False):
1227+ uninstall_path = get_bin_cmd(UNINSTALL_EXE_NAME)[0]
1228+ if uninstall_path is not None:
1229+ win32api.ShellExecute(None, '', uninstall_path,
1230+ '--mode win32', '', 0)

Subscribers

People subscribed via source and target branches

to all changes: