Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[web] Blame view #3398

Merged
merged 1 commit into from
Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/js/codechecker-api-node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codechecker-api",
"version": "6.41.0",
"version": "6.42.0",
"description": "Generated node.js compatible API stubs for CodeChecker server.",
"main": "lib",
"homepage": "https://github.com/Ericsson/codechecker",
Expand Down
Binary file modified web/api/py/codechecker_api/dist/codechecker_api.tar.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/py/codechecker_api/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
with open('README.md', encoding='utf-8', errors="ignore") as f:
long_description = f.read()

api_version = '6.41.0'
api_version = '6.42.0'

setup(
name='codechecker_api',
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/py/codechecker_api_shared/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
with open('README.md', encoding='utf-8', errors="ignore") as f:
long_description = f.read()

api_version = '6.41.0'
api_version = '6.42.0'

setup(
name='codechecker_api_shared',
Expand Down
35 changes: 34 additions & 1 deletion web/api/report_server.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,10 @@ enum CommentKind {
struct SourceFileData {
1: i64 fileId,
2: string filePath,
3: optional string fileContent
3: optional string fileContent,
4: optional bool hasBlameInfo,
5: optional string remoteUrl,
6: optional string trackingBranch,
}

struct SortMode {
Expand Down Expand Up @@ -377,6 +380,31 @@ struct AnalysisInfo {
1: string analyzerCommand,
}

typedef string CommitHash

struct BlameData {
1: i64 startLine,
2: i64 endLine,
3: CommitHash commitHash,
}

struct CommitAuthor {
1: string name,
2: string email,
}

struct Commit {
1: CommitAuthor author,
2: string summary,
3: string message,
4: string committedDateTime,
}

struct BlameInfo {
1: map<CommitHash, Commit> commits,
2: list<BlameData> blame,
}

service codeCheckerDBAccess {

// Gives back all analyzed runs.
Expand Down Expand Up @@ -497,6 +525,11 @@ service codeCheckerDBAccess {
3: Encoding encoding)
throws (1: codechecker_api_shared.RequestFailed requestError),

// Get blame information for a given file.
// PERMISSION: PRODUCT_ACCESS
BlameInfo getBlameInfo(1: i64 fileId)
throws (1: codechecker_api_shared.RequestFailed requestError),

// Get line content information for multiple files in different positions.
// The first key of the map is a file id, the second is a line number:
// (e.g.: lineContent = result[fileId][line])
Expand Down
57 changes: 56 additions & 1 deletion web/client/codechecker_client/cmd/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

import argparse
import base64
from git import Repo
from git.exc import InvalidGitRepositoryError
import hashlib
import json
import os
Expand Down Expand Up @@ -579,6 +581,49 @@ def parse_report_files(report_files: Set[str], zip_iter=map):
missing_source_files)


def get_blame_info(repo: Repo, file_path: str):
""" Get blame info for the given file in the given git repo. """
tracking_branch = None
try:
# If a commit is checked out, accessing the active_branch member will
# throw a type error. In this case we will use the current commit hash.
tracking_branch = str(repo.active_branch.tracking_branch())
except TypeError:
tracking_branch = repo.head.commit.hexsha

try:
blame = repo.blame_incremental(repo.head.commit.hexsha, file_path)

res = {
'version': 'v1',
'tracking_branch': tracking_branch,
'remote_url': next(repo.remote().urls, None),
'commits': {},
'blame': []}

for b in blame:
commit = b.commit

if commit.hexsha not in res['commits']:
res['commits'][commit.hexsha] = {
'author': {
'name': commit.author.name,
'email': commit.author.email,
},
'summary': commit.summary,
'message': commit.message,
'committed_datetime': str(commit.committed_datetime)}

res['blame'].append({
'from': b.linenos[0],
'to': b.linenos[-1],
'commit': commit.hexsha})
return res
except Exception as ex:
LOG.warning("Failed to get blame information for %s: %s",
file_path, ex)


def assemble_zip(inputs, zip_file, client):
"""Collect and compress report and source files, together with files
contanining analysis related information into a zip file which
Expand Down Expand Up @@ -687,6 +732,16 @@ def assemble_zip(inputs, zip_file, client):
except KeyError:
zipf.write(f, file_path)

try:
repo = Repo(f, search_parent_directories=True)
blame_info = get_blame_info(repo, f) if repo else None
if blame_info:
zipf.writestr(
os.path.join('blame', f.lstrip('/')),
json.dumps(blame_info))
except InvalidGitRepositoryError:
pass

zipf.writestr('content_hashes.json', json.dumps(file_to_hash))

# Compressing .zip file
Expand Down Expand Up @@ -887,7 +942,7 @@ def main(args):
except Exception as ex:
print(ex)
import traceback
traceback.print_stack()
traceback.print_exc()
LOG.error("Failed to assemble zip file.")
sys.exit(1)

Expand Down
2 changes: 1 addition & 1 deletion web/codechecker_web/shared/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# The newest supported minor version (value) for each supported major version
# (key) in this particular build.
SUPPORTED_VERSIONS = {
6: 41
6: 42
}

# Used by the client to automatically identify the latest major and minor
Expand Down
20 changes: 20 additions & 0 deletions web/codechecker_web/shared/webserver_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from collections.abc import Mapping
import os
import re
import sys

from codechecker_common import logger
Expand Down Expand Up @@ -65,6 +66,7 @@ def __init__(self):
load_json_or_empty(self.checkers_severity_map_file, {}))
self.__system_comment_map = \
load_json_or_empty(self.system_comment_map_file, {})
self.__git_commit_urls = self.__get_git_commit_urls()
self.__package_version = None
self.__package_build_date = None
self.__package_git_hash = None
Expand All @@ -75,6 +77,15 @@ def __init__(self):

self.__set_version()

def __get_git_commit_urls(self):
""" Get commit urls from the configuration file. """
git_commit_urls = load_json_or_empty(self.git_commit_urls_file, [])

for git_commit_url in git_commit_urls:
git_commit_url["regex"] = re.compile(git_commit_url["regex"])

return git_commit_urls

def __get_package_layout(self):
""" Get package layout configuration. """
layout_cfg_file = os.path.join(
Expand Down Expand Up @@ -147,6 +158,15 @@ def system_comment_map_file(self):
return os.path.join(self._data_files_dir_path, 'config',
'system_comment_kinds.json')

@property
def git_commit_urls_file(self):
return os.path.join(
self._data_files_dir_path, 'config', 'git_commit_urls.json')

@property
def git_commit_urls(self):
return self.__git_commit_urls

@property
def path_plist_to_html_dist(self):
return os.path.join(self._lib_dir_path, 'plist_to_html', 'static')
Expand Down
14 changes: 14 additions & 0 deletions web/config/git_commit_urls.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"regex": "(?P<protocol>(http[s]?)):\/\/(?P<user>\\w+@)?(?P<url>([^\/]*gerrit[^\/]*))/a/(?P<team>\\w+)/(?P<project>\\w+)",
"url": "$protocol://$url/gitweb?p=$team/$project.git;a=commit;h=$commit"
},
{
"regex": "(?P<url>.*bitbucket.*((?=\\.git)|$(?<!\\.git)))",
"url": "$url/commits/$commit"
},
{
"regex": "(?P<url>.*((?=\\.git)|$(?<!\\.git)))",
"url": "$url/commit/$commit"
}
]
1 change: 1 addition & 0 deletions web/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ portalocker==2.2.1
psutil==5.8.0
mypy_extensions==0.4.3
thrift==0.13.0
gitpython==3.1.11

./api/py/codechecker_api/dist/codechecker_api.tar.gz
./api/py/codechecker_api_shared/dist/codechecker_api_shared.tar.gz
1 change: 1 addition & 0 deletions web/requirements_py/dev/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mkdocs==1.1.2
mypy_extensions==0.4.3
coverage==5.5.0
thrift==0.13.0
gitpython==3.1.11

./api/py/codechecker_api/dist/codechecker_api.tar.gz
./api/py/codechecker_api_shared/dist/codechecker_api_shared.tar.gz
Expand Down
Loading