From 89ff083a392622ec8843623a86b80a766c5e263c Mon Sep 17 00:00:00 2001 From: Luis Sampaio Date: Wed, 20 Jul 2022 14:41:24 -0700 Subject: [PATCH] Debian: Add modify patch and update iso path - Adds the --modify to the make_patch script which updates the STATUS tag to one of the supported options: DEV, REL or OBS Example: ./make_patch.py modify --status development \ --patch-file PATCH_0001.patch * --formal can also be used if the patch needs to be signed - Updates the deploy dir path to: localdisk/deploy as now we have a single iso for std and rt. - Remove deprecated make_test_patch script Test Plan: Pass: create and modify patch status Pass: modify patch and formal sign it Story: 2009969 Task: 45842 Signed-off-by: Luis Sampaio Change-Id: I508c2a723a07f48f8fc84ed043968eadc5804dcf --- .../cgcs-patch/cgcs_make_patch/make_patch.py | 255 ++++++++++--- .../make_patching_workspace.py | 2 +- sw-patch/scripts/make_test_patch.py | 357 ------------------ 3 files changed, 205 insertions(+), 409 deletions(-) delete mode 100755 sw-patch/scripts/make_test_patch.py diff --git a/sw-patch/cgcs-patch/cgcs_make_patch/make_patch.py b/sw-patch/cgcs-patch/cgcs_make_patch/make_patch.py index bfb67204..eebb3931 100644 --- a/sw-patch/cgcs-patch/cgcs_make_patch/make_patch.py +++ b/sw-patch/cgcs-patch/cgcs_make_patch/make_patch.py @@ -31,11 +31,7 @@ This will create a new commit in the build ostree_repo --clone-repo ostree_test Once the script is done the .patch file can be located at: -$STX_BUILD_HOME/localdisk/lat/std/deploy/ - -Pending items: -- Modify patch Status - +$STX_BUILD_HOME/localdisk/deploy/ """ import argparse import hashlib @@ -52,10 +48,13 @@ from xml.dom import minidom # Signing function sys.path.insert(0, "../../cgcs-patch") from cgcs_patch.patch_signing import sign_files # noqa: E402 pylint: disable=wrong-import-position +from cgcs_patch.patch_verify import verify_files # noqa: E402 pylint: disable=wrong-import-position -# STATUS_OBSOLETE = 'OBS' -# STATUS_RELEASED = 'REL' -STATUS_DEVELOPEMENT = 'DEV' +PATCH_STATUS = { + 'release': 'REL', + 'obsolete': 'OBS', + 'development': 'DEV' +} METADATA_TAGS = ['ID', 'SW_VERSION', 'SUMMARY', 'DESCRIPTION', 'INSTALL_INSTRUCTIONS', 'WARNINGS', 'STATUS', 'UNREMOVABLE', 'REBOOT_REQUIRED', 'REQUIRES', 'RESTART_SCRIPT', 'APPLY_ACTIVE_RELEASE_ONLY'] @@ -103,6 +102,21 @@ class PatchRecipeXMLFail(PatchError): pass +class PatchInvalidStatus(PatchError): + """Invalid status""" + pass + + +class PatchModifyError(PatchError): + """Error while modifying patch""" + pass + + +class PatchValidationFailure(PatchError): + """Patch validation failure""" + pass + + class PatchRecipeData(object): """ Patch data @@ -202,7 +216,7 @@ class PatchBuilder(object): def __init__(self, delta_dir="delta_dir"): try: # ostree repo location - self.deploy_dir = os.path.join(os.environ["STX_BUILD_HOME"], "localdisk/lat/std/deploy") + self.deploy_dir = os.path.join(os.environ["STX_BUILD_HOME"], "localdisk/deploy") self.ostree_repo = os.path.join(self.deploy_dir, "ostree_repo") self.delta_dir = delta_dir self.detached_signature_file = "signature.v2" @@ -243,7 +257,7 @@ class PatchBuilder(object): if "STATUS" in self.patch_data.metadata: self.__add_text_tag_to_xml(top, "status", self.patch_data.metadata["STATUS"]) else: - self.__add_text_tag_to_xml(top, "status", STATUS_DEVELOPEMENT) + self.__add_text_tag_to_xml(top, "status", PATCH_STATUS['development']) self.__add_text_tag_to_xml(top, "unremovable", self.patch_data.metadata["UNREMOVABLE"]) self.__add_text_tag_to_xml(top, "reboot_required", self.patch_data.metadata["REBOOT_REQUIRED"]) @@ -344,18 +358,59 @@ class PatchBuilder(object): return commits_from_base - def __sign_official_patches(self): + def __sign_official_patches(self, patch_file): """ Sign formal patch Called internally once a patch is created and formal flag is set to true + :param patch_file full path to the patch file """ - log.info("Signing patch %s", self.patch_file_name) + log.info("Signing patch %s", patch_file) try: - patch_file_path = os.path.join(self.deploy_dir, self.patch_file_name) - subprocess.check_call(["sign_patch_formal.sh", patch_file_path]) + # patch_file_path = os.path.join(self.deploy_dir, self.patch_file_name) + subprocess.check_call(["sign_patch_formal.sh", patch_file]) except subprocess.CalledProcessError as e: log.exception("Failed to sign official patch. Call to sign_patch_formal.sh process returned non-zero exit status %i", e.returncode) - raise SystemExit(e.returncode) + except FileNotFoundError: + log.exception("sign_patch_formal.sh not found, make sure $STX_BUILD_HOME/repo/cgcs-root/build-tools is in the $PATH") + + def __sign_and_pack(self, patch_file, formal=False): + """ + Generates the patch signatures and pack the .patch file + :param patch_file .patch file full path + """ + filelist = ["metadata.tar", "software.tar"] + # Generate the local signature file + sig = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + for f in filelist: + sig ^= get_md5(f) + + sigfile = open("signature", "w") + sigfile.write("%x" % sig) + sigfile.close() + + # this comes from patch_functions write_patch + # Generate the detached signature + # + # Note: if cert_type requests a formal signature, but the signing key + # is not found, we'll instead sign with the "dev" key and + # need_resign_with_formal is set to True. + need_resign_with_formal = sign_files( + filelist, + self.detached_signature_file, + cert_type=None) + + log.debug("Formal signing status %s", need_resign_with_formal) + + # Save files into .patch + files = [f for f in os.listdir('.') if os.path.isfile(f)] + tar = tarfile.open(patch_file, "w:gz") + for file in files: + tar.add(file) + tar.close() + log.info("Patch file created %s", patch_file) + if formal: + log.info("Trying to sign formal patch") + self.__sign_official_patches(patch_file) def prepare_env(self, clone_repo="ostree-clone"): """ @@ -429,6 +484,7 @@ class PatchBuilder(object): tar = tarfile.open("metadata.tar", "w") tar.add("metadata.xml") tar.close() + os.remove("metadata.xml") if self.patch_data.restart_script: log.info("Saving restart scripts") @@ -437,39 +493,11 @@ class PatchBuilder(object): self.patch_data.restart_script["metadata_name"] ) - filelist = ["metadata.tar", "software.tar"] - # Generate the local signature file - sig = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - for f in filelist: - sig ^= get_md5(f) - - sigfile = open("signature", "w") - sigfile.write("%x" % sig) - sigfile.close() - - # this comes from patch_functions write_patch - # Generate the detached signature - # - # Note: if cert_type requests a formal signature, but the signing key - # is not found, we'll instead sign with the "dev" key and - # need_resign_with_formal is set to True. - need_resign_with_formal = sign_files( - filelist, - self.detached_signature_file, - cert_type=None) - - log.debug("Formal signing status %s", need_resign_with_formal) - - # Create the patch - tar = tarfile.open(os.path.join(self.deploy_dir, self.patch_file_name), "w:gz") - for file in filelist: - tar.add(file) - tar.add("signature") - tar.add(self.detached_signature_file) - if self.patch_data.restart_script and \ - os.path.isfile(self.patch_data.restart_script["metadata_name"]): - tar.add(self.patch_data.restart_script["metadata_name"]) - tar.close() + # Sign and create the .patch file + self.__sign_and_pack( + os.path.join(self.deploy_dir, self.patch_file_name), + formal + ) os.chdir(self.deploy_dir) shutil.rmtree(tmpdir) @@ -477,9 +505,91 @@ class PatchBuilder(object): log.info("Patch file created %s at %s", self.patch_file_name, self.deploy_dir) - if formal: - log.info("Trying to sign formal patch") - self.__sign_official_patches() + def modify_metadata_text(self, filename, key, value): + """ + Open an xml file, find first element matching 'key' and replace the text with 'value' + """ + new_filename = "%s.new" % filename + tree = ET.parse(filename) + + # Prevent a proliferation of carriage returns when we write this XML back out to file. + for e in tree.iter(): + if e.text is not None: + e.text = e.text.rstrip() + if e.tail is not None: + e.tail = e.tail.rstrip() + + root = tree.getroot() + # Make the substitution + e = root.find(key) + if e is None: + msg = "modify_metadata_text: failed to find tag '%s'" % key + log.error(msg) + raise PatchValidationFailure(msg) + e.text = value + + # write the modified file + outfile = open(new_filename, 'w') + rough_xml = ET.tostring(root) + outfile.write(minidom.parseString(rough_xml).toprettyxml(indent=" ")) + outfile.close() + os.rename(new_filename, filename) + + def read_patch(self, path): + """ + Extract the patch to current dir and validate signature + """ + # Open the patch file and extract the contents to the current dir + tar = tarfile.open(path, "r:gz") + tar.extractall() + # Checks signature + sigfile = open("signature", "r") + sig = int(sigfile.read(), 16) + sigfile.close() + + filelist = ["metadata.tar", "software.tar"] + expected_sig = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + for f in filelist: + sig ^= get_md5(f) + + if sig != expected_sig: + msg = "Patch failed verification" + log.error(msg) + raise PatchValidationFailure(msg) + + # Verify detached signature + if os.path.exists(self.detached_signature_file): + sig_valid = verify_files( + filelist, + self.detached_signature_file, + cert_type=None) + sig_valid = True + if sig_valid is True: + msg = "Signature verified, patch has been signed" + else: + msg = "Signature check failed" + raise PatchValidationFailure(msg) + else: + msg = "Patch has not been signed" + raise PatchValidationFailure(msg) + + # Extract metadata xml + tar = tarfile.open("metadata.tar") + tar.extractall() + + def write_patch(self, patch_file, formal=False): + """ + Write files into .patch file and sign + """ + log.info("Saving patch file") + tar = tarfile.open("metadata.tar", "w") + tar.add("metadata.xml") + tar.close() + # remove the xml + os.remove("metadata.xml") + + # Sign and create the .patch file + self.__sign_and_pack(patch_file, formal) def handle_create(params): @@ -510,6 +620,38 @@ def handle_prepare(params): patch_builder.prepare_env(params.clone_repo) +def handle_modify(params): + """ + Modify patch status and resigns + """ + log.info("Modifying patch %s", params.patch_file) + if not os.path.isfile(params.patch_file): + raise FileNotFoundError("Patch file not found") + + if params.status not in PATCH_STATUS: + raise PatchInvalidStatus(f"Supported status are {PATCH_STATUS}") + + # Modify patch + orig_wd = os.getcwd() + workdir = tempfile.mkdtemp(prefix="patch_modify_") + os.chdir(workdir) + + try: + p = PatchBuilder() + # extract and validate signatures + p.read_patch(params.patch_file) + log.info("Updating patch status to %s", PATCH_STATUS[params.status]) + # Update Status + p.modify_metadata_text("metadata.xml", "status", PATCH_STATUS[params.status]) + p.write_patch(params.patch_file, params.formal) + + except PatchModifyError: + log.exception("Error while modifying patch") + finally: + shutil.rmtree(workdir) + os.chdir(orig_wd) + + if __name__ == "__main__": parser = argparse.ArgumentParser(description="Debian make_patch helper") @@ -532,6 +674,15 @@ if __name__ == "__main__": create_parser.add_argument("-d", "--delta-dir", type=str, help="Delta dir name", default="delta-dir") create_parser.add_argument("-c", "--clone-repo", type=str, help="Clone repo directory name", default=None, required=True) + # Modify Patch action + modify_parser = subparsers.add_parser("modify", + add_help=False, + description="modify patch status", + help="Modify patch status - DEV, REL, OBS") + modify_parser.add_argument("-s", "--status", type=str, help="Patch status", required=True) + modify_parser.add_argument("-f", "--formal", action="store_true", help="Formal patch flag") + modify_parser.add_argument("-pf", "--patch-file", type=str, help="Patch file", required=True) + args = parser.parse_args() log.debug("Args: %s", args) @@ -539,5 +690,7 @@ if __name__ == "__main__": handle_create(args) elif args.cmd == "prepare": handle_prepare(args) + elif args.cmd == "modify": + handle_modify(args) log.info("Done") diff --git a/sw-patch/cgcs-patch/cgcs_make_patch/make_patching_workspace.py b/sw-patch/cgcs-patch/cgcs_make_patch/make_patching_workspace.py index 1d62498b..2b1fc8c2 100644 --- a/sw-patch/cgcs-patch/cgcs_make_patch/make_patching_workspace.py +++ b/sw-patch/cgcs-patch/cgcs_make_patch/make_patching_workspace.py @@ -252,7 +252,7 @@ if __name__ == "__main__": patch_env = PatchEnv() log.info("Environment: %s", patch_env) - deploy_dir = os.path.join(patch_env.build_home, "localdisk", "lat", "std", "deploy") + deploy_dir = os.path.join(patch_env.build_home, "localdisk", "deploy") ostree_repo_build = os.path.join(deploy_dir, "ostree_repo") # Setup env diff --git a/sw-patch/scripts/make_test_patch.py b/sw-patch/scripts/make_test_patch.py deleted file mode 100755 index f115d786..00000000 --- a/sw-patch/scripts/make_test_patch.py +++ /dev/null @@ -1,357 +0,0 @@ -# -# Copyright (c) 2022 Wind River Systems, Inc. -# -# SPDX-License-Identifier: Apache-2.0 -# -''' -Create a test patch for Debian - -- fake restart script -- fake dettached signature (signature.v2) - -Prereqs: -- Requires the ostree tool installed - apt-get install ostree -- export STX_BUILD_HOME - e.g: export STX_BUILD_HOME=/localdisk/designer/lsampaio/stx-debian -- pip3 install pycryptodomex - -Setup Steps: - sudo chmod 644 $STX_BUILD_HOME/localdisk/deploy/ostree_repo/.lock - sudo chmod 644 $STX_BUILD_HOME/localdisk/lat/std/deploy/ostree_repo/.lock - python make_test_patch.py --prepare --repo ostree_repo --clone-repo ostree-clone - -Patch Steps: - - - rm -Rf $STX_BUILD_HOME/localdisk/deploy/delta_dir - rm -Rf $STX_BUILD_HOME/localdisk/lat/std/deploy/delta_dir - python make_test_patch.py --create --repo ostree_repo --clone-repo ostree-clone - -''' - -import argparse -import hashlib -import logging -import tarfile -import tempfile -import os -import shutil -import subprocess -import sys -import xml.etree.ElementTree as ET - -from xml.dom import minidom - -sys.path.insert(0, "../cgcs-patch") -from cgcs_patch.patch_signing import sign_files - - -# ostree_repo location -DEPLOY_DIR = os.path.join(os.environ['STX_BUILD_HOME'], 'localdisk/lat/std/deploy') -OSTREE_REPO = os.path.join(DEPLOY_DIR, 'ostree_repo') -# Delta dir used by rsync, hardcoded for now -DELTA_DIR = 'delta_dir' - -detached_signature_file = 'signature.v2' -SOFTWARE_VERSION = '22.06' - -logging.basicConfig( - level=logging.DEBUG, - format='%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', -) - -log = logging.getLogger('make_test_patch') - - -def prepare_env(name='ostree-clone'): - ''' - Generates a copy of the current ostree_repo which is used - to create the delta dir during patch creation - :param name: name of the cloned directory - ''' - log.info('Preparing ostree clone directory') - os.chdir(DEPLOY_DIR) - clone_dir = os.path.join(DEPLOY_DIR, name) - if os.path.isdir(clone_dir): - log.error('Clone directory exists {}'.format(name)) - exit(1) - - os.mkdir(clone_dir) - current_sha = open(os.path.join(OSTREE_REPO, 'refs/heads/starlingx'), 'r').read() - log.info('Current SHA: {}'.format(current_sha)) - log.info('Cloning the directory...') - subprocess.call(['rsync', '-a', OSTREE_REPO + '/', clone_dir]) - - log.info('Prepared ostree repo clone at {}'.format(clone_dir)) - - -def create_delta_dir(delta_dir='delta_dir', clone_dir='ostree-clone', clean_mode=False): - ''' - Creates the ostree delta directory - Contains the changes from the REPO (updated) and the cloned dir (pre update) - :param delta_dir: delta directory name - :param clone_dir: clone dir name - ''' - log.info('Creating ostree delta') - clone_dir = os.path.join(DEPLOY_DIR, clone_dir) - - if os.path.isdir(delta_dir): - if clean_mode: - log.info('Delta dir exists {}, cleaning it'.format(delta_dir)) - shutil.rmtree(delta_dir) - else: - log.error('Delta dir exists {}, clean it up and try again'.format(delta_dir)) - exit(1) - - if not os.path.isdir(clone_dir): - log.error('Clone dir not found') - exit(1) - - subprocess.call(['rsync', '-rpgo', '--compare-dest', clone_dir, OSTREE_REPO + '/', delta_dir + '/']) - log.info('Delta dir created') - - -def add_text_tag_to_xml(parent, - name, - text): - ''' - Utility function for adding a text tag to an XML object - :param parent: Parent element - :param name: Element name - :param text: Text value - :return:The created element - ''' - tag = ET.SubElement(parent, name) - tag.text = text - return tag - - -def gen_xml(patch_id, ostree_content, file_name="metadata.xml"): - ''' - Generate patch metadata XML file - :param file_name: Path to output file - ''' - top = ET.Element("patch") - - add_text_tag_to_xml(top, 'id', patch_id) - add_text_tag_to_xml(top, 'sw_version', SOFTWARE_VERSION) - add_text_tag_to_xml(top, 'summary', 'Summary text') - add_text_tag_to_xml(top, 'description', 'Description text') - add_text_tag_to_xml(top, 'install_instructions', 'Install instructions text') - add_text_tag_to_xml(top, 'warnings', 'Warnings text') - add_text_tag_to_xml(top, 'status', 'DEV') - add_text_tag_to_xml(top, 'unremovable', 'N') - add_text_tag_to_xml(top, 'reboot_required', 'Y') - add_text_tag_to_xml(top, 'apply_active_release_only', '') - add_text_tag_to_xml(top, 'restart_script', 'Patch1_Restart_Script.sh') - - # Parse ostree_content - content = ET.SubElement(top, 'contents') - ostree = ET.SubElement(content, 'ostree') - - add_text_tag_to_xml(ostree, 'number_of_commits', str(len(ostree_content['commits']))) - base_commit = ET.SubElement(ostree, 'base') - add_text_tag_to_xml(base_commit, 'commit', ostree_content['base']['commit']) - add_text_tag_to_xml(base_commit, 'checksum', ostree_content['base']['checksum']) - - for i, c in enumerate(ostree_content['commits']): - commit = ET.SubElement(ostree, 'commit' + str(i + 1)) - add_text_tag_to_xml(commit, 'commit', c['commit']) - add_text_tag_to_xml(commit, 'checksum', c['checksum']) - - add_text_tag_to_xml(top, 'requires', '') - add_text_tag_to_xml(top, 'semantics', '') - - # print - outfile = open(file_name, 'w') - tree = ET.tostring(top) - outfile.write(minidom.parseString(tree).toprettyxml(indent=" ")) - - -def gen_restart_script(file_name): - ''' - Generate restart script - :param file_name: Path to script file - ''' - # print - outfile = open(file_name, 'w') - r = 'echo test restart script' - outfile.write(r) - - -def get_md5(path): - ''' - Utility function for generating the md5sum of a file - :param path: Path to file - ''' - md5 = hashlib.md5() - block_size = 8192 - with open(path, 'rb') as f: - for chunk in iter(lambda: f.read(block_size), b''): - md5.update(chunk) - return int(md5.hexdigest(), 16) - - -def get_commit_checksum(commit_id, repo='ostree_repo'): - ''' - Get commit checksum from a commit id - :param commit_id - :param repo - ''' - # get all checksums - cmd = 'ostree --repo={} log starlingx | grep -i checksum | sed \'s/.* //\''.format(repo) - cksums = subprocess.check_output(cmd, shell=True).decode(sys.stdout.encoding).strip().split('\n') - return(cksums[commit_id]) - - -def get_commits_from_base(base_sha, repo='ostree_repo'): - ''' - Get a list of commits from base sha - :param base_sha - :param repo - ''' - commits_from_base = [] - - cmd = 'ostree --repo={} log starlingx | grep commit | sed \'s/.* //\''.format(repo) - commits = subprocess.check_output(cmd, shell=True).decode(sys.stdout.encoding).strip().split('\n') - - if commits[0] == base_sha: - log.info('base and top commit are the same') - return commits_from_base - - # find base and add the commits to the list - for i, c in enumerate(commits): - if c == base_sha: - break - log.info('saving commit {}'.format(c)) - # find commit checksum - cksum = get_commit_checksum(i, repo) - commits_from_base.append({ - 'commit': c, - 'checksum': cksum - }) - - return commits_from_base - -def create_patch(patch_id, patch_file, repo='ostree_repo', clone_dir='ostree-clone', clean_mode=False): - ''' - Creates a debian patch using ostree delta between 2 repos (rsync) - :param repo: main ostree_repo where build-image adds new commits - :param clone_dir: repo cloned before the changes - ''' - os.chdir(DEPLOY_DIR) - # read the base sha from the clone - base_sha = open(os.path.join(clone_dir, 'refs/heads/starlingx'), 'r').read().strip() - - log.info('Generating delta dir') - create_delta_dir(delta_dir=DELTA_DIR, clone_dir=clone_dir, clean_mode=clean_mode) - - # ostree --repo=ostree_repo show starlingx | grep -i checksum | sed 's/.* //' - cmd = 'ostree --repo={} show starlingx | grep -i checksum | sed \'s/.* //\''.format(clone_dir) - base_checksum = subprocess.check_output(cmd, shell=True).decode(sys.stdout.encoding).strip() - - commits = get_commits_from_base(base_sha, repo) - - if commits: - ostree_content = { - 'base': { - 'commit': base_sha, - 'checksum': base_checksum - }, - } - ostree_content['commits'] = commits - else: - log.info('No changes detected') - exit(0) - - log.info('Generating patch file...') - # Create software.tar, metadata.tar and signatures - # Create a temporary working directory - tmpdir = tempfile.mkdtemp(prefix='patch_') - # Change to the tmpdir - os.chdir(tmpdir) - tar = tarfile.open('software.tar', 'w') - tar.add(os.path.join(DEPLOY_DIR, DELTA_DIR), arcname='') - tar.close - - log.info('Generating xml with ostree content {}'.format(commits)) - gen_xml(patch_id, ostree_content) - tar = tarfile.open('metadata.tar', 'w') - tar.add('metadata.xml') - tar.close() - - log.info('Saving restart scripts (if any)') - # TODO: verify how to handle the restart script - gen_restart_script('Patch1_Restart_Script.sh') - - filelist = ['metadata.tar', 'software.tar'] - # Generate the signature file - sig = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - for f in filelist: - sig ^= get_md5(f) - - sigfile = open('signature', 'w') - sigfile.write('%x' % sig) - sigfile.close() - - # this comes from patch_functions write_patch - # Generate the detached signature - # - # Note: if cert_type requests a formal signature, but the signing key - # is not found, we'll instead sign with the 'dev' key and - # need_resign_with_formal is set to True. - need_resign_with_formal = sign_files( - filelist, - detached_signature_file, - cert_type=None) - - # Create the patch - tar = tarfile.open(os.path.join(DEPLOY_DIR, patch_file), 'w:gz') - for f in filelist: - tar.add(f) - tar.add('signature') - tar.add(detached_signature_file) - tar.add('Patch1_Restart_Script.sh') - tar.close() - - os.chdir(DEPLOY_DIR) - shutil.rmtree(tmpdir) - - log.info('Patch file created {} at {}'.format(patch_file, DEPLOY_DIR)) - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Debian make_test_patch helper") - - parser.add_argument('-r', '--repo', type=str, - help='Ostree repo name', - default=None, required=True) - parser.add_argument('-p', '--prepare', action='store_true', - help='Prepare the ostree_repo clone directory, should be executed before making changes to the environment') - parser.add_argument('-cr', '--clone-repo', type=str, - help='Clone repo directory name', - default=None, required=True) - parser.add_argument('-c', '--create', action='store_true', - help='Create patch, should be executed after changes are done to the environment') - parser.add_argument('-i', '--id', type=str, - help='Patch ID', default='PATCH_0001') - parser.add_argument('-cl', '--clean-mode', action='store_true', - help='Whether to clean the delta directory automatically') - - args = parser.parse_args() - - log.info('STX_BUILD_HOME: {}'.format(os.environ['STX_BUILD_HOME'])) - log.info('DEPLOY DIR: {}'.format(DEPLOY_DIR)) - log.info('DELTA DIR: {}'.format(DELTA_DIR)) - - patch_id = args.id - patch_file = patch_id + '.patch' - - if args.prepare: - log.info('Calling prepare environment') - prepare_env(args.clone_repo) - elif args.create: - log.info('Calling create patch') - create_patch(patch_id, patch_file, args.repo, args.clone_repo, args.clean_mode) -