Skip to content

Commit

Permalink
Python 2 and 3 tweaks.
Browse files Browse the repository at this point in the history
Working toward #456.

- Add a wrap to test under python 2 and 3.
- Minor tweaks to improve support for both pythons.
- Tweak the tools a little for dual support.

RELNOTES: None.
PiperOrigin-RevId: 252104076
  • Loading branch information
thomasvl authored and swiple-rules-gardener committed Jun 10, 2019
1 parent 28844d7 commit 69cbc51
Show file tree
Hide file tree
Showing 23 changed files with 264 additions and 152 deletions.
7 changes: 6 additions & 1 deletion tools/bundletool/BUILD
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
load("//tools:py2and3_test.bzl", "py2and3_test")

licenses(["notice"])

py_binary(
name = "bundletool",
srcs = ["bundletool.py"],
srcs_version = "PY2AND3",
# Used by the rule implementations, so it needs to be public; but
# should be considered an implementation detail of the rules and
# not used by other things.
Expand All @@ -13,18 +16,20 @@ py_binary(
py_library(
name = "bundletool_lib",
srcs = ["bundletool.py"],
srcs_version = "PY2AND3",
)

py_binary(
name = "bundletool_experimental",
srcs = ["bundletool_experimental.py"],
srcs_version = "PY2AND3",
# Used by the rule implementations, so it needs to be public; but
# should be considered an implementation detail of the rules and
# not used by other things.
visibility = ["//visibility:public"],
)

py_test(
py2and3_test(
name = "bundletool_unittest",
srcs = ["bundletool_unittest.py"],
deps = [
Expand Down
3 changes: 2 additions & 1 deletion tools/bundletool/bundletool.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Lint as: python2, python3
# Copyright 2017 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -52,8 +53,8 @@
Apple at the root of the archive as well as within the bundle itself.
"""

import json
import hashlib
import json
import os
import sys
import zipfile
Expand Down
1 change: 1 addition & 0 deletions tools/bundletool/bundletool_experimental.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Lint as: python2, python3
# Copyright 2017 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
1 change: 1 addition & 0 deletions tools/bundletool/bundletool_unittest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Lint as: python2, python3
# Copyright 2017 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
1 change: 1 addition & 0 deletions tools/clangrttool/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ licenses(["notice"])
py_binary(
name = "clangrttool",
srcs = ["clangrttool.py"],
srcs_version = "PY2AND3",
# Used by the rule implementations, so it needs to be public; but
# should be considered an implementation detail of the rules and
# not used by other things.
Expand Down
5 changes: 3 additions & 2 deletions tools/clangrttool/clangrttool.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Lint as: python2, python3
# Copyright 2017 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -27,8 +28,9 @@
import zipfile

# Third party imports
from macholib.MachO import MachO

from macholib import mach_o
from macholib.MachO import MachO
from macholib.ptypes import sizeof


Expand Down Expand Up @@ -150,4 +152,3 @@ def run(self):
# Log tools errors cleanly for build output.
sys.stderr.write('ERROR: %s\n' % e)
sys.exit(1)

1 change: 1 addition & 0 deletions tools/codesigningtool/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ licenses(["notice"])
py_binary(
name = "codesigningtool",
srcs = ["codesigningtool.py"],
srcs_version = "PY2AND3",
# Used by the rule implementations, so it needs to be public; but
# should be considered an implementation detail of the rules and
# not used by other things.
Expand Down
209 changes: 112 additions & 97 deletions tools/codesigningtool/codesigningtool.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Lint as: python2, python3
# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -35,128 +36,142 @@


def _check_output(args, inputstr=None):
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = proc.communicate(input=inputstr)
if proc.returncode != 0:
# print the stdout and stderr, as the exception won't print it.
print("ERROR:{stdout}\n\n{stderr}".format(stdout=stdout, stderr=stderr))
raise subprocess.CalledProcessError(proc.returncode, args)
return stdout, stderr
proc = subprocess.Popen(
args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = proc.communicate(input=inputstr)
if proc.returncode != 0:
# print the stdout and stderr, as the exception won't print it.
print("ERROR:{stdout}\n\n{stderr}".format(stdout=stdout, stderr=stderr))
raise subprocess.CalledProcessError(proc.returncode, args)
return stdout, stderr


def plist_from_bytes(byte_content):
try:
return plistlib.loads(byte_content)
except AttributeError:
return plistlib.readPlistFromString(byte_content)
try:
return plistlib.loads(byte_content)
except AttributeError:
return plistlib.readPlistFromString(byte_content)


def _parse_mobileprovision_file(mobileprovision_file):
"""Reads and parses a mobileprovision file."""
plist_xml = subprocess.check_output([
"security", "cms",
"-D",
"-i", mobileprovision_file,
])
return plist_from_bytes(plist_xml)
"""Reads and parses a mobileprovision file."""
plist_xml = subprocess.check_output([
"security",
"cms",
"-D",
"-i",
mobileprovision_file,
])
return plist_from_bytes(plist_xml)


def _certificate_fingerprint(identity):
"""Extracts a fingerprint given identity in a mobileprovision file."""
fingerprint, stderr = _check_output([
"openssl", "x509", "-inform", "DER", "-noout", "-fingerprint",
], inputstr=identity)
fingerprint = fingerprint.decode("utf-8").strip()
fingerprint = fingerprint.replace("SHA1 Fingerprint=", "")
fingerprint = fingerprint.replace(":", "")
return fingerprint
"""Extracts a fingerprint given identity in a mobileprovision file."""
fingerprint, stderr = _check_output([
"openssl",
"x509",
"-inform",
"DER",
"-noout",
"-fingerprint",
],
inputstr=identity)
fingerprint = fingerprint.decode("utf-8").strip()
fingerprint = fingerprint.replace("SHA1 Fingerprint=", "")
fingerprint = fingerprint.replace(":", "")
return fingerprint


def _get_identities_from_provisioning_profile(mpf):
"""Iterates through all the identities in a provisioning profile, lazily."""
for identity in mpf["DeveloperCertificates"]:
yield _certificate_fingerprint(identity.data)
"""Iterates through all the identities in a provisioning profile, lazily."""
for identity in mpf["DeveloperCertificates"]:
yield _certificate_fingerprint(identity.data)


def _find_codesign_identities(identity=None):
"""Finds code signing identities on the current system."""
ids = []
output, stderr = _check_output([
"security", "find-identity", "-v", "-p", "codesigning",
])
output = output.decode("utf-8").strip()
pattern = "(?P<hash>[A-F0-9]{40})"
if identity:
pattern += r'\s+"(?P<full_name>.*?{}.*?)"'.format(re.escape(identity))
regex = re.compile(pattern)
for line in output.splitlines():
# CSSMERR_TP_CERT_REVOKED comes from Security.framework/cssmerr.h
if "CSSMERR_TP_CERT_REVOKED" in line:
continue
m = regex.search(line)
if m:
groups = m.groupdict()
id = groups.get("full_name") or groups["hash"]
ids.append(id)
return ids
"""Finds code signing identities on the current system."""
ids = []
output, stderr = _check_output([
"security",
"find-identity",
"-v",
"-p",
"codesigning",
])
output = output.decode("utf-8").strip()
pattern = "(?P<hash>[A-F0-9]{40})"
if identity:
pattern += r'\s+"(?P<full_name>.*?{}.*?)"'.format(re.escape(identity))
regex = re.compile(pattern)
for line in output.splitlines():
# CSSMERR_TP_CERT_REVOKED comes from Security.framework/cssmerr.h
if "CSSMERR_TP_CERT_REVOKED" in line:
continue
m = regex.search(line)
if m:
groups = m.groupdict()
id = groups.get("full_name") or groups["hash"]
ids.append(id)
return ids


def _find_codesign_identity(mobileprovision):
"""Finds a valid identity on the system given a mobileprovision file."""
mpf = _parse_mobileprovision_file(mobileprovision)
ids_codesign = set(_find_codesign_identities())
for id_mpf in _get_identities_from_provisioning_profile(mpf):
if id_mpf in ids_codesign:
return id_mpf
"""Finds a valid identity on the system given a mobileprovision file."""
mpf = _parse_mobileprovision_file(mobileprovision)
ids_codesign = set(_find_codesign_identities())
for id_mpf in _get_identities_from_provisioning_profile(mpf):
if id_mpf in ids_codesign:
return id_mpf


def _filter_codesign_output(codesign_output):
"""Filters the codesign output which can be extra verbose."""
filtered_lines = []
for line in codesign_output.split("\n"):
if line and not _BENIGN_CODESIGN_OUTPUT_REGEX.search(line):
filtered_lines.append(line)
filtered_lines.append(line)
return "\n".join(filtered_lines)

def main(argv):
parser = argparse.ArgumentParser(description="codesign wrapper")
parser.add_argument("--mobileprovision", type=str,
help="mobileprovision file")
parser.add_argument("--codesign", required=True, type=str,
help="path to codesign binary")
parser.add_argument("--identity", type=str,
help="specific identity to sign with")
args, codesign_args = parser.parse_known_args()
identity = args.identity
if identity is None:
identity = _find_codesign_identity(args.mobileprovision)
elif identity != "-":
matching_identities = _find_codesign_identities(identity)
if matching_identities:
identity = matching_identities[0]
else:
print(
"ERROR: No signing identity found for '{}'".format(identity),
file=sys.stderr
)
return -1
# No identity was found, fail
if identity == None:
print("ERROR: Unable to find an identity on the system matching the "\
"ones in %s" % args.mobileprovision, file=sys.stderr)
return 1
stdout, stderr = _check_output(
[args.codesign, "-v", "--sign", identity] + codesign_args,
)
if stdout:
filtered_stdout = _filter_codesign_output(stdout)
if filtered_stdout:
print(filtered_stdout)
if stderr:
filtered_stderr = _filter_codesign_output(stderr)
if filtered_stderr:
print(filtered_stderr)
parser = argparse.ArgumentParser(description="codesign wrapper")
parser.add_argument(
"--mobileprovision", type=str, help="mobileprovision file")
parser.add_argument(
"--codesign", required=True, type=str, help="path to codesign binary")
parser.add_argument(
"--identity", type=str, help="specific identity to sign with")
args, codesign_args = parser.parse_known_args()
identity = args.identity
if identity is None:
identity = _find_codesign_identity(args.mobileprovision)
elif identity != "-":
matching_identities = _find_codesign_identities(identity)
if matching_identities:
identity = matching_identities[0]
else:
print(
"ERROR: No signing identity found for '{}'".format(identity),
file=sys.stderr)
return -1
# No identity was found, fail
if identity == None:
print("ERROR: Unable to find an identity on the system matching the "\
"ones in %s" % args.mobileprovision, file=sys.stderr)
return 1
stdout, stderr = _check_output([args.codesign, "-v", "--sign", identity] +
codesign_args,)
if stdout:
filtered_stdout = _filter_codesign_output(stdout)
if filtered_stdout:
print(filtered_stdout)
if stderr:
filtered_stderr = _filter_codesign_output(stderr)
if filtered_stderr:
print(filtered_stderr)


if __name__ == '__main__':
sys.exit(main(sys.argv))
sys.exit(main(sys.argv))
6 changes: 5 additions & 1 deletion tools/plisttool/BUILD
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
load("//tools:py2and3_test.bzl", "py2and3_test")

licenses(["notice"])

py_binary(
name = "plisttool",
srcs = ["plisttool.py"],
srcs_version = "PY2AND3",
# Used by the rule implementations, so it needs to be public; but
# should be considered an implementation detail of the rules and
# not used by other things.
Expand All @@ -15,9 +18,10 @@ py_library(
srcs = [
"plisttool.py",
],
srcs_version = "PY2AND3",
)

py_test(
py2and3_test(
name = "plisttool_unittest",
srcs = ["plisttool_unittest.py"],
deps = [
Expand Down
Loading

0 comments on commit 69cbc51

Please sign in to comment.