Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: packagerEdge.py

Issue 29825555: Issue 6291 - add ManifoldJS packaging for Edge (Closed) Base URL: https://hg.adblockplus.org/buildtools/file/9a56d76cd951
Left Patch Set: Created July 12, 2018, 9:24 a.m.
Right Patch Set: Final patch set Created Aug. 9, 2018, 7:08 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « package.json ('k') | templates/edge/AppxBlockMap.xml.tmpl » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # This Source Code Form is subject to the terms of the Mozilla Public 1 # This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 4
5 import json
6 import os 5 import os
7 import shutil 6 import shutil
8 from StringIO import StringIO 7 from StringIO import StringIO
9 import subprocess 8 import subprocess
10 import tempfile 9 import tempfile
11 from xml.etree import ElementTree 10 from xml.etree import ElementTree
12 from zipfile import ZipFile 11 from zipfile import ZipFile
13 12
14 import packager 13 import packager
15 import packagerChrome 14 import packagerChrome
16 15
17 MANIFEST = 'appxmanifest.xml' 16 MANIFEST = 'appxmanifest.xml'
17 ASSETS_DIR = 'Assets'
18 18
19 defaultLocale = packagerChrome.defaultLocale 19 defaultLocale = packagerChrome.defaultLocale
20 20
21 21
22 def _get_template_for(filename): 22 def _get_template_for(filename):
23 return packager.getTemplate('edge/{}.tmpl'.format(filename)) 23 return packager.getTemplate('edge/{}.tmpl'.format(filename))
24
25
26 def load_translation(files, locale):
27 """Load translation strings for locale from files."""
28 path = '_locales/{}/messages.json'.format(locale)
29 return json.loads(files[path])
30 24
31 25
32 def register_xml_namespaces(manifest_path): 26 def register_xml_namespaces(manifest_path):
33 """Register namespaces of the given file, in order to preserve defaults.""" 27 """Register namespaces of the given file, in order to preserve defaults."""
34 with open(manifest_path, 'r') as fp: 28 with open(manifest_path, 'r') as fp:
35 ns = dict([node for _, node in ElementTree.iterparse( 29 ns = dict([node for _, node in ElementTree.iterparse(
36 fp, events=['start-ns'])]) 30 fp, events=['start-ns'])])
37 for prefix, uri in ns.items(): 31 for prefix, uri in ns.items():
38 ElementTree.register_namespace(prefix, uri) 32 ElementTree.register_namespace(prefix, uri)
39 33
34 # Make the default namespace available in an xpath expression
35 ns['_d'] = ns['']
36
40 return ns 37 return ns
41 38
42 39
43 def update_appx_manifest(manifest_path, files, metadata, release_build): 40 def update_appx_manifest(manifest_path, base_dir, files, metadata,
41 release_build):
44 namespaces = register_xml_namespaces(manifest_path) 42 namespaces = register_xml_namespaces(manifest_path)
Sebastian Noack 2018/07/12 14:43:10 I wonder if this is necessary? What happens if you
tlucas 2018/07/19 12:30:27 This is necessary so that xml.etree.ElementTree.wr
45 43
46 def traverse(current_elem, overwrite):
47 if isinstance(overwrite, dict):
48 for key, value in overwrite.items():
49 if isinstance(key, tuple):
50 prefix, element = key
51 next_elem = current_elem.find(
52 '{{{}}}{}'.format(namespaces[prefix], element))
53 traverse(next_elem, value)
54 else:
55 current_elem.attrib.update(overwrite)
56 else:
57 current_elem.text = overwrite
58
59 translation = load_translation(files, defaultLocale)
60 name_key = 'name' if release_build else 'name_devbuild'
61 v_min, v_max = metadata.get('compat', 'windows').split('/') 44 v_min, v_max = metadata.get('compat', 'windows').split('/')
62 45
63 overwrite = { 46 filenames = []
Sebastian Noack 2018/07/12 14:43:10 Instead of a dictionaries you might want to use li
tlucas 2018/07/19 12:30:28 Since order doesn't matter in the resulting XML (o
Sebastian Noack 2018/07/25 19:18:41 Originally I thought that nodes may be created for
tlucas 2018/08/08 09:35:54 It looks like adding the default namespaces with a
64 ('', 'Identity'): { 47
65 'Name': packager.get_app_id(release_build, metadata), 48 for name, path in metadata.items('appx_assets'):
66 'Publisher': metadata.get('general', 'publisher_id'), 49 path = os.path.join(base_dir, path)
67 }, 50 icon_path = '{}/{}'.format(ASSETS_DIR, name)
68 ('', 'Properties'): { 51
69 ('', 'DisplayName'): translation[name_key]['message'], 52 files.read(path, icon_path)
Sebastian Noack 2018/07/12 14:43:10 It seems we can just leave the DisplayName alone.
tlucas 2018/07/19 12:30:27 True indeed, removed this.
70 ('', 'PublisherDisplayName'): metadata.get('general', 'author'), 53 filenames.append(icon_path)
71 ('', 'Logo'): 'Assets/logo_50.png', 54
72 }, 55 assets = packagerChrome.makeIcons(files, filenames)
73 ('', 'Dependencies'): { 56
74 ('', 'TargetDeviceFamily'): { 57 author = metadata.get('general', 'author')
75 'MaxVersionTested': v_max, 58
76 'MinVersion': v_min, 59 overrides = [
77 }, 60 ('_d:Identity', None, [
78 }, 61 ('Name', packager.get_app_id(release_build, metadata)),
79 ('', 'Applications'): { 62 ('Publisher', metadata.get('general', 'publisher_id')),
80 ('', 'Application'): { 63 ]),
81 ('uap', 'VisualElements'): { 64 ('_d:Properties/_d:PublisherDisplayName', author, []),
Sebastian Noack 2018/07/12 14:43:10 Perhaps this structure is more readable if keys ar
tlucas 2018/07/19 12:30:27 You may be right about it being (only imho) a bit
Sebastian Noack 2018/07/25 19:18:41 What I meant is using "uap:VisualElements" as key
tlucas 2018/08/08 09:35:54 Done.
82 'Square150x150Logo': 'Assets/logo_150.png', 65 ('_d:Properties/_d:Logo', assets[50], []),
83 'Square44x44Logo': 'Assets/logo_44.png', 66 ('_d:Dependencies/_d:TargetDeviceFamily', None, [
Sebastian Noack 2018/07/12 14:43:10 Instead of hard-coding the assets, we could identi
tlucas 2018/07/19 12:30:27 Done.
84 }, 67 ('MaxVersionTested', v_max),
85 }, 68 ('MinVersion', v_min),
86 }, 69 ]),
87 } 70 ('_d:Applications/_d:Application/uap:VisualElements', None, [
71 ('Square150x150Logo', assets[150]),
72 ('Square44x44Logo', assets[44]),
73 ]),
74 ]
88 75
89 tree = ElementTree.parse(manifest_path) 76 tree = ElementTree.parse(manifest_path)
90 root = tree.getroot() 77 root = tree.getroot()
91 78
92 traverse(root, overwrite) 79 for xpath, text, attributes in overrides:
80 element = root.find(xpath, namespaces)
81 if text:
82 element.text = text
83 for attr, value in attributes:
84 element.set(attr, value)
93 85
94 tree.write(manifest_path, encoding='utf-8', xml_declaration=True) 86 tree.write(manifest_path, encoding='utf-8', xml_declaration=True)
95 87
96 88
97 def createBuild(baseDir, type='edge', outFile=None, # noqa: preserve API. 89 def createBuild(baseDir, type='edge', outFile=None, # noqa: preserve API.
98 buildNum=None, releaseBuild=False, keyFile=None, 90 buildNum=None, releaseBuild=False, keyFile=None,
99 devenv=False): 91 devenv=False):
100 92
101 metadata = packager.readMetadata(baseDir, type) 93 metadata = packager.readMetadata(baseDir, type)
102 version = packager.getBuildVersion(baseDir, metadata, releaseBuild, 94 version = packager.getBuildVersion(baseDir, metadata, releaseBuild,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 146
155 with ZipFile(zipped, 'r') as zip_file: 147 with ZipFile(zipped, 'r') as zip_file:
156 zip_file.extractall(src_dir) 148 zip_file.extractall(src_dir)
157 149
158 cmd_env = os.environ.copy() 150 cmd_env = os.environ.copy()
159 cmd_env['SRC_FOLDER'] = src_dir 151 cmd_env['SRC_FOLDER'] = src_dir
160 cmd_env['EXT_FOLDER'] = ext_dir 152 cmd_env['EXT_FOLDER'] = ext_dir
161 153
162 manifold_folder = os.path.join(ext_dir, 'MSGname', 'edgeextension') 154 manifold_folder = os.path.join(ext_dir, 'MSGname', 'edgeextension')
163 manifest_folder = os.path.join(manifold_folder, 'manifest') 155 manifest_folder = os.path.join(manifold_folder, 'manifest')
164 asset_folder = os.path.join(manifest_folder, 'Assets') 156 asset_folder = os.path.join(manifest_folder, ASSETS_DIR)
165 157
166 # prepare the extension with manifoldjs 158 # prepare the extension with manifoldjs
167 cmd = ['npm', 'run', '--silent', 'build-edge'] 159 cmd = ['npm', 'run', '--silent', 'build-edge']
168 subprocess.check_call(cmd, env=cmd_env, cwd=os.path.dirname(__file__)) 160 subprocess.check_call(cmd, env=cmd_env, cwd=os.path.dirname(__file__))
169 161
170 # update incomplete appxmanifest 162 # update incomplete appxmanifest
171 intermediate_manifest = os.path.join(manifest_folder, MANIFEST) 163 intermediate_manifest = os.path.join(manifest_folder, MANIFEST)
172 update_appx_manifest(intermediate_manifest, files, metadata, 164 update_appx_manifest(intermediate_manifest, baseDir, files, metadata,
173 releaseBuild) 165 releaseBuild)
174 166
175 # cleanup placeholders, copy actual images 167 # cleanup placeholders, copy actual images
176 shutil.rmtree(asset_folder) 168 shutil.rmtree(asset_folder)
177 os.mkdir(asset_folder) 169 os.mkdir(asset_folder)
178 if metadata.has_section('appx_assets'): 170 if metadata.has_section('appx_assets'):
179 for name, path in metadata.items('appx_assets'): 171 for name, path in metadata.items('appx_assets'):
180 path = os.path.join(baseDir, path) 172 path = os.path.join(baseDir, path)
181 target = os.path.join(asset_folder, name) 173 target = os.path.join(asset_folder, name)
182 shutil.copyfile(path, target) 174 shutil.copyfile(path, target)
183 175
184 # package app with manifoldjs 176 # package app with manifoldjs
185 cmd = ['npm', 'run', '--silent', 'package-edge'] 177 cmd = ['npm', 'run', '--silent', 'package-edge']
186 178
187 subprocess.check_call(cmd, env=cmd_env, cwd=os.path.dirname(__file__)) 179 subprocess.check_call(cmd, env=cmd_env, cwd=os.path.dirname(__file__))
188 180
189 package = os.path.join(manifold_folder, 'package', 181 package = os.path.join(manifold_folder, 'package',
190 'edgeExtension.appx') 182 'edgeExtension.appx')
191 183
192 shutil.copyfile(package, outfile) 184 shutil.copyfile(package, outfile)
193 finally: 185 finally:
194 shutil.rmtree(tmp_dir, ignore_errors=True) 186 shutil.rmtree(tmp_dir, ignore_errors=True)
LEFTRIGHT

Powered by Google App Engine
This is Rietveld