1 /** 2 This tool coverts D code coverage files from absolute to relative paths. 3 4 D code coverage files are written using absolute path names if absolute paths are 5 used in the build command. (This enables running coverage tests from a directory 6 other than the original build directory.) This tool converts the files to relative 7 paths. This includes the file name and the name included in the file. 8 9 Copyright (c) 2017, eBay Software Foundation 10 Initially written by Jon Degenhardt 11 12 License: Boost Licence 1.0 (http://boost.org/LICENSE_1_0.txt) 13 14 **/ 15 module codecov_to_relative_path; 16 17 import std.algorithm : findSplit; 18 import std.array : appender; 19 import std.conv : to; 20 import std.file : exists, isDir, isFile, remove, rename; 21 import std.path : absolutePath, baseName, buildPath, buildNormalizedPath, dirName, extension, 22 isAbsolute, stripExtension; 23 import std.range : empty; 24 import std.stdio; 25 import std..string : tr; 26 27 int main(string[] cmdArgs) 28 { 29 auto programName = (cmdArgs.length > 0) ? cmdArgs[0].stripExtension.baseName : "Unknown_program_name"; 30 31 if (cmdArgs.length < 2) 32 { 33 writefln("Synopsis: %s coverage-file [coverage-file...]", programName); 34 return 1; 35 } 36 37 auto coverageFiles = cmdArgs[1..$]; 38 39 foreach (cf; coverageFiles) 40 { 41 if (!cf.exists || !cf.isFile) 42 { 43 writefln("%s is not a file", cf); 44 return 1; 45 } 46 } 47 48 foreach (cf; coverageFiles) 49 { 50 auto rootDir = cf.absolutePath.buildNormalizedPath.dirName; 51 auto fileName = cf.baseName; 52 auto fileNameNoExt = fileName.stripExtension; 53 auto lines = appender!(string[])(); 54 foreach (l; cf.File.byLine) lines ~= l.to!string; 55 if (lines.data.length > 0) 56 { 57 /* Check that the last line matches our file name. */ 58 auto lastLine = lines.data[$ - 1]; 59 auto lastLineSplit = lastLine.findSplit(" "); 60 auto lastLinePath = lastLineSplit[1].empty ? "" : lastLineSplit[0]; 61 auto lastLinePathNoExt = lastLinePath.stripExtension; 62 if (lastLinePath.isAbsolute && 63 lastLinePathNoExt.tr("\\/", "--") == fileNameNoExt && 64 rootDir.length + 1 <= lastLine.length && 65 rootDir.length + 1 <= fileName.length) 66 { 67 auto updatedLastLine = lastLine[rootDir.length + 1 .. $]; 68 auto newFileName = fileName[rootDir.length + 1 .. $]; 69 if (newFileName != fileName) 70 { 71 auto ofile = newFileName.File("w"); 72 foreach (l; lines.data[0 .. $ - 1]) ofile.writeln(l); 73 ofile.writeln(updatedLastLine); 74 fileName.remove; 75 } 76 } 77 } 78 } 79 80 return 0; 81 }