| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /*************************************** | ||
| 2 | Auteur : Pierre Aubert | ||
| 3 | Mail : pierre.aubert@lapp.in2p3.fr | ||
| 4 | Licence : LGPL-3.0-only | ||
| 5 | ****************************************/ | ||
| 6 | |||
| 7 | |||
| 8 | #include <fstream> | ||
| 9 | #include <set> | ||
| 10 | |||
| 11 | #include "directory_replace_placeholder.h" | ||
| 12 | |||
| 13 | ///Extensions of binary/image assets that must never go through text placeholder substitution : | ||
| 14 | ///it is meaningless on such content (no XXXPlaceholderXXX token to substitute), unsafe (PPath::saveFileContent | ||
| 15 | ///writes through a NUL-terminated C string, so binary content gets truncated at the first embedded '\0'), | ||
| 16 | ///and prohibitively slow on large files (PString concatenation is not amortised, so replace() on a | ||
| 17 | ///multi-megabyte blob is effectively quadratic). | ||
| 18 | /** @param file : file to be checked | ||
| 19 | * @return true if the file extension is a known binary/image asset | ||
| 20 | */ | ||
| 21 | 8 | bool directory_replace_isBinaryAsset(const PPath & file){ | |
| 22 | static const std::set<PString> setBinaryExtension{ | ||
| 23 | //images | ||
| 24 | "png", "jpg", "jpeg", "gif", "bmp", "ico", "svg", "webp", "tiff", "tif", | ||
| 25 | //fonts | ||
| 26 | "woff", "woff2", "ttf", "otf", "eot", | ||
| 27 | //archives | ||
| 28 | "zip", "gz", "tar", "7z", "bz2", "xz", | ||
| 29 | //documents | ||
| 30 | "pdf", | ||
| 31 | //audio/video | ||
| 32 | "mp3", "mp4", "wav", "ogg", "avi", "mov", | ||
| 33 | //compiled/binary artefacts | ||
| 34 | "so", "dll", "dylib", "a", "o", "exe", "class", "pyc" | ||
| 35 |
9/18✓ Branch 0 (2→3) taken 1 times.
✓ Branch 1 (2→19) taken 7 times.
✓ Branch 2 (4→5) taken 1 times.
✗ Branch 3 (4→19) not taken.
✓ Branch 4 (6→7) taken 36 times.
✓ Branch 6 (8→6) taken 36 times.
✓ Branch 7 (8→9) taken 1 times.
✓ Branch 8 (11→12) taken 1 times.
✓ Branch 10 (16→17) taken 36 times.
✓ Branch 11 (16→18) taken 1 times.
✗ Branch 12 (33→34) not taken.
✗ Branch 13 (33→35) not taken.
✗ Branch 14 (36→37) not taken.
✗ Branch 15 (36→40) not taken.
✗ Branch 16 (38→39) not taken.
✗ Branch 17 (38→40) not taken.
✗ Branch 18 (42→43) not taken.
✗ Branch 19 (42→44) not taken.
|
82 | }; |
| 36 |
3/3✓ Branch 0 (19→20) taken 8 times.
✓ Branch 2 (20→21) taken 8 times.
✓ Branch 4 (21→22) taken 8 times.
|
8 | return setBinaryExtension.find(file.getExtension().toLower()) != setBinaryExtension.end(); |
| 37 | } | ||
| 38 | |||
| 39 | ///Copy a file byte for byte, with no text processing of any kind (safe for binary content) | ||
| 40 | /** @param inputFile : source file | ||
| 41 | * @param outputFile : destination file | ||
| 42 | * @return true on success, false otherwise | ||
| 43 | */ | ||
| 44 | ✗ | bool directory_replace_copyBinaryFile(const PPath & inputFile, const PPath & outputFile){ | |
| 45 | ✗ | std::ifstream in(inputFile.c_str(), std::ios::binary); | |
| 46 | ✗ | if(!in.is_open()){return false;} | |
| 47 | ✗ | std::ofstream out(outputFile.c_str(), std::ios::binary); | |
| 48 | ✗ | if(!out.is_open()){return false;} | |
| 49 | ✗ | out << in.rdbuf(); | |
| 50 | ✗ | return static_cast<bool>(out); | |
| 51 | ✗ | } | |
| 52 | |||
| 53 | ///Replace placeholder in a directory and its content by respect to the given map of value for all place holder (file only) | ||
| 54 | /** @param outputDir : output directory | ||
| 55 | * @param inputConfigDir : input configuration directory | ||
| 56 | * @param mapReplacePlaceholder : map of placeholders and values to be replaced with | ||
| 57 | * @return true on success, false otherwise | ||
| 58 | */ | ||
| 59 | 7 | bool directory_replace_placeholderFile(const PPath & outputDir, const PPath & inputConfigDir, const PMapString & mapReplacePlaceholder){ | |
| 60 | 7 | bool b(true); | |
| 61 |
1/1✓ Branch 0 (2→3) taken 7 times.
|
7 | PVecPath vecFileInputDir = inputConfigDir.getAllFileInDir(); |
| 62 |
2/2✓ Branch 0 (48→4) taken 8 times.
✓ Branch 1 (48→49) taken 7 times.
|
30 | for(PVecPath::iterator it(vecFileInputDir.begin()); it != vecFileInputDir.end(); ++it){ |
| 63 |
2/2✓ Branch 0 (6→7) taken 8 times.
✓ Branch 2 (7→8) taken 8 times.
|
16 | PPath relativeFile = it->replace(mapReplacePlaceholder); |
| 64 |
1/1✓ Branch 0 (11→12) taken 8 times.
|
16 | PPath fullFile = inputConfigDir / *it; |
| 65 |
1/1✓ Branch 0 (12→13) taken 8 times.
|
8 | PPath outputFile = outputDir / relativeFile; |
| 66 |
2/3✓ Branch 0 (13→14) taken 8 times.
✗ Branch 2 (14→15) not taken.
✓ Branch 3 (14→17) taken 8 times.
|
8 | if(directory_replace_isBinaryAsset(fullFile)){ |
| 67 | //Binary/image assets are copied verbatim, the file name/path may still use placeholders, but the content must not be touched | ||
| 68 | ✗ | b &= directory_replace_copyBinaryFile(fullFile, outputFile); | |
| 69 | ✗ | continue; | |
| 70 | } | ||
| 71 |
1/1✓ Branch 0 (17→18) taken 8 times.
|
8 | PString fileContent = fullFile.loadFileContent(); |
| 72 | //TODO : this could be optimised with the dico_replace_var algorithm, but this is enough for now | ||
| 73 |
1/1✓ Branch 0 (18→19) taken 8 times.
|
8 | PString replacedContent = fileContent.replace(mapReplacePlaceholder); |
| 74 |
1/1✓ Branch 0 (19→20) taken 8 times.
|
8 | b &= outputFile.saveFileContent(replacedContent); |
| 75 |
3/6✓ Branch 0 (24→25) taken 8 times.
✗ Branch 1 (24→26) not taken.
✓ Branch 2 (29→30) taken 8 times.
✗ Branch 3 (29→31) not taken.
✓ Branch 4 (34→35) taken 8 times.
✗ Branch 5 (34→37) not taken.
|
24 | } |
| 76 | 7 | return b; | |
| 77 | 7 | } | |
| 78 | |||
| 79 | ///Replace placeholder in a directory and its content by respect to the given map of value for all place holder | ||
| 80 | /** @param outputDir : output directory | ||
| 81 | * @param inputConfigDir : input configuration directory | ||
| 82 | * @param mapReplacePlaceholder : map of placeholders and values to be replaced with | ||
| 83 | * @return true on success, false otherwise | ||
| 84 | */ | ||
| 85 | 4 | bool directory_replace_placeholder(const PPath & outputDir, const PPath & inputConfigDir, const PMapString & mapReplacePlaceholder){ | |
| 86 |
2/3✓ Branch 0 (2→3) taken 4 times.
✗ Branch 2 (3→4) not taken.
✓ Branch 3 (3→9) taken 4 times.
|
4 | if(!outputDir.createDirectory()){ |
| 87 | ✗ | std::cerr << "directory_replace_placeholder : cannot create dir '"<<outputDir<<"'" << std::endl; | |
| 88 | ✗ | return false; | |
| 89 | } | ||
| 90 | //Let's get content of inputConfigDir | ||
| 91 |
1/1✓ Branch 0 (9→10) taken 4 times.
|
4 | PVecPath vecDirInputDir = inputConfigDir.getAllDirectoryInDir(); |
| 92 | 4 | bool b(true); | |
| 93 |
2/2✓ Branch 0 (36→11) taken 3 times.
✓ Branch 1 (36→37) taken 4 times.
|
14 | for(PVecPath::iterator itDir(vecDirInputDir.begin()); itDir != vecDirInputDir.end(); ++itDir){ |
| 94 |
2/2✓ Branch 0 (13→14) taken 3 times.
✓ Branch 2 (14→15) taken 3 times.
|
6 | PPath relativeDir = itDir->replace(mapReplacePlaceholder); |
| 95 |
1/1✓ Branch 0 (18→19) taken 3 times.
|
6 | PPath fullInputDir = inputConfigDir / *itDir; |
| 96 |
1/1✓ Branch 0 (19→20) taken 3 times.
|
3 | PPath fullOutputDir = outputDir / relativeDir; |
| 97 |
1/1✓ Branch 0 (20→21) taken 3 times.
|
3 | b &= fullOutputDir.createDirectory(); |
| 98 | |||
| 99 |
1/1✓ Branch 0 (21→22) taken 3 times.
|
3 | b &= directory_replace_placeholderFile(fullOutputDir, fullInputDir, mapReplacePlaceholder); |
| 100 |
1/1✓ Branch 0 (22→23) taken 3 times.
|
3 | b &= directory_replace_placeholder(fullOutputDir, fullInputDir, mapReplacePlaceholder); |
| 101 | 3 | } | |
| 102 |
1/1✓ Branch 0 (37→38) taken 4 times.
|
4 | b &= directory_replace_placeholderFile(outputDir, inputConfigDir, mapReplacePlaceholder); |
| 103 |
1/2✗ Branch 0 (38→39) not taken.
✓ Branch 1 (38→50) taken 4 times.
|
4 | if(!b){ |
| 104 | ✗ | std::cerr << "directory_replace_placeholder : cannot create output directories architecture" << std::endl; | |
| 105 | ✗ | std::cerr << "\tinputConfigDir = '"<<inputConfigDir<<"'" << std::endl; | |
| 106 | ✗ | std::cerr << "\toutputDir = '"<<outputDir<<"'" << std::endl; | |
| 107 | ✗ | return false; | |
| 108 | } | ||
| 109 | 4 | return b; | |
| 110 | 4 | } | |
| 111 |