From e7c196831519330a98b02455b6f86f2e322927f8 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Mon, 26 Nov 2012 10:13:40 +0100 Subject: Don't assume gcc was run in same directory as source gcov needs to be run in the same directory as gcc was run in order to find the source files correctly. We use gcov with --no-output to report which directory this is for given gcno files. --- git-coverage | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/git-coverage b/git-coverage index 1e5889b..f9c22f1 100755 --- a/git-coverage +++ b/git-coverage @@ -223,7 +223,8 @@ class GccCoverage: def __init__(self, skips): self._gcno_cache = [] - self._creating_re = re.compile(".*'(.+\.gcov)'.*") + self._creating_re = re.compile("^.*'(.+\.gcov)'$") + self._file_re = re.compile("^File.*'(.+)'$") self._skips = skips def visit(paths, dirname, names): @@ -252,20 +253,41 @@ class GccCoverage: matches.append(gcno) return matches + def _find_directory_gcno_compiled_in(self, gcno, filename): + cmd = ['gcov', '--preserve-paths', '--relative-only', '--no-output'] + for line in subprocess_lines(cmd + gcno): + match = self._file_re.match(line.strip()) + if not match: + continue + expected = match.group(1) + if filename.endswith(expected): + extra = filename[:-len(expected)] + if os.path.exists(extra): + return extra + elif expected.endswith(filename): + extra = expected[:-len(filename)] + up = "../" * len(extra.strip(os.sep).split(os.sep)) + if os.path.exists(up): + return up + return None + def _gcov_lines_for_files(self, filename): gcno = self._match_gcno_files(filename) if not gcno: return - # gcov wants to be in the directory with the source files - # so we make all the gcno paths absolute and change to that - # directory - absgcno = [os.path.abspath(path) for path in gcno] - (directory, base) = os.path.split(filename) - oldpwd = os.getcwd() + # gcov wants to be in the directory that gcc was executed + # from. We don't know which directory that is. So we run + # gcov once to figure out the file path it thinks the source + # is at. + + directory = self._find_directory_gcno_compiled_in(absgcno, filename) + + oldcwd = None if directory: + oldcwd = os.getcwd() os.chdir(directory) # We scrape the output of the command for the names of the @@ -274,7 +296,7 @@ class GccCoverage: cmd = ['gcov', '--preserve-paths', '--relative-only'] for line in subprocess_lines(cmd + absgcno): - match = self._creating_re.match(line) + match = self._creating_re.match(line.strip()) if not match: continue gcov = match.group(1) @@ -284,7 +306,8 @@ class GccCoverage: # Because we change the directory, we have to take care not # to yield while the current directory is changed - os.chdir(oldpwd) + if oldcwd: + os.chdir(oldcwd) for gcov in gcovs: with open(gcov, 'r') as f: -- cgit v1.2.3