class PrecommitClient:
    """Client for precommit analysis"""
    def __init__(self,
                 teamscale_config,
                 repository_path,
                 analyzed_file=None,
                 verify=True):
        """Constructor"""
        self.repository_path = repository_path
        self.teamscale_client = TeamscaleClient(teamscale_config.url,
                                                teamscale_config.username,
                                                teamscale_config.access_token,
                                                teamscale_config.project_id,
                                                verify)
        self.analyzed_file = analyzed_file

    def upload_precommit_data(self, changed_files, deleted_files):
        """Uploads the currently changed files for precommit analysis."""
        current_branch = get_current_branch(self.repository_path)
        self.teamscale_client.branch = current_branch
        parent_commit_timestamp = get_current_timestamp(self.repository_path)

        print("Uploading changes on branch '%s' in '%s'..." %
              (current_branch, self.repository_path))
        precommit_data = PreCommitUploadData(
            uniformPathToContentMap=changed_files,
            deletedUniformPaths=deleted_files)
        self.teamscale_client.upload_files_for_precommit_analysis(
            datetime.datetime.fromtimestamp(int(parent_commit_timestamp)),
            precommit_data)

    def wait_and_get_precommit_result(self):
        """Gets the current precommit results. Waits synchronously until server is ready. """
        return self.teamscale_client.get_precommit_analysis_results()

    def print_precommit_results_as_error_string(
            self, include_findings_in_changed_code=True):
        """Print the current precommit results formatting them in a way, most text editors understand.

        Returns:
            `True`, if RED findings were among the new findings. `False`, otherwise.
        """
        added_findings, removed_findings, findings_in_changed_code = self.wait_and_get_precommit_result(
        )

        print('New findings:')
        for formatted_finding in self._format_findings(added_findings):
            print(formatted_finding)

        if include_findings_in_changed_code:
            print('')
            print('Findings in changed code:')
            for formatted_finding in self._format_findings(
                    findings_in_changed_code):
                print(formatted_finding)

        red_added_findings = list(
            filter(lambda finding: finding.assessment == "RED",
                   added_findings))
        return len(red_added_findings) > 0

    def print_other_findings_as_error_string(self, include_all_findings=True):
        """Print existing findings for the current file or the whole repo in a way, most text editors understand. """
        uniform_path = os.path.relpath(self.analyzed_file,
                                       self.repository_path)
        if include_all_findings:
            uniform_path = ''

        existing_findings = self.teamscale_client.get_findings(
            uniform_path=uniform_path,
            timestamp=datetime.datetime.fromtimestamp(
                int(get_current_timestamp(self.repository_path))))

        print('')
        print('Existing findings:')
        for formatted_finding in self._format_findings(existing_findings):
            print(formatted_finding)

    def _format_findings(self, findings):
        """Formats the given findings as error or warning strings."""
        if len(findings) == 0:
            return ['> No findings.']
        sorted_findings = sorted(findings)
        return [
            os.path.join(self.repository_path, finding.uniformPath) + ':' +
            str(finding.startLine) + ':0: ' +
            self._severity_string(finding=finding) + ': ' + finding.message
            for finding in sorted_findings
        ]

    def _severity_string(self, finding):
        """Formats the given finding's assessment as severity."""
        return 'error' if finding.assessment == 'RED' else 'warning'
Beispiel #2
0
class PrecommitClient:
    """Client for precommit analysis"""

    def __init__(self, teamscale_config, repository_path, analyzed_file=None, verify=True):
        """Constructor"""
        self.repository_path = repository_path
        self.teamscale_client = TeamscaleClient(teamscale_config.url, teamscale_config.username,
                                                teamscale_config.access_token, teamscale_config.project_id,
                                                verify)
        self.analyzed_file = analyzed_file

    def upload_precommit_data(self, changed_files, deleted_files):
        """Uploads the currently changed files for precommit analysis."""
        current_branch = get_current_branch(self.repository_path)
        self.teamscale_client.branch = current_branch
        parent_commit_timestamp = get_current_timestamp(self.repository_path)

        print("Uploading changes on branch '%s' in '%s'..." % (current_branch, self.repository_path))
        precommit_data = PreCommitUploadData(uniformPathToContentMap=changed_files, deletedUniformPaths=deleted_files)
        self.teamscale_client.upload_files_for_precommit_analysis(
            datetime.datetime.fromtimestamp(int(parent_commit_timestamp)), precommit_data)

    def wait_and_get_precommit_result(self):
        """Gets the current precommit results. Waits synchronously until server is ready. """
        return self.teamscale_client.get_precommit_analysis_results()

    def print_precommit_results_as_error_string(self, include_findings_in_changed_code=True):
        """Print the current precommit results formatting them in a way, most text editors understand.

        Returns:
            `True`, if RED findings were among the new findings. `False`, otherwise.
        """
        added_findings, removed_findings, findings_in_changed_code = self.wait_and_get_precommit_result()

        print('New findings:')
        for formatted_finding in self._format_findings(added_findings):
            print(formatted_finding)

        if include_findings_in_changed_code:
            print('')
            print('Findings in changed code:')
            for formatted_finding in self._format_findings(findings_in_changed_code):
                print(formatted_finding)

        red_added_findings = list(filter(lambda finding: finding.assessment == "RED", added_findings))
        return len(red_added_findings) > 0

    def print_other_findings_as_error_string(self, include_all_findings=True):
        """Print existing findings for the current file or the whole repo in a way, most text editors understand. """
        uniform_path = os.path.relpath(self.analyzed_file, self.repository_path)
        if include_all_findings:
            uniform_path = ''

        existing_findings = self.teamscale_client.get_findings(
            uniform_path=uniform_path,
            timestamp=datetime.datetime.fromtimestamp(int(get_current_timestamp(self.repository_path))))

        print('')
        print('Existing findings:')
        for formatted_finding in self._format_findings(existing_findings):
            print(formatted_finding)

    def _format_findings(self, findings):
        """Formats the given findings as error or warning strings."""
        if len(findings) == 0:
            return ['> No findings.']
        sorted_findings = sorted(findings)
        return [os.path.join(self.repository_path, finding.uniformPath) + ':' + str(finding.startLine) + ':0: ' +
                self._severity_string(finding=finding) + ': ' + finding.message for finding in sorted_findings]

    def _severity_string(self, finding):
        """Formats the given finding's assessment as severity."""
        return 'error' if finding.assessment == 'RED' else 'warning'