3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this
5 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 from argparse
import ArgumentParser
15 def getFileHashAndSize(filename
):
16 sha512Hash
= 'UNKNOWN'
20 # open in binary mode to make sure we get consistent results
21 # across all platforms
22 f
= open(filename
, "rb")
23 shaObj
= hashlib
.sha512(f
.read())
24 sha512Hash
= shaObj
.hexdigest()
26 size
= os
.path
.getsize(filename
)
30 return (sha512Hash
, size
)
32 def getMarProperties(filename
, partial
=False):
33 if not os
.path
.exists(filename
):
35 (mar_hash
, mar_size
) = getFileHashAndSize(filename
)
36 martype
= 'partial' if partial
else 'complete'
38 '%sMarFilename' % martype
: os
.path
.basename(filename
),
39 '%sMarSize' % martype
: mar_size
,
40 '%sMarHash' % martype
: mar_hash
,
43 def getUrlProperties(filename
):
44 # let's create a switch case using name-spaces/dict
45 # rather than a long if/else with duplicate code
46 property_conditions
= [
47 # key: property name, value: condition
48 ('symbolsUrl', lambda m
: m
.endswith('crashreporter-symbols.zip') or
49 m
.endswith('crashreporter-symbols-full.zip')),
50 ('testsUrl', lambda m
: m
.endswith(('tests.tar.bz2', 'tests.zip'))),
51 ('unsignedApkUrl', lambda m
: m
.endswith('apk') and
52 'unsigned-unaligned' in m
),
53 ('robocopApkUrl', lambda m
: m
.endswith('apk') and 'robocop' in m
),
54 ('jsshellUrl', lambda m
: 'jsshell-' in m
and m
.endswith('.zip')),
55 ('completeMarUrl', lambda m
: m
.endswith('.complete.mar')),
56 ('partialMarUrl', lambda m
: m
.endswith('.mar') and '.partial.' in m
),
57 # packageUrl must be last!
58 ('packageUrl', lambda m
: True),
60 url_re
= re
.compile(r
'''^(https?://.*?\.(?:tar\.bz2|dmg|zip|apk|rpm|mar|tar\.gz))$''')
64 with
open(filename
) as f
:
66 m
= url_re
.match(line
)
69 for prop
, condition
in property_conditions
:
71 properties
.update({prop
: m
})
74 if e
.errno
!= errno
.ENOENT
:
76 properties
= {prop
: 'UNKNOWN' for prop
, condition
in property_conditions
}
79 def getPartialInfo(props
):
81 "from_buildid": props
.get("previous_buildid"),
82 "size": props
.get("partialMarSize"),
83 "hash": props
.get("partialMarHash"),
84 "url": props
.get("partialMarUrl"),
87 if __name__
== '__main__':
88 parser
= ArgumentParser(description
='Generate mach_build_properties.json for automation builds.')
89 parser
.add_argument("--complete-mar-file", required
=True,
90 action
="store", dest
="complete_mar_file",
91 help="Path to the complete MAR file, relative to the objdir.")
92 parser
.add_argument("--partial-mar-file", required
=False,
93 action
="store", dest
="partial_mar_file",
94 help="Path to the partial MAR file, relative to the objdir.")
95 parser
.add_argument("--upload-output", required
=True,
96 action
="store", dest
="upload_output",
97 help="Path to the text output of 'make upload'")
98 args
= parser
.parse_args()
100 json_data
= getMarProperties(args
.complete_mar_file
)
101 json_data
.update(getUrlProperties(args
.upload_output
))
102 if args
.partial_mar_file
:
103 json_data
.update(getMarProperties(args
.partial_mar_file
, partial
=True))
105 # Pull the previous buildid from the partial mar filename.
106 res
= re
.match(r
'.*\.([0-9]+)-[0-9]+.mar', args
.partial_mar_file
)
108 json_data
['previous_buildid'] = res
.group(1)
110 # Set partialInfo to be a collection of the partial mar properties
112 json_data
['partialInfo'] = getPartialInfo(json_data
)
114 with
open('mach_build_properties.json', 'w') as outfile
:
115 json
.dump(json_data
, outfile
, indent
=4)