cmFilePathUuid.cxx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2016 Sebastian Holtermann ([email protected])
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmFilePathUuid.h"
  11. #include "cmBase32.h"
  12. #include "cmCryptoHash.h"
  13. #include "cmMakefile.h"
  14. #include "cmSystemTools.h"
  15. #include <vector>
  16. cmFilePathUuid::cmFilePathUuid(cmMakefile* makefile)
  17. {
  18. initParentDirs(makefile->GetCurrentSourceDirectory(),
  19. makefile->GetCurrentBinaryDirectory(),
  20. makefile->GetHomeDirectory(),
  21. makefile->GetHomeOutputDirectory());
  22. }
  23. cmFilePathUuid::cmFilePathUuid(const std::string& currentSrcDir,
  24. const std::string& currentBinDir,
  25. const std::string& projectSrcDir,
  26. const std::string& projectBinDir)
  27. {
  28. initParentDirs(currentSrcDir, currentBinDir, projectSrcDir, projectBinDir);
  29. }
  30. void cmFilePathUuid::initParentDirs(const std::string& currentSrcDir,
  31. const std::string& currentBinDir,
  32. const std::string& projectSrcDir,
  33. const std::string& projectBinDir)
  34. {
  35. parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
  36. parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
  37. parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
  38. parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir);
  39. parentDirs[0].second = "CurrentSource";
  40. parentDirs[1].second = "CurrentBinary";
  41. parentDirs[2].second = "ProjectSource";
  42. parentDirs[3].second = "ProjectBinary";
  43. }
  44. std::string cmFilePathUuid::get(const std::string& filePath,
  45. const char* outputPrefix,
  46. const char* outputSuffix)
  47. {
  48. std::string sourceFilename = cmsys::SystemTools::GetFilenameName(filePath);
  49. std::string sourceBasename =
  50. cmsys::SystemTools::GetFilenameWithoutLastExtension(sourceFilename);
  51. // Acquire checksum string
  52. std::string checksum;
  53. {
  54. std::string sourceRelPath;
  55. std::string sourceRelSeed;
  56. GetRelPathSeed(filePath, sourceRelPath, sourceRelSeed);
  57. checksum = GetChecksumString(sourceFilename, sourceRelPath, sourceRelSeed);
  58. }
  59. // Compose the file name
  60. std::string uuid;
  61. if (outputPrefix) {
  62. uuid += outputPrefix;
  63. }
  64. uuid += sourceBasename.substr(0, partLengthName);
  65. uuid += "_";
  66. uuid += checksum.substr(0, partLengthCheckSum);
  67. if (outputSuffix) {
  68. uuid += outputSuffix;
  69. }
  70. return uuid;
  71. }
  72. void cmFilePathUuid::GetRelPathSeed(const std::string& filePath,
  73. std::string& sourceRelPath,
  74. std::string& sourceRelSeed)
  75. {
  76. const std::string sourceNameReal = cmsys::SystemTools::GetRealPath(filePath);
  77. std::string parentDirectory;
  78. // Find closest project parent directory
  79. for (size_t ii = 0; ii != numParentDirs; ++ii) {
  80. const std::string& pDir = parentDirs[ii].first;
  81. if (!pDir.empty() &&
  82. cmsys::SystemTools::IsSubDirectory(sourceNameReal, pDir)) {
  83. sourceRelSeed = parentDirs[ii].second;
  84. parentDirectory = pDir;
  85. break;
  86. }
  87. }
  88. // Check if the file path is below a known project directory
  89. if (parentDirectory.empty()) {
  90. // Use file syste root as fallback parent directory
  91. sourceRelSeed = "FileSystemRoot";
  92. cmsys::SystemTools::SplitPathRootComponent(sourceNameReal,
  93. &parentDirectory);
  94. }
  95. sourceRelPath = cmsys::SystemTools::RelativePath(
  96. parentDirectory, cmsys::SystemTools::GetParentDirectory(sourceNameReal));
  97. }
  98. std::string cmFilePathUuid::GetChecksumString(
  99. const std::string& sourceFilename, const std::string& sourceRelPath,
  100. const std::string& sourceRelSeed)
  101. {
  102. std::string checksumBase32;
  103. {
  104. // Calculate the file ( seed + relative path + name ) checksum
  105. std::vector<unsigned char> hashBytes =
  106. cmCryptoHash::New("SHA256")->ByteHashString(
  107. (sourceRelSeed + sourceRelPath + sourceFilename).c_str());
  108. checksumBase32 =
  109. cmBase32Encoder().encodeString(&hashBytes[0], hashBytes.size(), false);
  110. }
  111. return checksumBase32;
  112. }