1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# 5# Copyright (c) 2020 Huawei Device Co., Ltd. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19import os 20 21from hb_internal.common.utils import OHOSException 22from hb_internal.common.utils import exec_command 23from hb_internal.common.utils import read_yaml_file 24from hb_internal.common.config import Config 25 26 27class Patch(): 28 """Patch class for hb_internal.build --patch parameter 29 Install the patch based on the configuration file. 30 """ 31 def __init__(self): 32 self.config = Config() 33 # Patch configuration file path 34 self.patch_cfg = os.path.join(self.config.product_path, 'patch.yml') 35 36 def patch_make(self, cmd_args=None, reverse=False): 37 """Patch installation entry function 38 39 Args: 40 reverse (bool, optional): True if the patch is rolled back, 41 else False. Defaults to False. 42 43 Raises: 44 OHOSException: if configuration file does not exist. 45 """ 46 patch_cfg = self.config.patch_cache 47 # Check whether the rollback is in progress 48 if not reverse: 49 # Try to update patch cache and check whether rollback is required 50 self.patch_cache_update() 51 patch_cfg = self.patch_cfg 52 53 if not os.path.isfile(patch_cfg): 54 raise OHOSException(f'{patch_cfg} not found, ' 55 'which "--patch" parameter needs') 56 57 patch_cfg_dict = read_yaml_file(patch_cfg) 58 for src_path, patch_list in patch_cfg_dict.items(): 59 self.patch_apply(src_path, patch_list, reverse) 60 61 def patch_apply(self, src_path, patch_list, reverse=False): 62 """Run the patch installation command. 63 64 Args: 65 src_path (string): Path to which the patch needs to be installed 66 patch_list (list): List of paths for storing patches 67 reverse (bool, optional): True if the patch is rolled back, 68 else False. Defaults to False. 69 70 Raises: 71 OHOSException: src_path or patch_path is invalid, 72 or the command fails to be executed. 73 """ 74 src_path = os.path.join(self.config.root_path, src_path) 75 if not os.path.exists(src_path): 76 raise OHOSException(f'{src_path} not exist, stop applying patch') 77 78 cmd = '' 79 for patch in patch_list: 80 patch_path = os.path.join(self.config.root_path, patch) 81 if not os.path.isfile(patch_path): 82 patch_path = os.path.join(self.config.root_path, 83 src_path, patch) 84 if not os.path.isfile(patch_path): 85 raise OHOSException(f'patch {patch} not exist for ' 86 f'{src_path}, stop applying patch') 87 if reverse: 88 cmd = f'patch -p1 -R < {patch_path}' 89 else: 90 cmd = f'patch -p1 < {patch_path}' 91 try: 92 exec_command(cmd, log_path=self.config.log_path, 93 cwd=src_path, shell=True) 94 except OHOSException as ohos_exception: 95 # Failed to roll back the patch, clear patch cache 96 self.config.patch_cache = None 97 raise ohos_exception 98 99 def patch_cache_update(self): 100 """Try to update patch cache and Check whether rollback is required 101 If patch_cache is None, no rollback is required, 102 otherwise roll back patch. 103 """ 104 # patch_cache stores the configuration file of the last patch. 105 if self.config.patch_cache is not None: 106 self.patch_make(reverse=True) 107 # Update patch cache to current path configuration file path 108 self.config.patch_cache = self.patch_cfg 109 110 111if __name__ == "__main__": 112 patch = Patch() 113 patch.patch_make() 114