Skip to content

Commit 1d897ae

Browse files
authored
htmlreport: support remote GitHub/GitLab links for source files (danmar#7988)
Motivation: Cppcheck-htmlreport previously generated local annotated HTML for all source files. For private or large repositories, generating local HTML is unnecessary and cumbersome. It consumes additional disk space, increases report generation time, and duplicates functionality already provided by GitHub/GitLab browseable HTML pages. This patch allows the cppcheck report itself to be public, while the actual source code remains protected on GitHub/GitLab using their standard access controls. Changes: - Detect --source-dir URLs pointing to GitHub/GitLab. - Use remote URLs in index.html instead of generating local HTML for those files. - Line numbers link directly to GitHub/GitLab with proper anchors (#L123). - Remote links open in a new tab (target="_blank"), preserving local HTML behavior for normal files. Signed-off-by: Robin Getz <[email protected]>
1 parent 2fee3b4 commit 1d897ae

File tree

3 files changed

+91
-10
lines changed

3 files changed

+91
-10
lines changed

htmlreport/cppcheck-htmlreport

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,20 @@ def tr_str(td_th, line, id, cwe, severity, classification, guideline, message, t
494494
if classification:
495495
items.extend([classification, guideline])
496496
if htmlfile:
497-
ret += '<%s><a href="%s#line-%d">%d</a></%s>' % (td_th, htmlfile, line, line, td_th)
497+
if htmlfile.startswith("http://") or htmlfile.startswith("https://"):
498+
# GitHub/GitLab style line anchor
499+
href = f"{htmlfile.rstrip('#L1')}#L{line}"
500+
# Emit **line number with link**
501+
ret += f'<{td_th}><a href="{href}" target="_blank" rel="noopener noreferrer">{line}</a></{td_th}>'
502+
else:
503+
# local HTML annotated
504+
href = f"{htmlfile}#line-{line}"
505+
# Emit **line number with link**
506+
ret += f'<{td_th}><a href="{href}">{line}</a></{td_th}>'
507+
508+
# Emit id, cwe, severity, classification, ...
498509
for item in items:
499-
ret += '<%s>%s</%s>' % (td_th, item, td_th)
510+
ret += f'<{td_th}>{item}</{td_th}>'
500511
else:
501512
items.insert(0,line)
502513
for item in items:
@@ -675,7 +686,9 @@ def main() -> None:
675686
'written.')
676687
parser.add_argument('--source-dir', dest='source_dir',
677688
help='Base directory where source code files can be '
678-
'found.')
689+
'found, or a URL to a remote GitHub/GitLab '
690+
'repository including a branch, e.g. '
691+
'--source-dir=https://github.com/<username>/<repo>/blob/<branch>/')
679692
parser.add_argument('--add-author-information', dest='add_author_information',
680693
help='Blame information to include. '
681694
'Adds specified author information. '
@@ -705,6 +718,10 @@ def main() -> None:
705718
if options.source_dir:
706719
source_dir = options.source_dir
707720

721+
is_remote = False
722+
if source_dir.startswith("http://") or source_dir.startswith("https://"):
723+
is_remote = True
724+
708725
add_author_information = []
709726
if options.add_author_information:
710727
fields = [x.strip() for x in options.add_author_information.split(',')]
@@ -753,9 +770,14 @@ def main() -> None:
753770
for error in contentHandler.errors:
754771
filename = error['file']
755772
if filename not in files:
756-
files[filename] = {
757-
'errors': [], 'htmlfile': str(file_no) + '.html'}
758-
file_no = file_no + 1
773+
if is_remote:
774+
# Construct remote URL for GitHub/GitLab
775+
# tr_str() will use the actual line number, so we can just start with line 1
776+
remote_url = source_dir.rstrip('/') + '/' + filename + '#L1'
777+
files[filename] = {'errors': [], 'htmlfile': remote_url}
778+
else:
779+
files[filename] = {'errors': [], 'htmlfile': str(file_no) + '.html'}
780+
file_no += 1
759781
files[filename]['errors'].append(error)
760782

761783
# Make sure that the report directory is created if it doesn't exist.
@@ -795,6 +817,11 @@ def main() -> None:
795817
if filename == '':
796818
continue
797819

820+
if is_remote:
821+
# Remote source: do NOT generate local annotated HTML files.
822+
# The index will still point directly to GitHub/GitLab URLs.
823+
continue
824+
798825
source_filename = os.path.join(source_dir, filename)
799826
try:
800827
with io.open(source_filename, 'r', encoding=options.source_encoding) as input_file:

man/manual-premium.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,14 +1158,41 @@ The output screen says:
11581158
Default is reading from stdin.
11591159
--report-dir=REPORT_DIR
11601160
The directory where the html report content is written.
1161-
--source-dir=SOURCE_DIR
1162-
Base directory where source code files can be found.
1161+
--source-dir=SOURCE_DIR|URL
1162+
Base directory where source code files can be found, or
1163+
a URL to a remote GitHub/GitLab repository including a
1164+
branch, e.g.:
1165+
--source-dir=https://github.com/<username>/<repo>/blob/<branch>/
11631166

11641167
Example usage:
11651168

11661169
cppcheck gui/test.cpp --xml 2> err.xml
11671170
cppcheck-htmlreport --file=err.xml --report-dir=test1 --source-dir=.
11681171

1172+
or
1173+
cppcheck gui/test.cpp --xml 2> err.xml
1174+
cppcheck-htmlreport --file=err.xml --report-dir=test1 \
1175+
--source-dir=https://github.com/<username>/<repo>/blob/<branch>/
1176+
1177+
## Choosing Between Local Annotated HTML and Remote Repository Links
1178+
1179+
cppcheck-htmlreport supports two modes for linking to source files:
1180+
- Local annotated HTML files (default when `--source-dir` is a filesystem path)
1181+
- Remote GitHub/GitLab links (when `--source-dir` is a URL)
1182+
1183+
Pointing `--source-dir` to a filesystem path generates local annotated HTML files.
1184+
This is useful when you need a fully self-contained report that works offline,
1185+
includes inline annotations, and is ideal for small or medium projects where
1186+
generation is fast.
1187+
Using a remote GitHub/GitLab URL avoids generating per-file HTML and keeps the
1188+
summary report lightweight and fast to produce. This mode is ideal when the
1189+
source is already hosted online and local duplication is unnecessary.
1190+
Remote mode is especially helpful when the HTML report may be public or widely
1191+
distributed but the source code should remain private, since access control is
1192+
handled by the hosting service.
1193+
In general, local mode fits air-gapped environments, while remote mode works
1194+
best for CI workflows and large or private repositories.
1195+
11691196
# Check Level
11701197

11711198
## Reduced

man/manual.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,14 +1198,41 @@ The output screen says:
11981198
Default is reading from stdin.
11991199
--report-dir=REPORT_DIR
12001200
The directory where the html report content is written.
1201-
--source-dir=SOURCE_DIR
1202-
Base directory where source code files can be found.
1201+
--source-dir=SOURCE_DIR|URL
1202+
Base directory where source code files can be found, or
1203+
a URL to a remote GitHub/GitLab repository including a
1204+
branch, e.g.:
1205+
--source-dir=https://github.com/<username>/<repo>/blob/<branch>/
12031206

12041207
Example usage:
12051208

12061209
cppcheck gui/test.cpp --xml 2> err.xml
12071210
cppcheck-htmlreport --file=err.xml --report-dir=test1 --source-dir=.
12081211

1212+
or
1213+
cppcheck gui/test.cpp --xml 2> err.xml
1214+
cppcheck-htmlreport --file=err.xml --report-dir=test1 \
1215+
--source-dir=https://github.com/<username>/<repo>/blob/<branch>/
1216+
1217+
## Choosing Between Local Annotated HTML and Remote Repository Links
1218+
1219+
cppcheck-htmlreport supports two modes for linking to source files:
1220+
- Local annotated HTML files (default when `--source-dir` is a filesystem path)
1221+
- Remote GitHub/GitLab links (when `--source-dir` is a URL)
1222+
1223+
Pointing `--source-dir` to a filesystem path generates local annotated HTML files.
1224+
This is useful when you need a fully self-contained report that works offline,
1225+
includes inline annotations, and is ideal for small or medium projects where
1226+
generation is fast.
1227+
Using a remote GitHub/GitLab URL avoids generating per-file HTML and keeps the
1228+
summary report lightweight and fast to produce. This mode is ideal when the
1229+
source is already hosted online and local duplication is unnecessary.
1230+
Remote mode is especially helpful when the HTML report may be public or widely
1231+
distributed but the source code should remain private, since access control is
1232+
handled by the hosting service.
1233+
In general, local mode fits air-gapped environments, while remote mode works
1234+
best for CI workflows and large or private repositories.
1235+
12091236
# Check Level
12101237

12111238
## Reduced

0 commit comments

Comments
 (0)