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