def _check_params(self, params): params.cmakebuild_repo = self._check_git_url(params.cmakebuild_repo) if params.top_dir: if not os.path.exists(params.top_dir): raise InvalidInputParameterError("Git workspace {} does not exist.".format(params.top_dir)) if not os.path.exists(os.path.join(params.top_dir, '.git')): raise InvalidInputParameterError("Workspace {} does not seem to be a Git workspace.".format(params.top_dir)) return params
def _is_workspace_clean(self, top_dir=None): if top_dir: initial_work_dir = os.getcwd() os.chdir(top_dir) else: initial_work_dir = None top_dir = os.getcwd() git_argv = [self._git_executable, 'status', '-b', '--porcelain'] retv = subprocess.check_output(git_argv, universal_newlines=True) retv = retv.lstrip().rstrip() status_lines = retv.splitlines() if status_lines[0].startswith('## HEAD (no branch)'): raise InvalidInputParameterError("Git workspace {} has detached HEAD, not upgradable.".format(top_dir)) if len(status_lines) > 1: raise InvalidInputParameterError("Git workspace {} is not clean, please check.".format(top_dir)) if initial_work_dir: os.chdir(initial_work_dir) return True
def _check_git_url(self, git_url): vcs_url = vcsutil.VcsUrl(git_url) proto = vcs_url.get_protocol() if proto in ['ssh', 'https']: # Normalize a remote Git URL to end with .git even if specified without the extension. res_path = vcs_url.get_resource_path() if not res_path.endswith('.git'): vcs_url.set_resource_path("{}.git".format(res_path)) else: raise InvalidInputParameterError("Git URL {0} is not supported yet.".format(git_url)) # Normalize all URLs. git_url = str(vcs_url) self._logger.debug("returning url={0}".format(git_url)) return git_url
def _get_current_cmakebuild_version(self, top_dir): assert os.path.exists(top_dir) cmakebuild_top_dir = os.path.join(top_dir, 'CMakeBuild') if not os.path.exists(cmakebuild_top_dir): return None re_version_dir = re.compile(r'^\d+[0-9.]+-\d+$') version_list = [] for fname in os.listdir(cmakebuild_top_dir): if os.path.isdir(os.path.join(cmakebuild_top_dir, fname)): if re_version_dir.match(fname) and os.path.exists(os.path.join(cmakebuild_top_dir, fname, 'CMakeBuild', 'bin', 'cmake.py')): version_list.append(ver.version_tuple_from_str(fname)) if not version_list: return None if len(version_list) > 1: raise InvalidInputParameterError("Workspace {} contains multiple CMakeBuild versions, please update manually.".format(top_dir)) self._logger.debug("found CMakeBuild {} in {}".format(ver.version_tuple_to_str(version_list[0]), top_dir)) return version_list[0]
def cmakebuild_update(self, params): initial_work_dir = os.getcwd() # (Re)create GitHelper in case the log level has been changed. self._git_helper = vcsutil.GitHelper() params = self._check_params(params) if params.top_dir is None: params.top_dir = util.get_top_dir() self._summary_lines = [] if params.update_prepare: print("{}: preparing CMakeBuild update ...".format(self._prog_name)) cmakebuild_version_current = self._get_current_cmakebuild_version(params.top_dir) if cmakebuild_version_current is None: print("{}: no existing CMakeBuild version found.".format(params.top_dir)) if not self._is_workspace_clean(params.top_dir): return if params.cmakebuild_tag is None: cmakebuild_tag = self._git_helper.get_latest_cmakebuild_tag(params.cmakebuild_repo) if cmakebuild_version_current and (ver.version_compare(cmakebuild_version_current, ver.version_tuple_from_str(cmakebuild_tag)) == 0): print("{}: CMakeBuild is up to date, nothing to be done.".format(params.top_dir)) return else: # Validate CMakeBuild tag cmakebuild_tags = self._git_helper.get_remote_tags(params.cmakebuild_repo) if params.cmakebuild_tag not in cmakebuild_tags: raise InvalidInputParameterError("requested tag {0} does not exists in {1}.".format(params.cmakebuild_tag, params.cmakebuild_repo)) cmakebuild_tag = params.cmakebuild_tag if cmakebuild_version_current and (ver.version_compare(ver.version_tuple_from_str(cmakebuild_tag), cmakebuild_version_current) <= 0): print("{}: CMakeBuild is up to date, nothing to be done.".format(params.top_dir)) return install_dir = os.path.join(params.top_dir, 'build', 'cmakebuild_update') self._install_self(install_dir) update_script = os.path.join(install_dir, self._prog_name) # Prepare execv argument vector to call self with different arguments using the current python executable. if self._sys_info.is_windows(): child_args = [self._sys_info.get_short_path(self._sys_info.get_python_executable())] else: child_args = [self._sys_info.get_python_executable()] child_args.extend([update_script, '--update']) if cmakebuild_tag: child_args.extend(['-t', cmakebuild_tag]) if params.cmakebuild_repo: child_args.extend(['--cmakebuild-repo', params.cmakebuild_repo]) # Add currrent log option to child_args[] to propagate the current log option to the child process. log_level = self._logger.getEffectiveLevel() log_level_str = None if log_level == logging.DEBUG: log_level_str = 'debug' elif log_level == logging.INFO: log_level_str = 'info' elif log_level == logging.WARNING: log_level_str = 'warning' elif log_level == logging.ERROR: log_level_str = 'error' elif log_level == logging.CRITICAL: log_level_str = 'critical' if log_level_str is not None: child_args.append('--log={}'.format(log_level_str)) child_args.append(params.top_dir) os.chdir(params.top_dir) if self._sys_info.is_windows(): # Unfortunately, there are issues with os.execv() on Windows and therefore a subprocess call is used instead. util.subproc_check_call_flushed(child_args) else: # execv() is preferred as the child is likely to remove python files just being executed # by the current python process. os.execv(child_args[0], child_args) else: try: print("{}: updating CMakeBuild in {} to {}".format(self._prog_name, params.top_dir, params.cmakebuild_tag)) os.chdir(params.top_dir) if not self._is_workspace_clean(): return self._append_item_to_summary("Git workspace:", params.top_dir) if self._list_summary: cmakebuild_version_current = self._get_current_cmakebuild_version(params.top_dir) if cmakebuild_version_current is not None: self._append_item_to_summary("Current CMakeBuild version:", "{}-{:d}".format(ver.version_tuple_to_str(cmakebuild_version_current[:3]), cmakebuild_version_current[-1])) self._append_item_to_summary("New CMakeBuild version:", params.cmakebuild_tag) # Inventory of CMakeBuild to remember existing directories to be removed later on. (git_cmakebuild_dirs, cmakebuild_dirs) = self._get_git_cmakebuild_dirs(params.top_dir) if params.cmakebuild_tag in git_cmakebuild_dirs: git_cmakebuild_dirs.remove(params.cmakebuild_tag) if params.cmakebuild_tag in cmakebuild_dirs: cmakebuild_dirs.remove(params.cmakebuild_tag) # print("found existing Git CMakeBuild subdirs:", git_cmakebuild_dirs) # print("found existing CMakeBuild subdirs:", cmakebuild_dirs) # Add new CMakeBuild subtree self._add_cmakebuild_to_git_repo(params.cmakebuild_tag, params.cmakebuild_repo) # Update .svnimportprops in case is does exist. svnimportprops_file = os.path.join(params.top_dir, '.svnimportprops') svnimportprops_modified = self._update_svnimportprops(svnimportprops_file, params.cmakebuild_tag) for dname in git_cmakebuild_dirs: git_argv = [self._git_executable, 'rm', '-r', os.path.join('CMakeBuild', dname)] util.subproc_check_call_flushed(git_argv) if svnimportprops_modified or git_cmakebuild_dirs: # Need a git commit if '.svnimportprops' has been updated or git rm -r has been launched. git_comment = [] if git_cmakebuild_dirs: git_comment.append("rm -r CMakeBuild/{}".format(','.join(git_cmakebuild_dirs))) if svnimportprops_modified: git_comment.append("modifying {}".format('.svnimportprops')) git_argv = [self._git_executable, 'commit', '-am', '{}: {}'.format(self._prog_name, ', '.join(git_comment))] util.subproc_check_call_flushed(git_argv) # Check again to get rid of any python cache files cmakebuild_dirs.extend(git_cmakebuild_dirs) for dname in cmakebuild_dirs: dname_path = os.path.join(params.top_dir, 'CMakeBuild', dname) if os.path.exists(dname_path): util.rmtree(dname_path) print("{}: finished updating CMakeBuild in {} to {}".format(self._prog_name, params.top_dir, params.cmakebuild_tag)) if self._list_summary: print("\n{0:^80}".format("Summary")) print("{0:^80}".format("=======")) for line in self._summary_lines: print(line) finally: pass os.chdir(initial_work_dir)
def _check_params(self, params): assert params.rst_module_filenm is not None if not os.path.exists(params.rst_module_filenm): raise InvalidInputParameterError( "CMake doc module file {} does not exist.".format( params.rst_module_filenm))
def add_extension_modules(self, rst_module_filenm, extension_module_names, section_title="Extension Modules", output_rst_filenm=None): if not os.path.exists(rst_module_filenm): raise InvalidInputParameterError( "CMake RST module file {} does not exist.".format( rst_module_filenm)) if output_rst_filenm is None: # in-place replacement output_rst_filenm = rst_module_filenm # Empty sections are not permitted, use one of the remove_xxx() methods to get rid of a section. assert extension_module_names self._detect_cmake_source_tree(rst_module_filenm) self._check_section_title(section_title) (module_file_header, section_list) = self._parse_rst_module_file(rst_module_filenm) if len(section_list) > 0: # CMake's original module file has one or more sections. All extension sections are inserted in front of # section titled "All Modules" or "Standard Modules". The latter title is used after the first extension section has been inserted. # Get cmake module names cmake_module_names_set = self._get_cmake_module_names(section_list) # Extension module names must not replace existing cmake module names extension_module_names_set = set(extension_module_names) if not cmake_module_names_set.isdisjoint( extension_module_names_set): conflicting_names = cmake_module_names_set.intersection( extension_module_names_set) msg = "CMake builtin module names cannot be part of an extension section.\n" msg += "Please check the extension module names: " + " ".join( conflicting_names) raise Exception(msg) else: # Looks like a corrupted cmake-modules.7.rst assert False # Get a list of RST extension module wrapper files belonging to section "section_title". existing_extension_module_names = self._get_extension_module_names( section_list, section_title) if existing_extension_module_names: self._logger.debug('existing extensions: %s', ' '.join(existing_extension_module_names)) modified = self._update_section(section_list, section_title, extension_module_names) if modified: # print("new content lines:") # self._dump_section_list(section_list[0:-1]) # Change title of the CMake module section from "All Modules" to "Standard Modules". for section in section_list: if section.section_title == self._section_title_cmake_modules_orig: section.section_title = self._section_title_cmake_modules section.section_title_marker_line = '{0:=>{width}}'.format( self._section_title_marker, width=len(section.section_title)) break section_list = self._sort_section_list(section_list) # Save top-level RST module file self._save_rst_module_file(output_rst_filenm, module_file_header, section_list) # Remove RST extension module wrapper files not belonging to this section anymore. outdated_extension_module_names = [] for mod_nm in existing_extension_module_names: if mod_nm not in extension_module_names: outdated_extension_module_names.append(mod_nm) if outdated_extension_module_names: self._logger.debug('outdated extensions: %s', ' '.join(outdated_extension_module_names)) # Remove outdated RST extension module wrapper files. self._remove_rst_extension_module_files( outdated_extension_module_names)
def _check_section_title(self, section_title): if section_title in self._reserved_section_titles: raise InvalidInputParameterError( "section {} is protected and cannot be modified, please contact technical support." .format(section_title))