Merge lp:~nataliabidart/ubuntuone-windows-installer/stable-3-0-update into lp:ubuntuone-windows-installer/stable-3-0

Proposed by Natalia Bidart
Status: Merged
Approved by: Natalia Bidart
Approved revision: 91
Merged at revision: 91
Proposed branch: lp:~nataliabidart/ubuntuone-windows-installer/stable-3-0-update
Merge into: lp:ubuntuone-windows-installer/stable-3-0
Diff against target: 671 lines (+315/-75)
10 files modified
data/qt/congratulations.ui (+5/-16)
run-tests.bat (+1/-1)
setup.py (+1/-1)
ubuntuone_installer/gui/qt/gui.py (+61/-12)
ubuntuone_installer/gui/qt/tests/test_gui.py (+149/-34)
ubuntuone_installer/gui/qt/utils/__init__.py (+6/-0)
ubuntuone_installer/gui/qt/utils/tests/test_common.py (+9/-0)
ubuntuone_installer/gui/qt/utils/tests/test_windows.py (+48/-4)
ubuntuone_installer/gui/qt/utils/windows.py (+34/-6)
ubuntuone_installer/tests/__init__.py (+1/-1)
To merge this branch: bzr merge lp:~nataliabidart/ubuntuone-windows-installer/stable-3-0-update
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Review via email: mp+86297@code.launchpad.net

Commit message

[ Diego Sarmentero <email address hidden> ]
  - Fixed lint issues.
  - Fixed: When logging in with an no-yet-validated account, there is no useful
    message (LP: #851885).
  - Fixed congratulations page (LP: #859711).

[ Manuel de la Pena <email address hidden> ]
  - Put all the different pieces of the migration together so that we perform
    the uninstall and migtration of the data if the user has the very
    old first beta.
  - Fixes the code that will call the autoupdate-windows.exe. The idea is that
    in the release the .exe will be in a diff location to avoid dll collisions.
  - Changed the import from ubuntuone-dev-tools so that we do not use the
    deprecated API.

[ Natalia B. Bidart <email address hidden> ]
  - Pass module for test to u1trial properly.

Description of the change

All green in ubuntu, and windows (tested windows 7).

IRL tested on windows.

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

Looks good!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/qt/congratulations.ui'
2--- data/qt/congratulations.ui 2011-09-08 14:49:31 +0000
3+++ data/qt/congratulations.ui 2011-12-19 21:30:29 +0000
4@@ -7,7 +7,7 @@
5 <x>0</x>
6 <y>0</y>
7 <width>622</width>
8- <height>331</height>
9+ <height>362</height>
10 </rect>
11 </property>
12 <property name="windowTitle">
13@@ -21,20 +21,6 @@
14 <number>0</number>
15 </property>
16 <item>
17- <widget class="QLabel" name="label">
18- <property name="font">
19- <font>
20- <pointsize>14</pointsize>
21- <weight>75</weight>
22- <bold>true</bold>
23- </font>
24- </property>
25- <property name="text">
26- <string>Congratulations!</string>
27- </property>
28- </widget>
29- </item>
30- <item>
31 <layout class="QHBoxLayout" name="horizontalLayout_2">
32 <item>
33 <spacer name="horizontalSpacer">
34@@ -50,7 +36,7 @@
35 </spacer>
36 </item>
37 <item>
38- <widget class="QLabel" name="label_2">
39+ <widget class="QLabel" name="image_label">
40 <property name="text">
41 <string/>
42 </property>
43@@ -83,6 +69,9 @@
44 </item>
45 <item>
46 <widget class="QWidget" name="progressContainer" native="true">
47+ <property name="layoutDirection">
48+ <enum>Qt::RightToLeft</enum>
49+ </property>
50 <layout class="QHBoxLayout" name="horizontalLayout">
51 <property name="spacing">
52 <number>0</number>
53
54=== modified file 'run-tests.bat'
55--- run-tests.bat 2011-08-24 17:04:02 +0000
56+++ run-tests.bat 2011-12-19 21:30:29 +0000
57@@ -66,4 +66,4 @@
58 "%PYTHONEXEPATH%\python.exe" setup.py build
59 ECHO Running tests
60 :: execute the tests with a number of ignored linux only modules
61-"%PYTHONEXEPATH%\python.exe" "%PYTHONEXEPATH%\Scripts\u1trial" -i "test_linux.py" ubuntuone_installer --gui --reactor=qt4
62+"%PYTHONEXEPATH%\python.exe" "%PYTHONEXEPATH%\Scripts\u1trial" -i "test_linux.py" --gui --reactor=qt4 -c ubuntuone_installer
63
64=== modified file 'setup.py'
65--- setup.py 2011-12-01 19:30:38 +0000
66+++ setup.py 2011-12-19 21:30:29 +0000
67@@ -228,7 +228,7 @@
68
69 DistUtilsExtra.auto.setup(
70 name='ubuntuone-installer',
71- version='2.99',
72+ version='2.99.0',
73 license='GPL v3',
74 author='Roberto Alsina',
75 author_email='roberto.alsina@canonical.com',
76
77=== modified file 'ubuntuone_installer/gui/qt/gui.py'
78--- ubuntuone_installer/gui/qt/gui.py 2011-11-11 20:36:16 +0000
79+++ ubuntuone_installer/gui/qt/gui.py 2011-12-19 21:30:29 +0000
80@@ -1,8 +1,4 @@
81 # -*- coding: utf-8 -*-
82-
83-# Authors: Alejandro J. Cura <alecu@canonical.com>
84-# Roberto Alsina <roberto.alsina@canonical.com>
85-# Diego Sarmentero <diego.sarmentero@canonical.com>
86 #
87 # Copyright 2011 Canonical Ltd.
88 #
89@@ -84,31 +80,71 @@
90 from ubuntuone_installer.gui.qt.side_widget import SideWidget
91
92 _ = gettext.gettext
93+CONGRATULATIONS = _("Congratulations")
94+CREDENTIALS_ERROR_TITLE = _("Error getting credentials")
95+CREDENTIALS_ERROR = _('Application will close.\n\n%r')
96 SIGN_IN = _("Sign in to Ubuntu One")
97 SIGN_IN_SUBTITLE = _("Sign in with your existing Ubuntu One"
98 " username and password.")
99-TITLE_STYLE = "<span style=\"font-size:24px\">%s</span>"
100-CREDENTIALS_ERROR_TITLE = _("Error getting credentials")
101-CREDENTIALS_ERROR = _('Application will close.\n\n%r')
102 SKIP_TOUR = _("Skip tour, go to Dashboard")
103 START_SETUP = _("Start setup")
104 SUCCESSFUL_LOGIN = _("Login successful")
105+TITLE_STYLE = "<span style=\"font-size:24px\">%s</span>"
106 UPDATE_TITLE = _("Updates are available")
107 UPDATE_SOFTWARE = _("There is a new version available. "
108 "Do you want perform an upgrade?")
109+REMOVE_OLD_BETA_TITLE = _("Remove old Beta")
110+REMOVE_OLD_BETA = _("The old Ubuntu One Beta is installed in your system. Do "
111+ "you want to uninstall it?")
112+REMOVE_OLD_BETA_ERROR = _("There was an error uninstall the old beta. Please "
113+ "do this step manually")
114+MIGRATE_OLD_BETA_DATA_TITLE = _("Migrate old data")
115+MIGRATE_OLD_BETA = _("Do you want to migrate the files from the old Ubuntu "
116+ "One Beta location to the new one?")
117+MIGRATE_OLD_BETA_DATA_ERROR = _("There was an error migrating your data. "
118+ "Please do this step manually.")
119+
120 # Invalid name logger
121 # pylint: disable=C0103
122 logger = setup_logging('qt.gui')
123 # pylint: enable=C0103
124
125
126+def _ask_user_question(title, question):
127+ """Ask the user a Yes/No question."""
128+ result = QtGui.QMessageBox.question(None, title, question,
129+ QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
130+ return result == QtGui.QMessageBox.Yes
131+
132+
133 def user_wants_to_update():
134 """Ask the user if he really wants to update the software."""
135- result = QtGui.QMessageBox.question(None, UPDATE_TITLE, UPDATE_SOFTWARE,
136- QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
137- if result == QtGui.QMessageBox.Yes:
138- return True
139- return False
140+ return _ask_user_question(UPDATE_TITLE, UPDATE_SOFTWARE)
141+
142+
143+def user_wants_to_remove_old_beta():
144+ """Ask the user if he really wants to remove the old beta."""
145+ return _ask_user_question(REMOVE_OLD_BETA_TITLE, REMOVE_OLD_BETA)
146+
147+
148+def user_wants_to_migrate_data():
149+ """Ask the user if he really wants to migrate the data."""
150+ return _ask_user_question(MIGRATE_OLD_BETA_DATA_TITLE, MIGRATE_OLD_BETA)
151+
152+
153+def _warn_user(title, message):
154+ """Warn the user."""
155+ QtGui.QMessageBox.warning(None, title, message, QtGui.QMessageBox.Ok)
156+
157+
158+def warn_user_beta_not_removed():
159+ """Let the user know that the data was not migrated."""
160+ _warn_user(REMOVE_OLD_BETA_TITLE, REMOVE_OLD_BETA_ERROR)
161+
162+
163+def warn_user_data_not_migrated():
164+ """Let the user know that the data was not migrated."""
165+ _warn_user(MIGRATE_OLD_BETA_DATA_TITLE, MIGRATE_OLD_BETA_DATA_ERROR)
166
167
168 class LicensePage(SSOWizardPage):
169@@ -213,6 +249,10 @@
170 self.ui.sign_in_button.style().polish(
171 self.ui.sign_in_button)
172
173+ def cleanupPage(self):
174+ """Reset the state of the wizard if Verification code was visited."""
175+ self.wizard()._next_id = None
176+
177
178 class SuccessPage(SSOWizardPage):
179 """Shown after SSO login, before setup."""
180@@ -266,6 +306,7 @@
181 super(CongratulationsPage, self).__init__(
182 congratulations_ui.Ui_Form(), None, parent)
183 self.setFinalPage(True)
184+ self.setTitle(CONGRATULATIONS)
185
186 # Invalid names of Qt-inherited methods
187 # pylint: disable=C0103
188@@ -305,6 +346,7 @@
189 # definition of the signals raised by the widget (for SSO)
190 recoverableError = QtCore.pyqtSignal('QString', 'QString')
191 loginSuccess = QtCore.pyqtSignal('QString', 'QString')
192+ registrationIncomplete = QtCore.pyqtSignal('QString', 'QString')
193 registrationSuccess = QtCore.pyqtSignal('QString', 'QString')
194 userCancellation = QtCore.pyqtSignal('QString')
195
196@@ -412,6 +454,7 @@
197 self.reset_password_page_id = self.addPage(self.reset_password)
198
199 self.loginSuccess.connect(self.login_success_slot)
200+ self.registrationIncomplete.connect(self.registration_incomplete)
201 self.registrationSuccess.connect(self.registration_success_slot)
202
203 # End of SSO pages
204@@ -470,6 +513,12 @@
205 self.next()
206 self._next_id = self.SYNC_NOW_OR_LATER_PAGE
207
208+ def registration_incomplete(self):
209+ """Called when registration wasn't completed."""
210+ self._next_id = self.email_verification_page_id
211+ self.next()
212+ self._next_id = self.SUCCESS_PAGE
213+
214 def registration_success_slot(self):
215 """Called on successful registration."""
216 self._next_id = self.SUCCESS_PAGE
217
218=== modified file 'ubuntuone_installer/gui/qt/tests/test_gui.py'
219--- ubuntuone_installer/gui/qt/tests/test_gui.py 2011-11-11 20:36:16 +0000
220+++ ubuntuone_installer/gui/qt/tests/test_gui.py 2011-12-19 21:30:29 +0000
221@@ -347,6 +347,36 @@
222 folders_page.on_check_settings_button_clicked()
223 self.assertEqual(self.ui.currentId(), self.ui.preferences_page_id)
224
225+ def test_current_user_sign_in_page_clenaup(self):
226+ """Check CurrentUserSignIn cleanupPage method."""
227+ current_signin_page = self.ui.page(self.ui.current_user_page_id)
228+
229+ # Show the current id page
230+ self.ui.setStartId(self.ui.current_user_page_id)
231+ self.ui.restart()
232+ self.ui.show()
233+ self.addCleanup(self.ui.hide)
234+
235+ self.ui._next_id = self.ui.SUCCESS_PAGE
236+ current_signin_page.cleanupPage()
237+ # pylint: disable=W0212
238+ self.assertEqual(self.ui._next_id, None)
239+ # pylint: enable=W0212
240+
241+ def test_registration_incomplete(self):
242+ """Check the registration_incomplete slot."""
243+ self.ui.setStartId(self.ui.current_user_page_id)
244+ self.ui.restart()
245+ self.ui.show()
246+ self.addCleanup(self.ui.hide)
247+
248+ self.ui.registration_incomplete()
249+ self.assertEqual(self.ui.currentId(),
250+ self.ui.email_verification_page_id)
251+ # pylint: disable=W0212
252+ self.assertEqual(self.ui._next_id, self.ui.SUCCESS_PAGE)
253+ # pylint: enable=W0212
254+
255 def test_critical(self):
256 """Show a critical popup, but first hide the overlay."""
257 self.assertEqual(self.ui.overlay.hide_counter, 1)
258@@ -495,6 +525,19 @@
259 self.assertEqual(self._called, False)
260 self.assertEqual(FakeAreYouSure.shown, False)
261
262+ def test_congratulations_page_title(self):
263+ """Check congratulations page title."""
264+ congratulations_page = self.ui.page(self.ui.CONGRATULATIONS_PAGE)
265+ self.ui.setStartId(self.ui.CONGRATULATIONS_PAGE)
266+ self.ui.restart()
267+ self.ui.show()
268+ self.addCleanup(self.ui.hide)
269+ congratulations_page.initializePage()
270+ self.ui.show()
271+ self.addCleanup(self.ui.hide)
272+ self.assertEqual(congratulations_page.header.title_label.text(),
273+ gui.CONGRATULATIONS)
274+
275 def test_current_user_controller_parameters(self):
276 """Compare controller parameters with expected values."""
277 self.assertEqual(self.ui.current_user_controller.args,
278@@ -615,6 +658,7 @@
279
280 currentIdChanged = FakeSignal()
281 loginSuccess = FakeSignal()
282+ registrationIncomplete = FakeSignal()
283 registrationSuccess = FakeSignal()
284 userCancellation = FakeSignal()
285 shown = False
286@@ -716,51 +760,122 @@
287 self.assertTrue(self.ui.ui.existing_account_button.isDefault())
288
289
290-class UpgradeQuestion(BaseTestCase):
291+class MessageBoxTestCase(BaseTestCase):
292 """Test the dialog that ask the user if he wants to upgrade."""
293
294 @defer.inlineCallbacks
295 def setUp(self):
296 """Set the tests."""
297- yield super(UpgradeQuestion, self).setUp()
298+ yield super(MessageBoxTestCase, self).setUp()
299 self.answer = 0
300 self.parent = None
301 self.title = None
302 self.text = None
303 self.yes_button = None
304 self.no_button = None
305-
306- def fake_question(parent, title, text, yes_button,
307- no_button):
308- """Fake asking a question."""
309- self.parent = parent
310- self.title = title
311- self.text = text
312- self.yes_button = yes_button
313- self.no_button = no_button
314- return self.answer
315-
316- self.patch(gui.QtGui.QMessageBox, 'question', fake_question)
317-
318- def user_wants_to_update_true(self):
319- """Test the question."""
320+ self.ok_button = None
321+
322+ class FakeMessageBox(object):
323+ """A fake message box."""
324+
325+ No = 'No'
326+ Yes = 'Yes'
327+ Ok = 'Ok'
328+
329+ @classmethod
330+ def question(cls, parent, title, text, yes_button,
331+ no_button):
332+ """Fake asking a question."""
333+ self.parent = parent
334+ self.title = title
335+ self.text = text
336+ self.yes_button = yes_button
337+ self.no_button = no_button
338+ return self.answer
339+
340+ @classmethod
341+ def warning(cls, parent, title, text, ok_button):
342+ """Fake warning the user."""
343+ self.parent = parent
344+ self.title = title
345+ self.text = text
346+ self.ok_button = ok_button
347+ return self.answer
348+
349+ self.patch(gui.QtGui, 'QMessageBox', FakeMessageBox)
350+
351+ def _assert_question(self, question_title, question_text):
352+ """Assert the execution of a question."""
353+ self.assertEqual(None, self.parent)
354+ self.assertEqual(self.title, question_title)
355+ self.assertEqual(self.text, question_text)
356+ self.assertEqual(self.yes_button, gui.QtGui.QMessageBox.Yes)
357+ self.assertEqual(self.no_button, gui.QtGui.QMessageBox.No)
358+
359+ def _assert_true_question(self, question_fn, question_title,
360+ question_text):
361+ """Assert a positive answer to a question."""
362 self.answer = gui.QtGui.QMessageBox.Yes
363- self.assertTrue(gui.user_wants_to_update(), 'User wants to update.')
364- # lets assert the parameters
365- self.assertTrue(None, self.parent)
366- self.assertTrue(self.title, gui.UPDATE_TITLE)
367- self.assertTrue(self.text, gui.UPDATE_SOFTWARE)
368- self.assertTrue(self.yes_button, gui.QtGui.QMessageBox.Yes)
369- self.assertTrue(self.no_button, gui.QtGui.QMessageBox.No)
370+ self.assertTrue(question_fn())
371+ self._assert_question(question_title, question_text)
372
373- def user_wants_to_update_false(self):
374- """Test the question."""
375+ def _assert_false_question(self, question_fn, question_title,
376+ question_text):
377+ """Assert a negative answer to a question."""
378 self.answer = gui.QtGui.QMessageBox.No
379- msg = 'user_wants_to_update must return False when the answer is No.'
380- self.assertFalse(gui.user_wants_to_update(), msg)
381- # lets assert the parameters
382- self.assertTrue(None, self.parent)
383- self.assertTrue(self.title, gui.UPDATE_TITLE)
384- self.assertTrue(self.text, gui.UPDATE_SOFTWARE)
385- self.assertTrue(self.yes_button, gui.QtGui.QMessageBox.Yes)
386- self.assertTrue(self.no_button, gui.QtGui.QMessageBox.No)
387+ self.assertFalse(question_fn())
388+ self._assert_question(question_title, question_text)
389+
390+ def test_user_wants_to_update_true(self):
391+ """Test the question."""
392+ self._assert_true_question(gui.user_wants_to_update, gui.UPDATE_TITLE,
393+ gui.UPDATE_SOFTWARE)
394+
395+ def test_user_wants_to_update_false(self):
396+ """Test the question."""
397+ self._assert_false_question(gui.user_wants_to_update, gui.UPDATE_TITLE,
398+ gui.UPDATE_SOFTWARE)
399+
400+ def test_user_wants_to_remove_true(self):
401+ """Test the question."""
402+ self._assert_true_question(gui.user_wants_to_remove_old_beta,
403+ gui.REMOVE_OLD_BETA_TITLE,
404+ gui.REMOVE_OLD_BETA)
405+
406+ def test_user_wants_to_remove_false(self):
407+ """Test the question."""
408+ self._assert_false_question(gui.user_wants_to_remove_old_beta,
409+ gui.REMOVE_OLD_BETA_TITLE,
410+ gui.REMOVE_OLD_BETA)
411+
412+ def test_user_wants_to_migrate_true(self):
413+ """Test the question."""
414+ self._assert_true_question(gui.user_wants_to_migrate_data,
415+ gui.MIGRATE_OLD_BETA_DATA_TITLE,
416+ gui.MIGRATE_OLD_BETA)
417+
418+ def test_user_wants_to_migrate_false(self):
419+ """Test the question."""
420+ self._assert_false_question(gui.user_wants_to_migrate_data,
421+ gui.MIGRATE_OLD_BETA_DATA_TITLE,
422+ gui.MIGRATE_OLD_BETA)
423+
424+ def _assert_warn_user(self, warn_fn, title, text):
425+ """Assert waning a user."""
426+ self.assertEqual(None, warn_fn())
427+ self.assertEqual(None, self.parent)
428+ self.assertEqual(self.title, title)
429+ self.assertEqual(self.text, text)
430+ self.assertEqual(self.ok_button, gui.QtGui.QMessageBox.Ok)
431+
432+ def test_warn_user_data_migration(self):
433+ """Test warning the user."""
434+ self._assert_warn_user(gui.warn_user_data_not_migrated,
435+ gui.MIGRATE_OLD_BETA_DATA_TITLE,
436+ gui.MIGRATE_OLD_BETA_DATA_ERROR)
437+
438+ def test_warn_user_old_app_removal(self):
439+ """Test warning the user."""
440+ self._assert_warn_user(gui.warn_user_beta_not_removed,
441+ gui.REMOVE_OLD_BETA_TITLE,
442+ gui.REMOVE_OLD_BETA_ERROR)
443
444=== modified file 'ubuntuone_installer/gui/qt/utils/__init__.py'
445--- ubuntuone_installer/gui/qt/utils/__init__.py 2011-11-11 19:27:39 +0000
446+++ ubuntuone_installer/gui/qt/utils/__init__.py 2011-12-19 21:30:29 +0000
447@@ -42,6 +42,7 @@
448 uninstall_old_beta = windows.uninstall_old_beta
449 migrate_old_data = windows.migrate_old_data
450 check_updates = windows.check_updates
451+ perform_old_beta_data_migration = windows.perform_old_beta_data_migration
452 else:
453 from ubuntuone_installer.gui.qt.utils import linux
454 uninstall_application = linux.uninstall_application
455@@ -54,6 +55,7 @@
456 uninstall_old_beta = lambda *args, **kwargs: None
457 migrate_old_data = lambda *args, **kwargs: None
458 check_updates = lambda *args, **kwargs: None
459+ perform_old_beta_data_migration = lambda *args, **kwargs: None
460 # pylint: enable=C0103
461
462
463@@ -76,6 +78,10 @@
464 logger.info('Updates checked, stopping.')
465 stop_cb()
466 else: # No credentials
467+ # if there are no credentials it usually means that we
468+ # are installing the application, before we do anything
469+ # lets check if the old beta is present
470+ yield perform_old_beta_data_migration(gui)
471 logger.info('Got empty credentials, starting wizard app.')
472 window = gui.MainWindow(close_callback=stop_cb,
473 installing=installing)
474
475=== modified file 'ubuntuone_installer/gui/qt/utils/tests/test_common.py'
476--- ubuntuone_installer/gui/qt/utils/tests/test_common.py 2011-11-11 19:28:10 +0000
477+++ ubuntuone_installer/gui/qt/utils/tests/test_common.py 2011-12-19 21:30:29 +0000
478@@ -69,11 +69,19 @@
479
480 self.start_cp = lambda with_icon: \
481 self.called.extend(('start_cp', with_icon))
482+
483 self.patch(utils, 'start_control_panel', self.start_cp)
484
485 self.check_updates = lambda _: self.called.append('check_updates')
486+
487 self.patch(utils, 'check_updates', self.check_updates)
488
489+ self.migrate_data_cb = lambda gui: \
490+ self.called.extend(('migrate_data_cb', gui))
491+
492+ self.patch(utils, 'perform_old_beta_data_migration',
493+ self.migrate_data_cb)
494+
495 self.patch(gui, 'MainWindow', FakeWindow)
496
497 @defer.inlineCallbacks
498@@ -110,3 +118,4 @@
499 self.assertTrue(FakeWindow.visible)
500 msgs = ('Got empty credentials', 'starting wizard')
501 self.assertTrue(self.memento.check_info(*msgs))
502+ self.assertEqual(self.called, ['migrate_data_cb', gui])
503
504=== modified file 'ubuntuone_installer/gui/qt/utils/tests/test_windows.py'
505--- ubuntuone_installer/gui/qt/utils/tests/test_windows.py 2011-11-11 19:27:39 +0000
506+++ ubuntuone_installer/gui/qt/utils/tests/test_windows.py 2011-12-19 21:30:29 +0000
507@@ -37,6 +37,9 @@
508 from ubuntuone_installer.gui.qt import utils
509 from ubuntuone_installer.gui.qt.tests import BaseTestCase
510
511+# we want to test private methods
512+# pylint:disable=W0212
513+
514
515 class UninstallerTestCase(BaseTestCase):
516
517@@ -395,7 +398,7 @@
518 self.patch(utils.windows, 'deferToThread',
519 fake_msi_install_product)
520 self.assertFailure(utils.uninstall_old_beta(),
521- utils.windows.MsiException)
522+ utils.windows.UninstallException)
523 self.assertEqual(self.called['property_uid'],
524 utils.windows.OLD_BETA_UID_KEY)
525 self.assertEqual(self.called['property_name'], u'LocalPackage')
526@@ -416,7 +419,7 @@
527 self.patch(utils.windows, 'get_property_for_product',
528 fake_get_property_for_product)
529 self.assertFailure(utils.uninstall_old_beta(),
530- utils.windows.MsiException)
531+ utils.windows.UninstallException)
532 self.assertEqual(self.called['uid'], utils.windows.OLD_BETA_UID_KEY)
533 self.assertEqual(self.called['property_name'], u'LocalPackage')
534
535@@ -527,8 +530,49 @@
536 self.assertEqual('', self._called[0][4])
537 self.assertEqual(0, self._called[0][5])
538
539- def test_get_auto_update_path(self):
540- """Test the method used to get the autoupdate."""
541+
542+class UpdatePathTestCase(BaseTestCase):
543+ """Test getting the update path."""
544+
545+ @defer.inlineCallbacks
546+ def setUp(self):
547+ """Set the different tests."""
548+ yield super(UpdatePathTestCase, self).setUp()
549+ self.module_path = os.path.join('.', 'root', 'exe', 'dist')
550+ self.module_path = os.path.abspath(self.module_path)
551+ self.patch(os.path, 'exists', lambda *args: True)
552+
553+ def _clean_file(self, module, path):
554+ """Set back the correct path."""
555+ module.__file__ = path
556+
557+ def _clean_frozen(self, old_executable):
558+ """Set back not to be frozen."""
559+ del sys.frozen
560+ sys.executable = old_executable
561+
562+ def test_get_update_path_not_frozen(self):
563+ """Test we return the path to levels up to the dist."""
564+ old_utils_path = utils.windows.__file__
565+ utils.windows.__file__ = os.path.join(self.module_path, 'windows.py')
566+ self.addCleanup(self._clean_file, utils.windows, old_utils_path)
567+ expected_path = os.path.join('root',
568+ utils.windows.AUTO_UPDATE_EXE)
569+ expected_path = os.path.abspath(expected_path)
570+ path = utils.windows._get_update_path()
571+ self.assertEqual(expected_path, path)
572+
573+ def test_get_update_path_frozen(self):
574+ """Test we return the path to levels up to the dist."""
575+ sys.frozen = True
576+ old_exe = sys.executable
577+ sys.executable = os.path.join(self.module_path, 'ubuntuone.exe')
578+ self.addCleanup(self._clean_frozen, old_exe)
579+ expected_path = os.path.join('root', 'exe',
580+ utils.windows.AUTO_UPDATE_EXE)
581+ expected_path = os.path.abspath(expected_path)
582+ path = utils.windows._get_update_path()
583+ self.assertEqual(expected_path, path)
584
585
586 class CheckUpdatesTestCase(BaseTestCase):
587
588=== modified file 'ubuntuone_installer/gui/qt/utils/windows.py'
589--- ubuntuone_installer/gui/qt/utils/windows.py 2011-11-11 19:27:39 +0000
590+++ ubuntuone_installer/gui/qt/utils/windows.py 2011-12-19 21:30:29 +0000
591@@ -67,9 +67,10 @@
592 # LONG_PATH_PREFIX will always be appended only to windows paths,
593 # which should always be unicode.
594 LONG_PATH_PREFIX = u'\\\\?\\'
595-
596-
597-class MsiException(Exception):
598+AUTO_UPDATE_EXE = 'autoupdate-windows.exe'
599+
600+
601+class UninstallException(Exception):
602 """Raised when there are msi issues."""
603
604
605@@ -97,8 +98,12 @@
606 exec_path = os.path.abspath(sys.executable)
607 else:
608 exec_path = os.path.dirname(__file__)
609+ # we take as an axiom that the python code is present in a dist
610+ # folder (whatever the path is) and that the autoupdate is
611+ # present in a level above it
612+ exec_path = os.path.dirname(exec_path)
613 folder = os.path.dirname(exec_path)
614- update_path = os.path.join(folder, "autoupdate-windows.exe")
615+ update_path = os.path.join(folder, AUTO_UPDATE_EXE)
616 if os.path.exists(update_path):
617 return update_path
618 return None
619@@ -257,10 +262,10 @@
620 result = yield deferToThread(ctypes.windll.msi.MsiInstallProductW,
621 uninstall_path, command_line)
622 if result != ERROR_SUCCESS:
623- raise MsiException('Could not remove old beta.')
624+ raise UninstallException('Could not remove old beta.')
625 else:
626 # the local file is missing so we cannot un install it :(
627- raise MsiException('Could not remove old beta.')
628+ raise UninstallException('Could not remove old beta.')
629
630
631 def _append_long_path(path):
632@@ -302,3 +307,26 @@
633 new_full_path = os.path.join(new_location, path)
634 yield deferToThread(shutil.move, old_full_path,
635 new_full_path)
636+
637+
638+@defer.inlineCallbacks
639+def perform_old_beta_data_migration(gui):
640+ """Perform the migration from the old beta."""
641+ if is_old_beta_installed() and \
642+ gui.user_wants_to_remove_old_beta():
643+ logger.debug('Old beta is installed and user wants to remove it.')
644+ try:
645+ # uninstall the msi and migrate data
646+ yield uninstall_old_beta()
647+ # ask the user if he wants to move his data
648+ if gui.user_wants_to_migrate_data():
649+ yield migrate_old_data()
650+ except UninstallException:
651+ logger.error('Could not uninstall msi: %s')
652+ gui.warn_user_beta_not_removed()
653+ except DataMigrationException:
654+ # we did uninstall the msi \o/ but failed in the data migration.
655+ # This is not a big deal, lets just tell the user that he has to
656+ # manually do it
657+ logger.error('Could not migrate data: %s')
658+ gui.warn_user_data_not_migrated()
659
660=== modified file 'ubuntuone_installer/tests/__init__.py'
661--- ubuntuone_installer/tests/__init__.py 2011-10-28 11:00:42 +0000
662+++ ubuntuone_installer/tests/__init__.py 2011-12-19 21:30:29 +0000
663@@ -21,7 +21,7 @@
664
665 from twisted.internet import defer
666
667-from ubuntuone.devtools.testcase import TestCase as BaseTestCase
668+from ubuntuone.devtools.testcases import TestCase as BaseTestCase
669
670
671 class TestCase(BaseTestCase):

Subscribers

People subscribed via source and target branches