resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmFilePathChecksum.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmFilePathChecksum.h"
4
5 #include <vector>
6
7 #include "cmBase32.h"
8 #include "cmCryptoHash.h"
9 #include "cmMakefile.h"
10 #include "cmSystemTools.h"
11
12 cmFilePathChecksum::cmFilePathChecksum() = default;
13
14 cmFilePathChecksum::cmFilePathChecksum(std::string const& currentSrcDir,
15                                        std::string const& currentBinDir,
16                                        std::string const& projectSrcDir,
17                                        std::string const& projectBinDir)
18 {
19   this->setupParentDirs(currentSrcDir, currentBinDir, projectSrcDir,
20                         projectBinDir);
21 }
22
23 cmFilePathChecksum::cmFilePathChecksum(cmMakefile* makefile)
24 {
25   this->setupParentDirs(makefile->GetCurrentSourceDirectory(),
26                         makefile->GetCurrentBinaryDirectory(),
27                         makefile->GetHomeDirectory(),
28                         makefile->GetHomeOutputDirectory());
29 }
30
31 void cmFilePathChecksum::setupParentDirs(std::string const& currentSrcDir,
32                                          std::string const& currentBinDir,
33                                          std::string const& projectSrcDir,
34                                          std::string const& projectBinDir)
35 {
36   this->parentDirs[0].first = cmSystemTools::GetRealPath(currentSrcDir);
37   this->parentDirs[1].first = cmSystemTools::GetRealPath(currentBinDir);
38   this->parentDirs[2].first = cmSystemTools::GetRealPath(projectSrcDir);
39   this->parentDirs[3].first = cmSystemTools::GetRealPath(projectBinDir);
40
41   this->parentDirs[0].second = "CurrentSource";
42   this->parentDirs[1].second = "CurrentBinary";
43   this->parentDirs[2].second = "ProjectSource";
44   this->parentDirs[3].second = "ProjectBinary";
45 }
46
47 std::string cmFilePathChecksum::get(std::string const& filePath) const
48 {
49   std::string relPath;
50   std::string relSeed;
51   {
52     std::string const fileReal = cmSystemTools::GetRealPath(filePath);
53     std::string parentDir;
54     // Find closest project parent directory
55     for (auto const& pDir : this->parentDirs) {
56       if (!pDir.first.empty() &&
57           cmsys::SystemTools::IsSubDirectory(fileReal, pDir.first)) {
58         parentDir = pDir.first;
59         relSeed = pDir.second;
60         break;
61       }
62     }
63     // Use file system root as fallback parent directory
64     if (parentDir.empty()) {
65       relSeed = "FileSystemRoot";
66       cmsys::SystemTools::SplitPathRootComponent(fileReal, &parentDir);
67     }
68     // Calculate relative path from project parent directory
69     relPath = cmsys::SystemTools::RelativePath(
70       parentDir, cmsys::SystemTools::GetParentDirectory(fileReal));
71   }
72
73   // Calculate the file ( seed + relative path ) binary checksum
74   std::vector<unsigned char> hashBytes =
75     cmCryptoHash(cmCryptoHash::AlgoSHA256).ByteHashString(relSeed + relPath);
76
77   // Convert binary checksum to string
78   return cmBase32Encoder().encodeString(hashBytes.data(), hashBytes.size(),
79                                         false);
80 }
81
82 std::string cmFilePathChecksum::getPart(std::string const& filePath,
83                                         size_t length) const
84 {
85   return this->get(filePath).substr(0, length);
86 }