Skip to content

Commit fea35bc

Browse files
committed
Refactor callback implementation to use Perl modules, if available.
The module may be faster than an external callback and enables reuse while providing some additional flexibility. Refactor source layout to move scripts to 'scripts' directory. This makes the layout cleaner and enables a place to put non-public interfaces which have not be opensourced (yet) - without naming them in public Makefiles or elsewhere. Signed-off-by: Henry Cox <[email protected]>
1 parent a292209 commit fea35bc

30 files changed

+1722
-890
lines changed

Makefile

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ FILES := $(wildcard bin/*) $(wildcard man/*) README Makefile \
6363
$(wildcard rpm/*) lcovrc
6464

6565
EXES = lcov genhtml geninfo genpng gendesc
66-
SCRIPTS = p4udiff p4annotate getp4version get_signature gitblame gitdiff \
67-
criteria analyzeInfoFiles spreadsheet.py py2lcov gitversion
66+
# there may be both public and non-public user scripts - so lets not show
67+
# any of their names
68+
SCRIPTS = $(shell ls scripts | grep -v -E '([\#\~]|\.orig|\.bak|\.BAK)' )
6869
LIBS = lcovutil.pm
6970
MANPAGES = man1/lcov.1 man1/genhtml.1 man1/geninfo.1 man1/genpng.1 \
7071
man1/gendesc.1 man5/lcovrc.5
@@ -119,10 +120,11 @@ install:
119120
$(INSTALL) -d -m 755 $(SCRIPT_DIR)
120121
for s in $(SCRIPTS) ; do \
121122
$(call echocmd," INSTALL $(SCRIPT_DIR)/$$s") \
122-
$(INSTALL) -m 755 bin/$$s $(SCRIPT_DIR)/$$s ; \
123+
$(INSTALL) -m 755 scripts/$$s $(SCRIPT_DIR)/$$s ; \
123124
$(FIX) --version $(VERSION) --release $(RELEASE) \
124125
--libdir $(LIB_DIR) --bindir $(BIN_DIR) \
125-
--fixinterp --fixver --fixlibdir --fixbindir \
126+
--fixinterp --fixver --fixlibdir \
127+
--fixscriptdir --scriptdir $(SCRIPT_DIR) \
126128
--exec $(SCRIPT_DIR)/$$s ; \
127129
done
128130
$(INSTALL) -d -m 755 $(LIB_DIR)

bin/fix.pl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,14 @@ ($)
114114
die("$0: Missing option --bindir\n") if (!defined($opt_bindir));
115115

116116
$source =~ s/^use FindBin;\n//mg;
117-
$source =~ s/\$FindBin::RealBin/"$opt_bindir"/mg;
117+
$source =~ s/"\$FindBin::RealBin"/"$opt_bindir"/mg;
118+
}
119+
120+
if ($opt_fixscriptdir) {
121+
die("$0: Missing option --scriptdir\n") if (!defined($opt_scriptdir));
122+
123+
$source =~ s/^use FindBin;\n//mg;
124+
$source =~ s/"\$FindBin::RealBin"/"$opt_scriptdir"/mg;
118125
}
119126

120127
return $source;

bin/genhtml

Lines changed: 62 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ use lcovutil qw (set_tool_name define_errors parse_ignore_errors
104104
$ERROR_DEPRECATED $ERROR_INCONSISTENT_DATA $ERROR_CALLBACK
105105
$ERROR_RANGE $ERROR_PATH
106106
$ERROR_PARALLEL $ERROR_CHILD report_parallel_error
107+
report_exit_status
107108
summarize_messages
108109
$br_coverage $func_coverage
109110
info $verbose init_verbose_flag debug $debug $devnull
@@ -272,6 +273,7 @@ sub gen_png($$$$$@);
272273
package SummaryInfo;
273274

274275
our @coverageCriteriaScript;
276+
our $criteriaCallback;
275277
our %coverageCriteria; # hash of name->(type, success 0/1, string)
276278
our $coverageCriteriaStatus = 0; # set to non-zero if we see any errors
277279
our @criteriaCallbackTypes; # include date, owner bin info
@@ -1059,7 +1061,7 @@ sub checkCoverageCriteria
10591061
my $self = shift;
10601062
my $type = $self->type();
10611063
return
1062-
unless (@coverageCriteriaScript &&
1064+
unless ($criteriaCallback &&
10631065
(0 == scalar(@criteriaCallbackLevels) ||
10641066
grep(/$type/, @criteriaCallbackLevels)));
10651067

@@ -1136,29 +1138,18 @@ sub checkCoverageCriteria
11361138
'\' ' . $self->type() . ' \'' . $json . '\'';
11371139
# command: script name (top|dir|file) jsonString args..
11381140
lcovutil::info(1, "criteria: '$cmd'\n");
1139-
if (open(HANDLE, "-|", @coverageCriteriaScript,
1140-
$self->type() eq 'top' ? 'top' : $self->name(),
1141-
$self->type(), $json
1142-
)) {
1143-
my @msg;
1144-
while (my $line = <HANDLE>) {
1145-
chomp $line;
1146-
$line =~ s/\r//g; # remove CR from line-end
1147-
next if '' eq $line;
1148-
push(@msg, $line);
1149-
}
1150-
close(HANDLE);
1151-
my $status = $? >> 8;
1152-
my $name = $self->type() eq 'top' ? "" : $self->name();
1153-
$coverageCriteria{$name} = [$self->type(), $status, \@msg]
1154-
if (0 != $status ||
1155-
0 != scalar(@msg));
1156-
$coverageCriteriaStatus = $status
1157-
if $status != 0;
1158-
} else {
1159-
lcovutil::ignorable_error($lcovutil::ERROR_CALLBACK,
1160-
"'open(-| $cmd)' failed: \"$!\"");
1161-
}
1141+
my ($status, $msgs) =
1142+
$criteriaCallback->check_criteria(
1143+
$self->type() eq 'top' ? 'top' : $self->name(),
1144+
$self->type(), $json);
1145+
1146+
my $name = $self->type() eq 'top' ? "" : $self->name();
1147+
$coverageCriteria{$name} = [$self->type(), $status, $msgs]
1148+
if (0 != $status ||
1149+
(defined $msgs &&
1150+
0 != scalar(@$msgs)));
1151+
$coverageCriteriaStatus = $status
1152+
if $status != 0;
11621153
my $end = Time::HiRes::gettimeofday();
11631154
$lcovutil::profileData{criteria}{
11641155
$self->type() eq 'top' ? 'top' :
@@ -3567,6 +3558,7 @@ sub text
35673558

35683559
package SourceFile;
35693560
our @annotateScript;
3561+
our $annotateCallback;
35703562
our $annotateTooltip = 'Line %l: commit %C on %d by %F';
35713563
our $annotatedFiles = 0;
35723564
our $totalFiles = 0;
@@ -4310,7 +4302,7 @@ sub _load
43104302
# not exist - but that might be fine if it exists in the repo
43114303
my $repo_path = Cwd::realpath($path);
43124304
if (!defined($repo_path)) {
4313-
if (0 == scalar(@annotateScript) &&
4305+
if (!defined($annotateCallback) &&
43144306
!$main::synthesizeMissingFile) {
43154307
lcovutil::ignorable_error($lcovutil::ERROR_SOURCE,
43164308
"\"" . $self->path() . "\" does not exist: $!" .
@@ -4343,35 +4335,23 @@ sub _load
43434335
$lcovutil::profileData{check_version}{$self->path()} = $end - $start;
43444336
}
43454337

4346-
#stat($annotateScript);
4347-
4348-
ANNOTATE: if (0 != scalar(@annotateScript)) {
4349-
4350-
last ANNOTATE
4351-
if (scalar(@lcovutil::extractVersionScript) ==
4352-
0 && # already checked
4353-
lcovutil::fileExistenceBeforeCallbackError($repo_path));
4354-
4338+
if (defined($annotateCallback) &&
4339+
# also skip if we already emitted 'missing file' error
4340+
(defined($lcovutil::versionCallback) ||
4341+
!lcovutil::fileExistenceBeforeCallbackError($repo_path))
4342+
) {
43554343
my $begin = Time::HiRes::gettimeofday();
43564344
my $lineNum = 0;
4357-
my $cmd = join(' ', @annotateScript) . ' \'' . $repo_path . '\'';
4358-
lcovutil::info(1, "annotate: '$cmd'\n");
4359-
my $found; # check that either all lines are annotated or none are
4360-
local *HANDLE;
4361-
if (open(HANDLE, "-|", @annotateScript, $repo_path)) {
4362-
while (my $line = <HANDLE>) {
4363-
chomp $line;
4364-
$line =~ s/\r//g; # remove CR from line-end
4345+
4346+
my ($status, $lines) = $annotateCallback->annotate($repo_path);
4347+
if (!$status && defined($lines)) {
4348+
my $found; # check that either all lines are annotated or none are
4349+
foreach my $line (@$lines) {
4350+
4351+
my ($text, $abbrev, $full, $when, $commit) = @$line;
43654352
++$lineNum;
43664353

4367-
my ($commit, $owner, $when, $text) = split(/\|/, $line, 4);
43684354
my $age = _computeAge($when, $path);
4369-
# semicolon is not a legal character in email address -
4370-
# so we use that to delimit the 'abbreviated name' and
4371-
# the 'full name' - in case they are different.
4372-
# this is an attempt to be backward-compatible with
4373-
# existing annotation scripts which return only one name
4374-
my ($abbrev, $full) = split(/;/, $owner, 2);
43754355
if ($commit ne 'NONE') {
43764356
die("inconsistent 'annotate' data for '$repo_path': both 'commit' and 'no commit' lines"
43774357
) if (defined($found) && !$found);
@@ -4396,38 +4376,27 @@ sub _load
43964376
SourceLine->new($lineNum, $text, $abbrev, $full,
43974377
$when, $age, $commit);
43984378
}
4399-
close(HANDLE);
4400-
my $status = $? >> 8;
44014379

44024380
my $end = Time::HiRes::gettimeofday();
44034381

44044382
$lcovutil::profileData{annotate}{$self->path()} = $end - $begin;
4405-
if (0 == $status) {
4406-
++$annotatedFiles if $found;
4407-
$self->_synthesize($countdata, 1); # fake annotations too
4408-
return $self;
4409-
}
4383+
4384+
++$annotatedFiles if $found;
4385+
$self->_synthesize($countdata, 1); # fake annotations too
4386+
return $self;
4387+
} else {
44104388

44114389
# non-zero exit status: something bad happened in annotation
44124390
# if we ignore the error - then fall through and just try to load the file
4413-
my $text = ': ' . $self->[LINES]->[0]->text() . '...'
4414-
if @{$self->[LINES]};
4391+
my $text = '';
4392+
$text = ': ' . $lines->[0]->[0] . '...'
4393+
if $lines && @$lines;
44154394
# might be useful to provide more than one line of context - if there is more than one line?
4416-
lcovutil::ignorable_error(
4417-
$lcovutil::ERROR_ANNOTATE_SCRIPT,
4418-
($! ? "annotate command '$cmd' pipe error: $!" :
4419-
"non-zero exit status from annotate '$cmd' pipe"
4420-
) .
4421-
($text ? $text : ''));
4422-
# if falling through, clear the LINES array that might have been
4423-
# populated in the annotate loop. Needs to be empty for bare load
4424-
# or synthesize operation
4425-
$self->[LINES] = [];
4426-
} else {
4427-
# open failed.
4428-
lcovutil::ignorable_error($lcovutil::ERROR_ANNOTATE_SCRIPT,
4429-
"'open(-| $cmd)' failed: \"$!\"\n");
4430-
}
4395+
4396+
lcovutil::report_exit_status($lcovutil::ERROR_ANNOTATE_SCRIPT,
4397+
"annotate command failed",
4398+
$status, '', $text);
4399+
} # end if error
44314400
} # end if annotate script exists
44324401

44334402
# Check if file exists and is readable
@@ -4862,15 +4831,11 @@ sub compute
48624831
if ($consumption > $lcovutil::maxMemory);
48634832
my $child = wait();
48644833
my $childstatus = $?;
4865-
--$currentParallel;
4866-
if (!exists($children->{$child})) {
4867-
# this should not happen..
4868-
lcovutil::ignorable_error($lcovutil::ERROR_PARALLEL,
4869-
"lost track of children: currentSize:$currentSize wait:$child, currentParallel:$currentParallel children:("
4870-
. join(', ', keys(%$children))
4871-
. ")");
4834+
unless (exists($children->{$child})) {
4835+
lcovutil::report_unknown_child($child);
48724836
next WORK;
48734837
}
4838+
--$currentParallel;
48744839
my ($summary, $fullname, $parentData, $now) =
48754840
@{$children->{$child}};
48764841
my ($parentSummary, $parentPerTestData, $parentPath) =
@@ -5076,16 +5041,11 @@ sub compute
50765041
while ($currentParallel != 0) {
50775042
my $child = wait();
50785043
my $childstatus = $?;
5079-
--$currentParallel;
5080-
if (!exists($children->{$child})) {
5081-
# this should not happen..
5082-
lcovutil::ignorable_erro($lcovutil::ERROR_PARALLEL,
5083-
"lost track of children in tail: wait:$child, currentParallel:$currentParallel children:("
5084-
. join(', ', keys(%$children))
5085-
. ")");
5044+
unless (exists($children->{$child})) {
5045+
lcovutil::report_unknown_child($child);
50865046
next;
50875047
}
5088-
5048+
--$currentParallel;
50895049
my ($summary, $fullname, $parentSummary, $parentPath, $now) =
50905050
@{$children->{$child}};
50915051
$self->merge_child($child, $childstatus);
@@ -5210,7 +5170,7 @@ package main;
52105170

52115171
# Global variables & initialization
52125172

5213-
lcovutil::save_cmd_line(\@ARGV, $FindBin::RealBin);
5173+
lcovutil::save_cmd_line(\@ARGV, "$FindBin::RealBin");
52145174

52155175
# TraceFile Instance containing all data from the 'current' .info file
52165176
# - constructed at start of GenHtml
@@ -5436,6 +5396,16 @@ foreach my $rc ([\@datebins, \@rc_date_bins],
54365396
@{$rc->[0]} = @{$rc->[1]} unless (@{$rc->[0]});
54375397
}
54385398

5399+
foreach my $cb ([\$SourceFile::annotateCallback, \@SourceFile::annotateScript],
5400+
[\$SummaryInfo::criteriaCallback,
5401+
\@SummaryInfo::coverageCriteriaScript
5402+
]
5403+
) {
5404+
5405+
${$cb->[0]} = lcovutil::configure_callback(@{$cb->[1]})
5406+
if scalar(@{$cb->[1]});
5407+
}
5408+
54395409
foreach my $data (['criteria_callback_levels', \@criteriaCallbackLevels,
54405410
['top', 'directory', 'file']
54415411
],
@@ -5748,7 +5718,9 @@ if (0 == $exit_status &&
57485718
print(STDERR $msg);
57495719
}
57505720
}
5751-
$exit_status = $SummaryInfo::coverageCriteriaStatus;
5721+
# fail for signal or status
5722+
$exit_status = (($SummaryInfo::coverageCriteriaStatus & 0xFF) |
5723+
($SummaryInfo::coverageCriteriaStatus >> 8));
57525724
}
57535725

57545726
lcovutil::save_profile(File::Spec->catfile($output_directory, 'genhtml'));

bin/geninfo

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ use lcovutil qw (define_errors parse_ignore_errors
9595
parseOptions
9696
@comments
9797
$maxParallelism init_parallel_params $maxMemory
98+
count_totals print_overall_rate
9899
);
99100

100101
if ($^O eq "msys") {
@@ -258,7 +259,7 @@ our $defaultInterval;
258259
our $cwd = getcwd();
259260
chomp($cwd);
260261

261-
lcovutil::save_cmd_line(\@ARGV, $FindBin::RealBin);
262+
lcovutil::save_cmd_line(\@ARGV, "$FindBin::RealBin");
262263

263264
#
264265
# Code entry point
@@ -629,8 +630,11 @@ if (0 == $exit_code) {
629630
my $then = Time::HiRes::gettimeofday();
630631
$lcovutil::profileData{emit} = $then - $now;
631632

632-
lcovutil::info(1, "Processed $processedFiles GCDA files\n");
633633
info("Finished .info-file creation\n");
634+
my @counts = $trace_data->count_totals();
635+
lcovutil::print_overall_rate(\@counts, 1, $lcovutil::func_coverage,
636+
$lcovutil::br_coverage)
637+
if ($lcovutil::verbose >= 0);
634638
summarize_cov_filters();
635639
# print warnings
636640
lcovutil::warn_file_patterns();
@@ -883,6 +887,7 @@ sub _process_one_chunk($$$$)
883887
# "name" will be .gcno if "$initial" else will be $gcda
884888
my $name = defined($gcda_file) ? $gcda_file : $gcno_file;
885889
info(1, "Processing $name%s\n", defined($pid) ? " in child $pid" : "");
890+
my $context = MessageContext->new("capturing from $name");
886891

887892
# multiple gcda files may refer to the same source - so generate the
888893
# same 'source.gcda' output file - so they each need a different directory
@@ -1302,6 +1307,10 @@ sub gen_info(@)
13021307
$lcovutil::maxMemory);
13031308
my $child = wait();
13041309
my $childstatus = $?;
1310+
unless (exists($children{$child})) {
1311+
lcovutil::report_unknown_child($child);
1312+
next;
1313+
}
13051314
_merge_one_child($child, \%children, $type, $tempFileExt,
13061315
$childstatus);
13071316
--$currentParallel;
@@ -1414,6 +1423,7 @@ sub gen_info(@)
14141423
$trace_data =
14151424
_process_one_chunk($chunk, $processedChunks, $trace_data,
14161425
undef);
1426+
$processedFiles += scalar(@$chunk);
14171427
my $then = Time::HiRes::gettimeofday();
14181428
$lcovutil::profileData{process}{$processedChunks} = $then - $now;
14191429
}
@@ -1422,10 +1432,15 @@ sub gen_info(@)
14221432
while ($currentParallel != 0) {
14231433
my $child = wait();
14241434
my $childstatus = $?;
1435+
unless (exists($children{$child})) {
1436+
lcovutil::report_unknown_child($child);
1437+
next;
1438+
}
14251439
--$currentParallel;
14261440
_merge_one_child($child, \%children, $type, $tempFileExt, $childstatus);
14271441
}
1428-
info("Finished GDCA file processing\n");
1442+
info("Finished processing %d GDCA file%s\n",
1443+
$processedFiles, 1 == $processedFiles ? '' : 's');
14291444
# Report whether files were excluded.
14301445
if (%lcovutil::excluded_files) {
14311446
my $count = scalar keys %lcovutil::excluded_files;

0 commit comments

Comments
 (0)