def create_remove_instructions(self): self.have_map = svnTree.SVNTree() have_info_path = var_stack.resolve("$(HAVE_INFO_MAP_PATH)") if not os.path.isfile(have_info_path): have_info_path = var_stack.resolve("$(SITE_HAVE_INFO_MAP_PATH)") self.have_map.read_info_map_from_file(have_info_path, a_format="text") self.batch_accum.set_current_section('remove') self.batch_accum += self.platform_helper.progress("Starting remove") sorted_target_folder_list = sorted(self.installState.install_items_by_target_folder, key=lambda fold: var_stack.resolve(fold), reverse=True) # print(sorted_target_folder_list) self.accumulate_unique_actions('pre_remove', self.installState.full_install_items) for folder_name in sorted_target_folder_list: var_stack.set_var("__TARGET_DIR__").append(os.path.normpath(folder_name)) items_in_folder = self.installState.install_items_by_target_folder[folder_name] logging.info("folder %s", var_stack.resolve(folder_name)) self.batch_accum += self.platform_helper.new_line() self.accumulate_unique_actions('pre_remove_from_folder', items_in_folder) for IID in items_in_folder: with self.install_definitions_index[IID] as installi: for source_var in var_stack.get_configVar_obj("iid_source_var_list"): source = var_stack.resolve_var_to_list(source_var) self.batch_accum += var_stack.resolve_var_to_list_if_exists("iid_action_list_pre_remove_item") self.create_remove_instructions_for_source(folder_name, source) self.batch_accum += var_stack.resolve_var_to_list_if_exists("iid_action_list_post_remove_item") self.batch_accum += self.platform_helper.progress("Remove {installi.name}".format(**locals())) self.accumulate_unique_actions('post_remove_from_folder', items_in_folder) self.accumulate_unique_actions('post_remove', self.installState.full_install_items)
def create_remove_instructions_for_source(self, folder, source): """ source is a tuple (source_folder, tag), where tag is either !file or !dir """ base_, leaf = os.path.split(source[0]) to_remove_path = os.path.normpath(os.path.join(folder, leaf)) remove_actions = var_stack.resolve_var_to_list_if_exists("iid_action_list_remove_item") if len(remove_actions) == 0: if source[1] == '!dir': # remove whole folder remove_action = self.platform_helper.rmdir(to_remove_path, recursive=True) self.batch_accum += remove_action elif source[1] == '!file': # remove single file remove_action = self.platform_helper.rmfile(to_remove_path) self.batch_accum += remove_action elif source[1] == '!dir_cont': # remove all source's files and folders from a folder source_folder_info_map_item = self.have_map.get_item_at_path(source[0]) # avoid removing items that were not installed, # could happen because install dependencies are not always the same as remove dependencies. if source_folder_info_map_item is not None: file_list, folder_list = source_folder_info_map_item.sorted_sub_items() unwtared_file_name_list = self.replace_wtar_names_with_real_names(file_item.name for file_item in file_list) for sub_file_name in unwtared_file_name_list: to_remove_path = os.path.normpath(os.path.join(folder, sub_file_name)) remove_action = self.platform_helper.rm_file_or_dir(to_remove_path) self.batch_accum += remove_action for sub_folder in folder_list: to_remove_path = os.path.normpath(os.path.join(folder, sub_folder.name)) remove_action = self.platform_helper.rmdir(to_remove_path, recursive=True) self.batch_accum += remove_action elif source[1] == '!files': # # remove all source's files from a folder source_folder_info_map_item = self.have_map.get_item_at_path(source[0]) # avoid removing items that were not installed, # could happen because install dependencies are not always the same as remove dependencies. if source_folder_info_map_item is not None: file_list, folder_list = source_folder_info_map_item.sorted_sub_items() unwtared_file_name_list = self.replace_wtar_names_with_real_names(file_item.name for file_item in file_list) for sub_file_name in unwtared_file_name_list: to_remove_path = os.path.normpath(os.path.join(folder, sub_file_name)) remove_action = self.platform_helper.rm_file_or_dir(to_remove_path) self.batch_accum += remove_action else: remove_actions = filter(None, remove_actions) # filter out None values self.batch_accum += remove_actions
def accumulate_unique_actions(self, action_type, iid_list): """ accumulate action_type actions from iid_list, eliminating duplicates""" unique_actions = unique_list() # unique_list will eliminate identical actions while keeping the order for IID in iid_list: with self.install_definitions_index[IID] as installi: action_var_name = "iid_action_list_" + action_type item_actions = var_stack.resolve_var_to_list_if_exists(action_var_name) num_unique_actions = 0 for an_action in item_actions: len_before = len(unique_actions) unique_actions.append(an_action) len_after = len(unique_actions) if len_before < len_after: # add progress only for the first same action num_unique_actions += 1 action_description = self.action_type_to_progress_message[action_type] if num_unique_actions > 1: action_description = " ".join((action_description, str(num_unique_actions))) unique_actions.append( self.platform_helper.progress("{installi.name} {action_description}".format(**locals()))) self.batch_accum += unique_actions logging.info("... %s actions: %d", action_type, len(unique_actions))
def create_copy_instructions(self): self.have_map = svnTree.SVNTree() # read NEW_HAVE_INFO_MAP_PATH and not HAVE_INFO_MAP_PATH. Copy might be called after the sync batch file was created # but before it was executed. HAVE_INFO_MAP_PATH is only created # when the sync batch file is executed. have_info_path = var_stack.resolve("$(NEW_HAVE_INFO_MAP_PATH)") self.have_map.read_info_map_from_file(have_info_path, a_format="text") # copy and actions instructions for sources self.batch_accum.set_current_section('copy') self.batch_accum += self.platform_helper.progress("Starting copy from $(LOCAL_REPO_SYNC_DIR)") sorted_target_folder_list = sorted(self.installState.install_items_by_target_folder, key=lambda fold: var_stack.resolve(fold)) # first create all target folders so to avoid dependency order problems such as creating links between folders if len(sorted_target_folder_list) > 0: self.batch_accum += self.platform_helper.progress("Creating folders...") for folder_name in sorted_target_folder_list: self.batch_accum += self.platform_helper.mkdir_with_owner(folder_name) self.batch_accum += self.platform_helper.progress("Create folders done") self.accumulate_unique_actions('pre_copy', self.installState.full_install_items) if 'Mac' in var_stack.resolve_to_list("$(__CURRENT_OS_NAMES__)") and 'Mac' in var_stack.resolve_to_list("$(TARGET_OS)"): self.pre_copy_mac_handling() for folder_name in sorted_target_folder_list: items_in_folder = self.installState.install_items_by_target_folder[folder_name] logging.info("folder %s", var_stack.resolve(folder_name)) self.batch_accum += self.platform_helper.new_line() self.batch_accum += self.platform_helper.cd(folder_name) # accumulate pre_copy_to_folder actions from all items, eliminating duplicates self.accumulate_unique_actions('pre_copy_to_folder', items_in_folder) batch_accum_len_before = len(self.batch_accum) self.batch_accum += self.platform_helper.copy_tool.begin_copy_folder() for IID in items_in_folder: with self.install_definitions_index[IID] as installi: for source_var in var_stack.get_configVar_obj("iid_source_var_list"): source = var_stack.resolve_var_to_list(source_var) self.batch_accum += var_stack.resolve_var_to_list_if_exists("iid_action_list_pre_copy_item") self.create_copy_instructions_for_source(source) self.batch_accum += var_stack.resolve_var_to_list_if_exists("iid_action_list_post_copy_item") self.batch_accum += self.platform_helper.progress("Copy {installi.name}".format(**locals())) self.batch_accum += self.platform_helper.copy_tool.end_copy_folder() logging.info("... copy actions: %d", len(self.batch_accum) - batch_accum_len_before) self.batch_accum += self.platform_helper.progress("Expanding files...") self.batch_accum += self.platform_helper.unwtar_current_folder(no_artifacts=True) self.batch_accum += self.platform_helper.progress("Expand files done") if 'Mac' in var_stack.resolve_to_list("$(__CURRENT_OS_NAMES__)") and 'Mac' in var_stack.resolve_to_list("$(TARGET_OS)"): self.batch_accum += self.platform_helper.progress("Resolving symlinks...") self.batch_accum += self.platform_helper.resolve_symlink_files() self.batch_accum += self.platform_helper.progress("Resolve symlinks done") # accumulate post_copy_to_folder actions from all items, eliminating duplicates self.accumulate_unique_actions('post_copy_to_folder', items_in_folder) self.batch_accum.indent_level -= 1 # actions instructions for sources that do not need copying, here folder_name is the sync folder for folder_name, items_in_folder in self.installState.no_copy_items_by_sync_folder.iteritems(): self.batch_accum += self.platform_helper.new_line() self.batch_accum += self.platform_helper.cd(folder_name) self.batch_accum.indent_level += 1 # accumulate pre_copy_to_folder actions from all items, eliminating duplicates self.accumulate_unique_actions('pre_copy_to_folder', items_in_folder) for IID in items_in_folder: with self.install_definitions_index[IID]: for source_var in var_stack.resolve_var_to_list_if_exists("iid_source_var_list"): source = var_stack.resolve_var_to_list(source_var) source_folder, source_name = os.path.split(source[0]) to_untar = os.path.join(folder_name, source_name) self.batch_accum += self.platform_helper.unwtar_something(to_untar) self.batch_accum += var_stack.resolve_var_to_list_if_exists("iid_action_list_pre_copy_item") self.batch_accum += var_stack.resolve_var_to_list_if_exists("iid_action_list_post_copy_item") # accumulate post_copy_to_folder actions from all items, eliminating duplicates self.accumulate_unique_actions('post_copy_to_folder', items_in_folder) self.batch_accum += self.platform_helper.progress("{folder_name}".format(**locals())) self.batch_accum.indent_level -= 1 self.accumulate_unique_actions('post_copy', self.installState.full_install_items) self.batch_accum.set_current_section('post-copy') # Copy have_info file to "site" (e.g. /Library/Application support/... or c:\ProgramData\...) # for reference. But when preparing offline installers the site location is the same as the sync location # so copy should be avoided. if var_stack.resolve("$(HAVE_INFO_MAP_PATH)") != var_stack.resolve("$(SITE_HAVE_INFO_MAP_PATH)"): self.batch_accum += self.platform_helper.mkdir_with_owner("$(SITE_REPO_BOOKKEEPING_DIR)") self.batch_accum += self.platform_helper.copy_file_to_file("$(HAVE_INFO_MAP_PATH)", "$(SITE_HAVE_INFO_MAP_PATH)") self.platform_helper.copy_tool.finalize() self.create_require_file_instructions() # messages about orphan iids for iid in self.installState.orphan_install_items: logging.info("Orphan item: %s", iid) self.batch_accum += self.platform_helper.echo("Don't know how to install " + iid) self.batch_accum += self.platform_helper.progress("Done copy")