Merge lp:~mikemc/ubuntuone-windows-installer/setup-mac into lp:ubuntuone-windows-installer

Proposed by Mike McCracken on 2012-06-13
Status: Merged
Approved by: Mike McCracken on 2012-06-19
Approved revision: 124
Merged at revision: 123
Proposed branch: lp:~mikemc/ubuntuone-windows-installer/setup-mac
Merge into: lp:ubuntuone-windows-installer
Diff against target: 631 lines (+611/-0)
4 files modified
scripts/README-mac.txt (+69/-0)
scripts/data/macapp_template.plist (+12/-0)
scripts/data/qt.conf (+2/-0)
scripts/setup-mac.py (+528/-0)
To merge this branch: bzr merge lp:~mikemc/ubuntuone-windows-installer/setup-mac
Reviewer Review Type Date Requested Status
Brian Curtin (community) 2012-06-13 Approve on 2012-06-18
Alejandro J. Cura (community) Approve on 2012-06-15
Review via email: mp+110155@code.launchpad.net

Commit Message

- add initial setup-mac.py script to create a hierarchy of application packages ( LP: 1010202 )

Description of the Change

- add initial setup-mac.py script to create a hierarchy of application packages ( LP: 1010202 )

The script requires an installation of py2app from https://bitbucket.org/ronaldoussoren/py2app

It creates .app wrappers for ubuntuone-control-panel and several other pieces of the client.
As we add darwin support, this script and what it generates will change.

See README-mac.txt for information on how to run and how to test that it worked as much as I expect it to. (It doesn't yet generate anything you can double-click to test)

To post a comment you must log in.
Brian Curtin (brian.curtin) wrote :

Looks reasonable to me. However, while I don't personally care about this part, I know others do -- the imports should be alphabetized.

review: Needs Fixing
121. By Mike McCracken on 2012-06-14

reorganize imports, fix many pep8 complaints

122. By Mike McCracken on 2012-06-15

merge with trunk

123. By Mike McCracken on 2012-06-15

add valicert .pem

124. By Mike McCracken on 2012-06-15

standardize docstrings

Mike McCracken (mikemc) wrote :

> Looks reasonable to me. However, while I don't personally care about this
> part, I know others do -- the imports should be alphabetized.

121 fixed the imports, the other revisions fixed Alejandro's comments from IRC.

Alejandro J. Cura (alecu) wrote :

+1!

review: Approve
Brian Curtin (brian.curtin) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'scripts/README-mac.txt'
2--- scripts/README-mac.txt 1970-01-01 00:00:00 +0000
3+++ scripts/README-mac.txt 2012-06-15 17:16:18 +0000
4@@ -0,0 +1,69 @@
5+
6+====================================
7+Mac packaging overview for U1 client
8+====================================
9+
10+Overview
11+========
12+
13+NOTE: you must use the python wrapper from the buildout to run
14+setup-mac.py.
15+
16+Run 'python setup-mac.py prepare --from-trunk py2app' to download and build
17+all dependencies, and package the .app bundles together into a
18+standalone dist/ubuntuone-control-panel/UbuntuOne.app
19+
20+For development, omit --from-trunk to build from the buildout's
21+'parts' directory.
22+
23+The Prepare Step
24+================
25+
26+Prepare builds and installs the subprojects into a staging directory
27+'installed/'.
28+
29+prepare --from-trunk will grab the trunk of the relevant projects from
30+launchpad and put them in ./sources/projectname
31+
32+prepare --only-prepare allows you to pick which of the three
33+subprojects to stage (default is all).
34+
35+This is mostly only useful for development, to make the build-test loop faster.
36+
37+
38+The py2app Step
39+===============
40+
41+The py2app action does the dependency detection and .app bundle
42+building.
43+
44+
45+Testing
46+=======
47+
48+As of June 12, 2012, none of the generated .app bundles do anything
49+when double-clicked in the OS X Finder.
50+
51+The main UbuntuOne.app will launch the ubuntuone-control-panel but is
52+pending some platform integration work.
53+
54+The project that is the furthest along is the ubuntu-sso-client, and
55+you can test its operation from within the main package like this:
56+
57+# build:
58+
59+% cd buildout-env/scripts/devsetup/parts/ubuntuone-windows-installer/scripts
60+% PYTHONPATH=. python setup-mac.py prepare py2app
61+
62+
63+# test:
64+
65+% U1_DEBUG=1 dist/ubuntuone-control-panel/UbuntuOne.app/Contents/Resources/Ubuntu\ Single\ Sign-On.app/Contents/MacOS/ubuntu-sso-login-qt --app_name holycowmacpac
66+
67+# or test login only:
68+% U1_DEBUG=1 dist/ubuntuone-control-panel/UbuntuOne.app/Contents/Resources/Ubuntu\ Single\ Sign-On.app/Contents/MacOS/ubuntu-sso-login-qt --app_name holycowmacpac --login_only
69+
70+
71+This should show the Ubuntu SSO screen (it may show behind the topmost
72+window, move the terminal window to reveal it). The account creation
73+and login steps should work properly.
74
75=== added file 'scripts/data/macapp_template.plist'
76--- scripts/data/macapp_template.plist 1970-01-01 00:00:00 +0000
77+++ scripts/data/macapp_template.plist 2012-06-15 17:16:18 +0000
78@@ -0,0 +1,12 @@
79+<?xml version="1.0" encoding="UTF-8"?>
80+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
81+<plist version="1.0">
82+<dict>
83+ <key>LSMinimumSystemVersion</key>
84+ <string>10.6</string>
85+ <key>CFBundleIconFile</key>
86+ <string>ubuntuone.icns</string>
87+ <key>CFBundleDevelopmentRegion</key>
88+ <string>English</string>
89+</dict>
90+</plist>
91\ No newline at end of file
92
93=== added file 'scripts/data/qt.conf'
94--- scripts/data/qt.conf 1970-01-01 00:00:00 +0000
95+++ scripts/data/qt.conf 2012-06-15 17:16:18 +0000
96@@ -0,0 +1,2 @@
97+[Paths]
98+Plugins = Frameworks/plugins
99
100=== added file 'scripts/setup-mac.py'
101--- scripts/setup-mac.py 1970-01-01 00:00:00 +0000
102+++ scripts/setup-mac.py 2012-06-15 17:16:18 +0000
103@@ -0,0 +1,528 @@
104+# setup-mac.py - Build system for Ubuntu One Client package
105+#
106+# Copyright 2012 Canonical Ltd.
107+#
108+# This program is free software: you can redistribute it and/or modify it
109+# under the terms of the GNU General Public License version 3, as published
110+# by the Free Software Foundation.
111+#
112+# This program is distributed in the hope that it will be useful, but
113+# WITHOUT ANY WARRANTY; without even the implied warranties of
114+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
115+# PURPOSE. See the GNU General Public License for more details.
116+#
117+# You should have received a copy of the GNU General Public License along
118+# with this program. If not, see <http://www.gnu.org/licenses/>.
119+"""
120+Setup.py script for Ubuntu One Mac Client
121+
122+Usage:
123+ % python setup.py prepare # builds and arranges subpackages
124+
125+ use --from-trunk to grab sources from launchpad. otherwise, builds
126+ from buildout parts dir.
127+
128+ use --only_prepare='sso, controlpanel, client' (or 'sso, client',
129+ etc) to limit which of those three to stage. This is only useful
130+ for development
131+
132+ % python setup.py py2app # builds .app
133+"""
134+
135+
136+import copy
137+import glob
138+import os
139+import shutil
140+import subprocess
141+import sys
142+
143+import conf
144+
145+from distutils.cmd import Command
146+from distutils.core import setup
147+from plistlib import Plist
148+
149+try:
150+ import py2app
151+except ImportError:
152+ print "This setup requires py2app, check your path"
153+ print "or see http://bitbucket.com/ronaldoussoren/py2app/"
154+ sys.exit()
155+
156+
157+LOG_LEVEL = "DEBUG"
158+LOG_FILE_SIZE = "1000000"
159+
160+INSTALL_DIR = os.path.abspath("installed")
161+
162+# bzr env assumes homebrew install:
163+# This is necessary so we can run setup-mac with the buildout python,
164+# which breaks the paths needed for bzr.
165+BZR_PATH = "/usr/local/Cellar/bazaar/2.5.0/libexec/:/usr/local/bin:/usr/bin"
166+BZR_ENV = os.environ.copy()
167+BZR_ENV.update(dict(PYTHONPATH="/usr/local/Cellar/bazaar/2.5.0/libexec/",
168+ PATH=BZR_PATH))
169+
170+
171+def branch_and_merge(urls):
172+ """Branch and merge all requested branches."""
173+ project_name = urls[0].split(":")[1]
174+ print "Getting sources for:", project_name
175+ folder_name = os.path.join('sources', project_name)
176+ current_folder = os.getcwd()
177+ if os.path.isdir(folder_name): # Folder exists
178+ shutil.rmtree(folder_name)
179+ subprocess.check_call(["bzr", "branch", urls[0], folder_name],
180+ env=BZR_ENV)
181+ os.chdir(folder_name)
182+ for url in urls[1:]:
183+ print "Merging:", url
184+ subprocess.check_call(["bzr", "merge", url], env=BZR_ENV)
185+ subprocess.check_call(["bzr", "commit", "-m", '"merged %s"' % url],
186+ env=BZR_ENV)
187+ os.chdir(current_folder)
188+
189+
190+# pylint is complaining about parent classes having too many methods
191+# pylint: disable=R0904
192+class DoNotPrepareAnything(Command):
193+ """No-op, lets us call setup multiple times without re-preparing."""
194+
195+ user_options = user_options = [("from-trunk", None, "noop."),
196+ ("only-prepare=", None, "noop."),
197+ ("source-dir=", None, "noop.")]
198+
199+ def initialize_options(self):
200+ """No-op."""
201+ self.only_prepare = None
202+ self.from_trunk = None
203+ self.source_dir = None
204+
205+ def finalize_options(self):
206+ """No-op."""
207+ pass
208+
209+ def run(self):
210+ """No-op."""
211+ pass
212+
213+# pylint: enable=R0904
214+
215+
216+# pylint is complaining about parent classes having too many methods
217+# pylint: disable=R0904
218+class PrepareSources(Command):
219+ """Manipulate the sources to look as if they were installed."""
220+
221+ user_options = [("from-trunk", None,
222+ """Download sources from launchpad. default is to
223+ use buildout instead."""),
224+ ("only-prepare=", None,
225+ """Only do expensive stuff for the packages on
226+ this list of one or more of 'sso',
227+ 'controlpanel', or 'client'.
228+ (NOTE: still downloads everything if from-trunk
229+ is set)"""),
230+ ("source-dir=", None,
231+ """Set the directory to get the sources from.
232+ The default depends on from-trunk:
233+ * if from-trunk is not specified,
234+ the default is buildout sources dir.
235+ * if from-trunk is specified,
236+ the default source dir is './sources'""")]
237+
238+ def initialize_options(self):
239+ """Init options."""
240+ self.from_trunk = None
241+ self.only_prepare = None
242+ self.source_dir = None
243+
244+ def finalize_options(self):
245+ """Finalize options."""
246+ if self.source_dir is None:
247+ if self.from_trunk is not None:
248+ self.source_dir = 'sources'
249+ else:
250+ self.source_dir = os.path.join(os.path.dirname(__file__),
251+ "../..")
252+
253+ if self.only_prepare is None:
254+ # default is to do everything:
255+ self.only_prepare = "sso, controlpanel, client"
256+
257+ def run(self):
258+ """Copy, build and munge things to prepare for packaging."""
259+
260+ print "Starting Prepare step:"
261+
262+ for folder in ["bin", INSTALL_DIR, "data"]:
263+ if not os.path.isdir(folder):
264+ os.mkdir(folder)
265+
266+ if self.from_trunk is not None:
267+ if not os.path.isdir(self.source_dir):
268+ os.mkdir(self.source_dir)
269+
270+ branch_and_merge(conf.U1_CLIENT_BRANCHES)
271+ branch_and_merge(conf.U1_CONTROL_PANEL_BRANCHES)
272+ branch_and_merge(conf.UBUNTU_SSO_BRANCHES)
273+ branch_and_merge(conf.U1_STORAGE_PROTOCOL_BRANCHES)
274+
275+ print "will look for sources in ", self.source_dir
276+ print "and install into ", INSTALL_DIR
277+
278+ # Copy main executables. In some cases, add .py so py2app
279+ # will recognize the file as python and not crash.
280+
281+ shutil.copyfile(os.path.join(self.source_dir,
282+ "ubuntuone-client", "bin",
283+ "ubuntuone-syncdaemon"),
284+ os.path.join("bin", "ubuntuone-syncdaemon.py"))
285+
286+ shutil.copyfile(os.path.join(self.source_dir, "ubuntuone-client",
287+ "bin", "u1sdtool"),
288+ os.path.join("bin", "u1sdtool"))
289+
290+ dest = os.path.join("bin", "ubuntuone-proxy-tunnel.py")
291+ shutil.copyfile(os.path.join(self.source_dir, "ubuntuone-client",
292+ "bin", "ubuntuone-proxy-tunnel"),
293+ dest)
294+
295+ dest = os.path.join("bin", "ubuntu-sso-login.py")
296+ shutil.copyfile(os.path.join(self.source_dir, "ubuntu-sso-client",
297+ "bin", "ubuntu-sso-login"), dest)
298+ os.chmod(dest, 0755)
299+
300+ dest = os.path.join("bin", "ubuntu-sso-login-qt.py")
301+ shutil.copyfile(os.path.join(self.source_dir, "ubuntu-sso-client",
302+ "bin", "ubuntu-sso-login-qt"), dest)
303+
304+ shutil.copyfile(os.path.join(self.source_dir, "ubuntu-sso-client",
305+ "bin", "ubuntu-sso-proxy-creds-qt"),
306+ os.path.join("bin", "ubuntu-sso-proxy-creds-qt.py"))
307+
308+ shutil.copyfile(os.path.join(self.source_dir, "ubuntu-sso-client",
309+ "bin", "ubuntu-sso-ssl-certificate-qt"),
310+ os.path.join("bin",
311+ "ubuntu-sso-ssl-certificate-qt.py"))
312+
313+ shutil.copyfile(os.path.join(self.source_dir,
314+ "ubuntuone-control-panel", "bin",
315+ "ubuntuone-control-panel-qt"),
316+ os.path.join("bin", "ubuntuone-control-panel-qt.py"))
317+
318+ # Remove "installed" copy
319+ try:
320+ shutil.rmtree(os.path.join(INSTALL_DIR, "lib"))
321+ except OSError, e:
322+ print "WARNING: OSError %r removing %r" \
323+ % (e, os.path.join(INSTALL_DIR, "lib"))
324+
325+ start_dir = os.getcwd()
326+
327+ # Build SSO UI files, copy packages.
328+ dest_dir = os.path.join(INSTALL_DIR, "lib", "site-packages")
329+ dest_sso = os.path.join(dest_dir, "ubuntu_sso")
330+
331+ os.chdir(os.path.join(self.source_dir, "ubuntu-sso-client"))
332+
333+ if "sso" in self.only_prepare:
334+ print "building and installing ubuntu-sso-client"
335+ print "from directory ", os.getcwd()
336+ log_file_name = os.path.join(INSTALL_DIR, "sso-build.log")
337+ with open(log_file_name, 'w') as logfile:
338+ cmd = "python setup.py build"
339+ retval = subprocess.call(cmd,
340+ shell=True,
341+ stderr=subprocess.STDOUT,
342+ stdout=logfile
343+ )
344+ if retval != 0:
345+ print "error running %r in %r. look in %r for details" %\
346+ (cmd, os.getcwd(), logfile.name)
347+
348+ # install UI files from sso. ignore the ubuntu_sso module
349+ # this installs:
350+ log_file_name = os.path.join(INSTALL_DIR, "sso-install.log")
351+ with open(log_file_name, 'w') as logfile:
352+ cmd = "python setup.py install --prefix=%s" % INSTALL_DIR,
353+ retval = subprocess.call(cmd,
354+ shell=True,
355+ stderr=subprocess.STDOUT,
356+ stdout=logfile
357+ )
358+ if retval != 0:
359+ print "error running %r in %r. look in %r for details" %\
360+ (cmd, os.getcwd(), logfile.name)
361+
362+ # copy ubuntu_sso module separately to
363+ # install/lib/site-packages/ubuntu_sso
364+ try:
365+ shutil.copytree("ubuntu_sso", dest_sso)
366+ except Exception, e:
367+ print e
368+ print "tried to copy", os.path.abspath('ubuntu_sso'),
369+ print "to ", dest_sso
370+
371+ sso_revno = subprocess.check_output(["bzr", "revno", "."],
372+ env=BZR_ENV).strip()
373+
374+ os.chdir(start_dir)
375+
376+ # install u1 client package to install/lib/site-packages/ubuntuone:
377+ os.chdir(os.path.join(self.source_dir, "ubuntuone-client"))
378+
379+ if "client" in self.only_prepare:
380+ print "copying ubuntuone-client package"
381+ shutil.copy(os.path.join("windows", "clientdefs.py"),
382+ os.path.join("ubuntuone", "clientdefs.py"))
383+ dest_client = os.path.join(dest_dir, "ubuntuone")
384+ shutil.copytree("ubuntuone", dest_client)
385+
386+ # workaround for py2app issue #49:
387+ # (it can't handle non-py files in a py module directory)
388+ os.remove(os.path.join(dest_client,
389+ "syncdaemon",
390+ "u1fsfsm.ods"))
391+
392+ u1client_revno = subprocess.check_output(["bzr", "revno", "."],
393+ env=BZR_ENV).strip()
394+
395+ os.chdir(start_dir)
396+
397+ # install controlpanel files
398+ os.chdir(os.path.join(self.source_dir, "ubuntuone-control-panel"))
399+
400+ if "controlpanel" in self.only_prepare:
401+ print "building ubuntuone-controlpanel"
402+ log_file_name = os.path.join(INSTALL_DIR, "u1cp-build.log")
403+ with open(log_file_name, 'w') as logfile:
404+ cmd = "python setup.py build"
405+ retval = subprocess.call(cmd,
406+ shell=True,
407+ stderr=subprocess.STDOUT,
408+ stdout=logfile
409+ )
410+ if retval != 0:
411+ print "error running %r in %r. look in %r for details" %\
412+ (cmd, os.getcwd(), logfile.name)
413+
414+ # Copying by hand because the install is borked
415+ dest_cp = os.path.join(dest_dir, "ubuntuone", "controlpanel")
416+ shutil.copytree(os.path.join("ubuntuone", "controlpanel"),
417+ dest_cp)
418+
419+ u1cp_revno = subprocess.check_output(["bzr", "revno", "."],
420+ env=BZR_ENV).strip()
421+
422+ os.chdir(start_dir)
423+
424+ # Create revno file
425+ with open(os.path.join("data", "revnos.txt"), "w+") as revnos:
426+ revnos.write("ubuntu-sso-client: %s"
427+ "ubuntuone-client: %s"
428+ "ubuntuone-control-panel: %s" %
429+ (sso_revno, u1client_revno, u1cp_revno))
430+
431+ # Copy storage-protocol's pem files
432+ shutil.copyfile(os.path.join(self.source_dir,
433+ "ubuntuone-storage-protocol", "data",
434+ "UbuntuOne-Go_Daddy_CA.pem"),
435+ os.path.join("data", "UbuntuOne-Go_Daddy_CA.pem"))
436+ shutil.copyfile(os.path.join(self.source_dir,
437+ "ubuntuone-storage-protocol", "data",
438+ "UbuntuOne-Go_Daddy_Class_2_CA.pem"),
439+ os.path.join("data", "UbuntuOne-Go_Daddy_Class_2_CA.pem"))
440+ shutil.copyfile(os.path.join(self.source_dir,
441+ "ubuntuone-storage-protocol", "data",
442+ "ValiCert_Class_2_VA.pem"),
443+ os.path.join("data", "ValiCert_Class_2_VA.pem"))
444+
445+ # Copy syncdaemon config data
446+ shutil.copyfile(os.path.join(self.source_dir,
447+ "ubuntuone-client", "data",
448+ "syncdaemon.conf"),
449+ os.path.join("data", "syncdaemon.conf"))
450+ logging_path = os.path.join(self.source_dir,
451+ "ubuntuone-client", "data",
452+ "logging.conf.in")
453+ with open(logging_path, "rb") as logconf:
454+ data = logconf.read()
455+ data = data.replace("@LOG_LEVEL@", LOG_LEVEL)
456+ data = data.replace("@LOG_FILE_SIZE@", LOG_FILE_SIZE)
457+ with open(os.path.join("data", "logging.conf"), "wb") as logconf:
458+ logconf.write(data)
459+
460+ # clear path_importer_cache to make sure that a following
461+ # py2app step can see the newly-copied
462+ # INSTALL_PATH/lib/site-packages/ubuntu_sso module without
463+ # clearing, py2app will fail on a clean run when both prepare
464+ # and py2app are specified on the same command:
465+ sys.path_importer_cache.clear()
466+
467+ print "Prepare done"
468+# pylint: enable=R0904
469+
470+
471+if __name__ == '__main__':
472+
473+ # this path is from homebrew:
474+ paths = glob.glob("/usr/local/Cellar/qt/*/plugins")
475+ if len(paths) != 1:
476+ print "Warning: expected just one path to Homebrew Qt plugins"
477+ print "but found ", paths
478+
479+ qt_plugin_path = paths[0]
480+
481+ qt_network_plugins = glob.glob(qt_plugin_path + "/bearer/*.dylib")
482+ qt_imageformat_plugins = glob.glob(qt_plugin_path +
483+ "/imageformats/*.dylib")
484+ dylib_paths = qt_imageformat_plugins + qt_network_plugins
485+
486+ master_plist = Plist.fromFile('data/macapp_template.plist')
487+ master_options = {"includes": ['google.protobuf.descriptor',
488+ 'sip',
489+ 'twisted.web.resource',
490+ 'twisted.web.client',
491+ 'ubuntu_sso.qt',
492+ 'ubuntu_sso.qt.ui',
493+ 'oauth'],
494+ "excludes": ["fsm", "PyQt4.uic"],
495+ "frameworks": dylib_paths,
496+ "resources": ['data/qt.conf'],
497+ "strip": True,
498+ }
499+
500+ # make sure we can see the prepared libraries:
501+ sys.path.insert(0, os.path.join(INSTALL_DIR, "lib", "site-packages"))
502+
503+ def do_setup(name, is_background, id, exename,
504+ mainscript,
505+ verbose=False,
506+ doprepare=False):
507+ """Customize plist & options and run setup.
508+
509+ Returns the path of the generated .app bundle.
510+ """
511+
512+ print "calling setup for:", name
513+ plist = copy.deepcopy(master_plist)
514+ plist.update(LSUIElement=is_background,
515+ CFBundleIdentifier=id,
516+ CFBundleExecutable=exename,
517+ CFBundleName=name)
518+
519+ options = copy.deepcopy(master_options)
520+ options.update({"plist": plist,
521+ "bdist_base": os.path.join("build", exename),
522+ "dist_dir": os.path.join("dist", exename)})
523+
524+ if doprepare:
525+ prepare_class = PrepareSources
526+ else:
527+ prepare_class = DoNotPrepareAnything
528+
529+ setup(cmdclass=dict(prepare=prepare_class),
530+ app=[mainscript],
531+ options=dict(py2app=options),
532+ verbose=verbose)
533+
534+ return os.path.join("dist", exename, name + ".app")
535+
536+ sso_login_qt_app_path = do_setup("Ubuntu Single Sign-On",
537+ True,
538+ "com.ubuntu.sso.login-qt",
539+ "ubuntu-sso-login-qt",
540+ os.path.join("bin",
541+ "ubuntu-sso-login-qt.py"),
542+ doprepare=True)
543+
544+ sso_login_app_path = do_setup("Ubuntu SSO Helper",
545+ True,
546+ "com.ubuntu.sso.login",
547+ "ubuntu-sso-login",
548+ os.path.join("bin", "ubuntu-sso-login.py"))
549+
550+ proxy_tunnel_app_path = do_setup("UbuntuOne Proxy Tunnel",
551+ True,
552+ "com.ubuntu.one.proxy-tunnel",
553+ "ubuntuone-proxy-tunnel",
554+ os.path.join("bin",
555+ "ubuntuone-proxy-tunnel.py"))
556+
557+ control_panel_script = os.path.join("bin", "ubuntuone-control-panel-qt.py")
558+ control_panel_app_path = do_setup("UbuntuOne",
559+ True,
560+ "com.ubuntu.one.controlpanel",
561+ "ubuntuone-control-panel",
562+ control_panel_script)
563+
564+ control_panel_resources_path = os.path.join(control_panel_app_path,
565+ "Contents", "Resources")
566+
567+ # only do tweaks if you've done setup.py py2app
568+ if 'py2app' not in sys.argv:
569+ print "skipping post-setup tweaks."
570+ print "run setup.py py2app to build apps and finalize packaging"
571+ print "note that --source-dir only applies to 'prepare'."
572+ sys.exit()
573+
574+ print "Starting post-setup tweaks"
575+
576+ # move plugins around
577+ frameworks_paths = [os.path.join(p, "Contents", "Frameworks") for p in
578+ sso_login_qt_app_path,
579+ sso_login_app_path,
580+ control_panel_app_path]
581+
582+ plugin_names = [os.path.basename(f) for f in dylib_paths]
583+
584+ for f_path in frameworks_paths:
585+ bearers_dir = os.path.join(f_path, "plugins", "bearer")
586+ imagefmts_dir = os.path.join(f_path, "plugins", "imageformats")
587+ try:
588+ os.makedirs(imagefmts_dir)
589+ except Exception as e:
590+ print "ignoring exception in makedirs(%r): %r" % (imagefmts_dir,
591+ e)
592+
593+ try:
594+ os.makedirs(bearers_dir)
595+ except Exception as e:
596+ print "ignoring exception in makedirs(%r): %r" % (bearers_dir, e)
597+
598+ try:
599+ for plugin_name in plugin_names:
600+ if "bearer" in plugin_name:
601+ print "moving ", os.path.join(f_path, plugin_name), "to"
602+ print " ", os.path.join(bearers_dir, plugin_name)
603+ os.rename(os.path.join(f_path, plugin_name),
604+ os.path.join(bearers_dir, plugin_name))
605+ else:
606+ os.rename(os.path.join(f_path, plugin_name),
607+ os.path.join(imagefmts_dir, plugin_name))
608+ print "moving ", os.path.join(f_path, plugin_name), "to"
609+ print " ", os.path.join(imagefmts_dir, plugin_name)
610+ except Exception as e:
611+ print "ERROR moving:", e
612+
613+ print "copying helper apps into main app"
614+
615+ def copy_helper(helper_path):
616+ """Copy sub-apps into main app resources folder."""
617+
618+ helper_app_name = os.path.basename(helper_path)
619+ dest = os.path.join(control_panel_resources_path,
620+ helper_app_name)
621+ if os.path.exists(dest):
622+ print "removing", dest
623+ shutil.rmtree(dest)
624+
625+ shutil.copytree(helper_path, dest)
626+
627+ copy_helper(sso_login_qt_app_path)
628+ copy_helper(sso_login_app_path)
629+ copy_helper(proxy_tunnel_app_path)
630+
631+ print "DONE. see dist/ for the .app."

Subscribers

People subscribed via source and target branches