From ea2e330e43c182dc16b0111ebc69ee5a71ee4ce1 Mon Sep 17 00:00:00 2001 From: Gavin Mak Date: Sat, 11 Mar 2023 06:46:20 +0000 Subject: Format codebase with black and check formatting in CQ Apply rules set by https://gerrit-review.googlesource.com/c/git-repo/+/362954/ across the codebase and fix any lingering errors caught by flake8. Also check black formatting in run_tests (and CQ). Bug: b/267675342 Change-Id: I972d77649dac351150dcfeb1cd1ad0ea2efc1956 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/363474 Reviewed-by: Mike Frysinger Tested-by: Gavin Mak Commit-Queue: Gavin Mak --- release/sign-launcher.py | 178 +++++++++++++++++++++++++------------------ release/sign-tag.py | 171 +++++++++++++++++++++++------------------ release/update_manpages.py | 186 +++++++++++++++++++++++++++------------------ release/util.py | 78 ++++++++++--------- 4 files changed, 355 insertions(+), 258 deletions(-) (limited to 'release') diff --git a/release/sign-launcher.py b/release/sign-launcher.py index ffe23cc5..86566122 100755 --- a/release/sign-launcher.py +++ b/release/sign-launcher.py @@ -28,43 +28,56 @@ import util def sign(opts): - """Sign the launcher!""" - output = '' - for key in opts.keys: - # We use ! at the end of the key so that gpg uses this specific key. - # Otherwise it uses the key as a lookup into the overall key and uses the - # default signing key. i.e. It will see that KEYID_RSA is a subkey of - # another key, and use the primary key to sign instead of the subkey. - cmd = ['gpg', '--homedir', opts.gpgdir, '-u', f'{key}!', '--batch', '--yes', - '--armor', '--detach-sign', '--output', '-', opts.launcher] - ret = util.run(opts, cmd, encoding='utf-8', stdout=subprocess.PIPE) - output += ret.stdout - - # Save the combined signatures into one file. - with open(f'{opts.launcher}.asc', 'w', encoding='utf-8') as fp: - fp.write(output) + """Sign the launcher!""" + output = "" + for key in opts.keys: + # We use ! at the end of the key so that gpg uses this specific key. + # Otherwise it uses the key as a lookup into the overall key and uses + # the default signing key. i.e. It will see that KEYID_RSA is a subkey + # of another key, and use the primary key to sign instead of the subkey. + cmd = [ + "gpg", + "--homedir", + opts.gpgdir, + "-u", + f"{key}!", + "--batch", + "--yes", + "--armor", + "--detach-sign", + "--output", + "-", + opts.launcher, + ] + ret = util.run(opts, cmd, encoding="utf-8", stdout=subprocess.PIPE) + output += ret.stdout + + # Save the combined signatures into one file. + with open(f"{opts.launcher}.asc", "w", encoding="utf-8") as fp: + fp.write(output) def check(opts): - """Check the signature.""" - util.run(opts, ['gpg', '--verify', f'{opts.launcher}.asc']) + """Check the signature.""" + util.run(opts, ["gpg", "--verify", f"{opts.launcher}.asc"]) def get_version(opts): - """Get the version from |launcher|.""" - # Make sure we don't search $PATH when signing the "repo" file in the cwd. - launcher = os.path.join('.', opts.launcher) - cmd = [launcher, '--version'] - ret = util.run(opts, cmd, encoding='utf-8', stdout=subprocess.PIPE) - m = re.search(r'repo launcher version ([0-9.]+)', ret.stdout) - if not m: - sys.exit(f'{opts.launcher}: unable to detect repo version') - return m.group(1) + """Get the version from |launcher|.""" + # Make sure we don't search $PATH when signing the "repo" file in the cwd. + launcher = os.path.join(".", opts.launcher) + cmd = [launcher, "--version"] + ret = util.run(opts, cmd, encoding="utf-8", stdout=subprocess.PIPE) + m = re.search(r"repo launcher version ([0-9.]+)", ret.stdout) + if not m: + sys.exit(f"{opts.launcher}: unable to detect repo version") + return m.group(1) def postmsg(opts, version): - """Helpful info to show at the end for release manager.""" - print(f""" + """Helpful info to show at the end for release manager.""" + print( + f""" Repo launcher bucket: gs://git-repo-downloads/ @@ -81,55 +94,72 @@ NB: If a rollback is necessary, the GS bucket archives old versions, and may be gsutil ls -la gs://git-repo-downloads/repo gs://git-repo-downloads/repo.asc gsutil cp -a public-read gs://git-repo-downloads/repo# gs://git-repo-downloads/repo gsutil cp -a public-read gs://git-repo-downloads/repo.asc# gs://git-repo-downloads/repo.asc -""") +""" # noqa: E501 + ) def get_parser(): - """Get a CLI parser.""" - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('-n', '--dry-run', - dest='dryrun', action='store_true', - help='show everything that would be done') - parser.add_argument('--gpgdir', - default=os.path.join(util.HOMEDIR, '.gnupg', 'repo'), - help='path to dedicated gpg dir with release keys ' - '(default: ~/.gnupg/repo/)') - parser.add_argument('--keyid', dest='keys', default=[], action='append', - help='alternative signing keys to use') - parser.add_argument('launcher', - default=os.path.join(util.TOPDIR, 'repo'), nargs='?', - help='the launcher script to sign') - return parser + """Get a CLI parser.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "-n", + "--dry-run", + dest="dryrun", + action="store_true", + help="show everything that would be done", + ) + parser.add_argument( + "--gpgdir", + default=os.path.join(util.HOMEDIR, ".gnupg", "repo"), + help="path to dedicated gpg dir with release keys " + "(default: ~/.gnupg/repo/)", + ) + parser.add_argument( + "--keyid", + dest="keys", + default=[], + action="append", + help="alternative signing keys to use", + ) + parser.add_argument( + "launcher", + default=os.path.join(util.TOPDIR, "repo"), + nargs="?", + help="the launcher script to sign", + ) + return parser def main(argv): - """The main func!""" - parser = get_parser() - opts = parser.parse_args(argv) - - if not os.path.exists(opts.gpgdir): - parser.error(f'--gpgdir does not exist: {opts.gpgdir}') - if not os.path.exists(opts.launcher): - parser.error(f'launcher does not exist: {opts.launcher}') - - opts.launcher = os.path.relpath(opts.launcher) - print(f'Signing "{opts.launcher}" launcher script and saving to ' - f'"{opts.launcher}.asc"') - - if opts.keys: - print(f'Using custom keys to sign: {" ".join(opts.keys)}') - else: - print('Using official Repo release keys to sign') - opts.keys = [util.KEYID_DSA, util.KEYID_RSA, util.KEYID_ECC] - util.import_release_key(opts) - - version = get_version(opts) - sign(opts) - check(opts) - postmsg(opts, version) - - return 0 - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) + """The main func!""" + parser = get_parser() + opts = parser.parse_args(argv) + + if not os.path.exists(opts.gpgdir): + parser.error(f"--gpgdir does not exist: {opts.gpgdir}") + if not os.path.exists(opts.launcher): + parser.error(f"launcher does not exist: {opts.launcher}") + + opts.launcher = os.path.relpath(opts.launcher) + print( + f'Signing "{opts.launcher}" launcher script and saving to ' + f'"{opts.launcher}.asc"' + ) + + if opts.keys: + print(f'Using custom keys to sign: {" ".join(opts.keys)}') + else: + print("Using official Repo release keys to sign") + opts.keys = [util.KEYID_DSA, util.KEYID_RSA, util.KEYID_ECC] + util.import_release_key(opts) + + version = get_version(opts) + sign(opts) + check(opts) + postmsg(opts, version) + + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/release/sign-tag.py b/release/sign-tag.py index 605437c9..fbfe7b26 100755 --- a/release/sign-tag.py +++ b/release/sign-tag.py @@ -35,46 +35,61 @@ import util KEYID = util.KEYID_DSA # Regular expression to validate tag names. -RE_VALID_TAG = r'^v([0-9]+[.])+[0-9]+$' +RE_VALID_TAG = r"^v([0-9]+[.])+[0-9]+$" def sign(opts): - """Tag the commit & sign it!""" - # We use ! at the end of the key so that gpg uses this specific key. - # Otherwise it uses the key as a lookup into the overall key and uses the - # default signing key. i.e. It will see that KEYID_RSA is a subkey of - # another key, and use the primary key to sign instead of the subkey. - cmd = ['git', 'tag', '-s', opts.tag, '-u', f'{opts.key}!', - '-m', f'repo {opts.tag}', opts.commit] - - key = 'GNUPGHOME' - print('+', f'export {key}="{opts.gpgdir}"') - oldvalue = os.getenv(key) - os.putenv(key, opts.gpgdir) - util.run(opts, cmd) - if oldvalue is None: - os.unsetenv(key) - else: - os.putenv(key, oldvalue) + """Tag the commit & sign it!""" + # We use ! at the end of the key so that gpg uses this specific key. + # Otherwise it uses the key as a lookup into the overall key and uses the + # default signing key. i.e. It will see that KEYID_RSA is a subkey of + # another key, and use the primary key to sign instead of the subkey. + cmd = [ + "git", + "tag", + "-s", + opts.tag, + "-u", + f"{opts.key}!", + "-m", + f"repo {opts.tag}", + opts.commit, + ] + + key = "GNUPGHOME" + print("+", f'export {key}="{opts.gpgdir}"') + oldvalue = os.getenv(key) + os.putenv(key, opts.gpgdir) + util.run(opts, cmd) + if oldvalue is None: + os.unsetenv(key) + else: + os.putenv(key, oldvalue) def check(opts): - """Check the signature.""" - util.run(opts, ['git', 'tag', '--verify', opts.tag]) + """Check the signature.""" + util.run(opts, ["git", "tag", "--verify", opts.tag]) def postmsg(opts): - """Helpful info to show at the end for release manager.""" - cmd = ['git', 'rev-parse', 'remotes/origin/stable'] - ret = util.run(opts, cmd, encoding='utf-8', stdout=subprocess.PIPE) - current_release = ret.stdout.strip() - - cmd = ['git', 'log', '--format=%h (%aN) %s', '--no-merges', - f'remotes/origin/stable..{opts.tag}'] - ret = util.run(opts, cmd, encoding='utf-8', stdout=subprocess.PIPE) - shortlog = ret.stdout.strip() - - print(f""" + """Helpful info to show at the end for release manager.""" + cmd = ["git", "rev-parse", "remotes/origin/stable"] + ret = util.run(opts, cmd, encoding="utf-8", stdout=subprocess.PIPE) + current_release = ret.stdout.strip() + + cmd = [ + "git", + "log", + "--format=%h (%aN) %s", + "--no-merges", + f"remotes/origin/stable..{opts.tag}", + ] + ret = util.run(opts, cmd, encoding="utf-8", stdout=subprocess.PIPE) + shortlog = ret.stdout.strip() + + print( + f""" Here's the short log since the last release. {shortlog} @@ -84,57 +99,69 @@ NB: People will start upgrading to this version immediately. To roll back a release: git push origin --force {current_release}:stable -n -""") +""" + ) def get_parser(): - """Get a CLI parser.""" - parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument('-n', '--dry-run', - dest='dryrun', action='store_true', - help='show everything that would be done') - parser.add_argument('--gpgdir', - default=os.path.join(util.HOMEDIR, '.gnupg', 'repo'), - help='path to dedicated gpg dir with release keys ' - '(default: ~/.gnupg/repo/)') - parser.add_argument('-f', '--force', action='store_true', - help='force signing of any tag') - parser.add_argument('--keyid', dest='key', - help='alternative signing key to use') - parser.add_argument('tag', - help='the tag to create (e.g. "v2.0")') - parser.add_argument('commit', default='HEAD', nargs='?', - help='the commit to tag') - return parser + """Get a CLI parser.""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + parser.add_argument( + "-n", + "--dry-run", + dest="dryrun", + action="store_true", + help="show everything that would be done", + ) + parser.add_argument( + "--gpgdir", + default=os.path.join(util.HOMEDIR, ".gnupg", "repo"), + help="path to dedicated gpg dir with release keys " + "(default: ~/.gnupg/repo/)", + ) + parser.add_argument( + "-f", "--force", action="store_true", help="force signing of any tag" + ) + parser.add_argument( + "--keyid", dest="key", help="alternative signing key to use" + ) + parser.add_argument("tag", help='the tag to create (e.g. "v2.0")') + parser.add_argument( + "commit", default="HEAD", nargs="?", help="the commit to tag" + ) + return parser def main(argv): - """The main func!""" - parser = get_parser() - opts = parser.parse_args(argv) + """The main func!""" + parser = get_parser() + opts = parser.parse_args(argv) - if not os.path.exists(opts.gpgdir): - parser.error(f'--gpgdir does not exist: {opts.gpgdir}') + if not os.path.exists(opts.gpgdir): + parser.error(f"--gpgdir does not exist: {opts.gpgdir}") - if not opts.force and not re.match(RE_VALID_TAG, opts.tag): - parser.error(f'tag "{opts.tag}" does not match regex "{RE_VALID_TAG}"; ' - 'use --force to sign anyways') + if not opts.force and not re.match(RE_VALID_TAG, opts.tag): + parser.error( + f'tag "{opts.tag}" does not match regex "{RE_VALID_TAG}"; ' + "use --force to sign anyways" + ) - if opts.key: - print(f'Using custom key to sign: {opts.key}') - else: - print('Using official Repo release key to sign') - opts.key = KEYID - util.import_release_key(opts) + if opts.key: + print(f"Using custom key to sign: {opts.key}") + else: + print("Using official Repo release key to sign") + opts.key = KEYID + util.import_release_key(opts) - sign(opts) - check(opts) - postmsg(opts) + sign(opts) + check(opts) + postmsg(opts) - return 0 + return 0 -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/release/update_manpages.py b/release/update_manpages.py index d1bf8928..cd2acc01 100644 --- a/release/update_manpages.py +++ b/release/update_manpages.py @@ -29,91 +29,125 @@ import sys import tempfile TOPDIR = Path(__file__).resolve().parent.parent -MANDIR = TOPDIR.joinpath('man') +MANDIR = TOPDIR.joinpath("man") # Load repo local modules. sys.path.insert(0, str(TOPDIR)) from git_command import RepoSourceVersion import subcmds + def worker(cmd, **kwargs): - subprocess.run(cmd, **kwargs) + subprocess.run(cmd, **kwargs) + def main(argv): - parser = argparse.ArgumentParser(description=__doc__) - opts = parser.parse_args(argv) - - if not shutil.which('help2man'): - sys.exit('Please install help2man to continue.') - - # Let repo know we're generating man pages so it can avoid some dynamic - # behavior (like probing active number of CPUs). We use a weird name & - # value to make it less likely for users to set this var themselves. - os.environ['_REPO_GENERATE_MANPAGES_'] = ' indeed! ' - - # "repo branch" is an alias for "repo branches". - del subcmds.all_commands['branch'] - (MANDIR / 'repo-branch.1').write_text('.so man1/repo-branches.1') - - version = RepoSourceVersion() - cmdlist = [['help2man', '-N', '-n', f'repo {cmd} - manual page for repo {cmd}', - '-S', f'repo {cmd}', '-m', 'Repo Manual', f'--version-string={version}', - '-o', MANDIR.joinpath(f'repo-{cmd}.1.tmp'), './repo', - '-h', f'help {cmd}'] for cmd in subcmds.all_commands] - cmdlist.append(['help2man', '-N', '-n', 'repository management tool built on top of git', - '-S', 'repo', '-m', 'Repo Manual', f'--version-string={version}', - '-o', MANDIR.joinpath('repo.1.tmp'), './repo', - '-h', '--help-all']) - - with tempfile.TemporaryDirectory() as tempdir: - tempdir = Path(tempdir) - repo_dir = tempdir / '.repo' - repo_dir.mkdir() - (repo_dir / 'repo').symlink_to(TOPDIR) - - # Create a repo wrapper using the active Python executable. We can't pass - # this directly to help2man as it's too simple, so insert it via shebang. - data = (TOPDIR / 'repo').read_text(encoding='utf-8') - tempbin = tempdir / 'repo' - tempbin.write_text(f'#!{sys.executable}\n' + data, encoding='utf-8') - tempbin.chmod(0o755) - - # Run all cmd in parallel, and wait for them to finish. - with multiprocessing.Pool() as pool: - pool.map(partial(worker, cwd=tempdir, check=True), cmdlist) - - for tmp_path in MANDIR.glob('*.1.tmp'): - path = tmp_path.parent / tmp_path.stem - old_data = path.read_text() if path.exists() else '' - - data = tmp_path.read_text() - tmp_path.unlink() - - data = replace_regex(data) - - # If the only thing that changed was the date, don't refresh. This avoids - # a lot of noise when only one file actually updates. - old_data = re.sub(r'^(\.TH REPO "1" ")([^"]+)', r'\1', old_data, flags=re.M) - new_data = re.sub(r'^(\.TH REPO "1" ")([^"]+)', r'\1', data, flags=re.M) - if old_data != new_data: - path.write_text(data) + parser = argparse.ArgumentParser(description=__doc__) + parser.parse_args(argv) + + if not shutil.which("help2man"): + sys.exit("Please install help2man to continue.") + + # Let repo know we're generating man pages so it can avoid some dynamic + # behavior (like probing active number of CPUs). We use a weird name & + # value to make it less likely for users to set this var themselves. + os.environ["_REPO_GENERATE_MANPAGES_"] = " indeed! " + + # "repo branch" is an alias for "repo branches". + del subcmds.all_commands["branch"] + (MANDIR / "repo-branch.1").write_text(".so man1/repo-branches.1") + + version = RepoSourceVersion() + cmdlist = [ + [ + "help2man", + "-N", + "-n", + f"repo {cmd} - manual page for repo {cmd}", + "-S", + f"repo {cmd}", + "-m", + "Repo Manual", + f"--version-string={version}", + "-o", + MANDIR.joinpath(f"repo-{cmd}.1.tmp"), + "./repo", + "-h", + f"help {cmd}", + ] + for cmd in subcmds.all_commands + ] + cmdlist.append( + [ + "help2man", + "-N", + "-n", + "repository management tool built on top of git", + "-S", + "repo", + "-m", + "Repo Manual", + f"--version-string={version}", + "-o", + MANDIR.joinpath("repo.1.tmp"), + "./repo", + "-h", + "--help-all", + ] + ) + + with tempfile.TemporaryDirectory() as tempdir: + tempdir = Path(tempdir) + repo_dir = tempdir / ".repo" + repo_dir.mkdir() + (repo_dir / "repo").symlink_to(TOPDIR) + + # Create a repo wrapper using the active Python executable. We can't + # pass this directly to help2man as it's too simple, so insert it via + # shebang. + data = (TOPDIR / "repo").read_text(encoding="utf-8") + tempbin = tempdir / "repo" + tempbin.write_text(f"#!{sys.executable}\n" + data, encoding="utf-8") + tempbin.chmod(0o755) + + # Run all cmd in parallel, and wait for them to finish. + with multiprocessing.Pool() as pool: + pool.map(partial(worker, cwd=tempdir, check=True), cmdlist) + + for tmp_path in MANDIR.glob("*.1.tmp"): + path = tmp_path.parent / tmp_path.stem + old_data = path.read_text() if path.exists() else "" + + data = tmp_path.read_text() + tmp_path.unlink() + + data = replace_regex(data) + + # If the only thing that changed was the date, don't refresh. This + # avoids a lot of noise when only one file actually updates. + old_data = re.sub( + r'^(\.TH REPO "1" ")([^"]+)', r"\1", old_data, flags=re.M + ) + new_data = re.sub(r'^(\.TH REPO "1" ")([^"]+)', r"\1", data, flags=re.M) + if old_data != new_data: + path.write_text(data) def replace_regex(data): - """Replace semantically null regexes in the data. - - Args: - data: manpage text. - - Returns: - Updated manpage text. - """ - regex = ( - (r'(It was generated by help2man) [0-9.]+', r'\g<1>.'), - (r'^\033\[[0-9;]*m([^\033]*)\033\[m', r'\g<1>'), - (r'^\.IP\n(.*:)\n', r'.SS \g<1>\n'), - (r'^\.PP\nDescription', r'.SH DETAILS'), - ) - for pattern, replacement in regex: - data = re.sub(pattern, replacement, data, flags=re.M) - return data + """Replace semantically null regexes in the data. + + Args: + data: manpage text. + + Returns: + Updated manpage text. + """ + regex = ( + (r"(It was generated by help2man) [0-9.]+", r"\g<1>."), + (r"^\033\[[0-9;]*m([^\033]*)\033\[m", r"\g<1>"), + (r"^\.IP\n(.*:)\n", r".SS \g<1>\n"), + (r"^\.PP\nDescription", r".SH DETAILS"), + ) + for pattern, replacement in regex: + data = re.sub(pattern, replacement, data, flags=re.M) + return data diff --git a/release/util.py b/release/util.py index 9d0eb1dc..df7a5638 100644 --- a/release/util.py +++ b/release/util.py @@ -20,54 +20,60 @@ import subprocess import sys -assert sys.version_info >= (3, 6), 'This module requires Python 3.6+' +assert sys.version_info >= (3, 6), "This module requires Python 3.6+" TOPDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -HOMEDIR = os.path.expanduser('~') +HOMEDIR = os.path.expanduser("~") # These are the release keys we sign with. -KEYID_DSA = '8BB9AD793E8E6153AF0F9A4416530D5E920F5C65' -KEYID_RSA = 'A34A13BE8E76BFF46A0C022DA2E75A824AAB9624' -KEYID_ECC = 'E1F9040D7A3F6DAFAC897CD3D3B95DA243E48A39' +KEYID_DSA = "8BB9AD793E8E6153AF0F9A4416530D5E920F5C65" +KEYID_RSA = "A34A13BE8E76BFF46A0C022DA2E75A824AAB9624" +KEYID_ECC = "E1F9040D7A3F6DAFAC897CD3D3B95DA243E48A39" def cmdstr(cmd): - """Get a nicely quoted shell command.""" - ret = [] - for arg in cmd: - if not re.match(r'^[a-zA-Z0-9/_.=-]+$', arg): - arg = f'"{arg}"' - ret.append(arg) - return ' '.join(ret) + """Get a nicely quoted shell command.""" + ret = [] + for arg in cmd: + if not re.match(r"^[a-zA-Z0-9/_.=-]+$", arg): + arg = f'"{arg}"' + ret.append(arg) + return " ".join(ret) def run(opts, cmd, check=True, **kwargs): - """Helper around subprocess.run to include logging.""" - print('+', cmdstr(cmd)) - if opts.dryrun: - cmd = ['true', '--'] + cmd - try: - return subprocess.run(cmd, check=check, **kwargs) - except subprocess.CalledProcessError as e: - print(f'aborting: {e}', file=sys.stderr) - sys.exit(1) + """Helper around subprocess.run to include logging.""" + print("+", cmdstr(cmd)) + if opts.dryrun: + cmd = ["true", "--"] + cmd + try: + return subprocess.run(cmd, check=check, **kwargs) + except subprocess.CalledProcessError as e: + print(f"aborting: {e}", file=sys.stderr) + sys.exit(1) def import_release_key(opts): - """Import the public key of the official release repo signing key.""" - # Extract the key from our repo launcher. - launcher = getattr(opts, 'launcher', os.path.join(TOPDIR, 'repo')) - print(f'Importing keys from "{launcher}" launcher script') - with open(launcher, encoding='utf-8') as fp: - data = fp.read() - - keys = re.findall( - r'\n-----BEGIN PGP PUBLIC KEY BLOCK-----\n[^-]*' - r'\n-----END PGP PUBLIC KEY BLOCK-----\n', data, flags=re.M) - run(opts, ['gpg', '--import'], input='\n'.join(keys).encode('utf-8')) - - print('Marking keys as fully trusted') - run(opts, ['gpg', '--import-ownertrust'], - input=f'{KEYID_DSA}:6:\n'.encode('utf-8')) + """Import the public key of the official release repo signing key.""" + # Extract the key from our repo launcher. + launcher = getattr(opts, "launcher", os.path.join(TOPDIR, "repo")) + print(f'Importing keys from "{launcher}" launcher script') + with open(launcher, encoding="utf-8") as fp: + data = fp.read() + + keys = re.findall( + r"\n-----BEGIN PGP PUBLIC KEY BLOCK-----\n[^-]*" + r"\n-----END PGP PUBLIC KEY BLOCK-----\n", + data, + flags=re.M, + ) + run(opts, ["gpg", "--import"], input="\n".join(keys).encode("utf-8")) + + print("Marking keys as fully trusted") + run( + opts, + ["gpg", "--import-ownertrust"], + input=f"{KEYID_DSA}:6:\n".encode("utf-8"), + ) -- cgit v1.2.3-54-g00ecf