예제 #1
0
 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
예제 #2
0
 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
예제 #3
0
 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
예제 #4
0
 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]
예제 #5
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)
예제 #6
0
 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))
예제 #7
0
    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)
예제 #8
0
 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))