Skip to content

Commit 40f8b2d

Browse files
Ported Build Client Clean to C++
1 parent 472f5a1 commit 40f8b2d

4 files changed

Lines changed: 252 additions & 3 deletions

File tree

Artifacts/build_apidocs_clean.bat

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ cd ..
1818
git log -n 1 --format="%%H" -- "OpenAPI" >"build_apidocs\_githash_apidocs.txt"
1919
git log -n 1 --format="%%H" -- "OpenAPI" >"Artifacts\apidocsdist\_githash_apidocs.txt"
2020

21-
go run BuildScripts\createClientDist.go build_apidocs Artifacts\apidocsdist\apidocspackage.zip
21+
set TOOLBUILDDIR=build_clientdist_tools
22+
if not exist "%TOOLBUILDDIR%" (mkdir "%TOOLBUILDDIR%")
23+
git rev-parse --verify --short HEAD >"%TOOLBUILDDIR%\githash.txt"
24+
git log -n 1 --format="%%H" -- "OpenAPI" >"%TOOLBUILDDIR%\clientdirhash.txt"
25+
cmake -S . -B "%TOOLBUILDDIR%"
26+
cmake --build "%TOOLBUILDDIR%" --target create_client_dist --config Release
27+
"%TOOLBUILDDIR%\DevPackage\Framework\create_client_dist.exe" build_apidocs Artifacts\apidocsdist\apidocspackage.zip
2228

2329
if "%1" neq "NOPAUSE" (
2430
pause

Artifacts/build_client_clean.bat

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,13 @@ cd ..\..\
4242

4343
cd build_client\Client
4444

45-
go run ..\..\BuildScripts\createClientDist.go dist ..\..\Artifacts\clientdist\clientpackage.zip
45+
set TOOLBUILDDIR=..\..\build_clientdist_tools
46+
if not exist "%TOOLBUILDDIR%" (mkdir "%TOOLBUILDDIR%")
47+
git rev-parse --verify --short HEAD >"%TOOLBUILDDIR%\githash.txt"
48+
git log -n 1 --format="%%H" -- "Client" >"%TOOLBUILDDIR%\clientdirhash.txt"
49+
cmake -S ..\.. -B "%TOOLBUILDDIR%"
50+
cmake --build "%TOOLBUILDDIR%" --target create_client_dist --config Release
51+
"%TOOLBUILDDIR%\DevPackage\Framework\create_client_dist.exe" dist ..\..\Artifacts\clientdist\clientpackage.zip
4652

4753
go run ..\..\BuildScripts\createClientSource.go . ..\..\Artifacts\clientdist\clientsourcepackage.zip
4854

Artifacts/build_client_clean.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ cd ../..
3939

4040
cd build_client/Client
4141

42-
go run ../../BuildScripts/createClientDist.go dist ../../Artifacts/clientdist/clientpackage.zip
42+
TOOLBUILDDIR="../../build_clientdist_tools"
43+
mkdir -p "$TOOLBUILDDIR"
44+
git rev-parse --verify --short HEAD > "$TOOLBUILDDIR/githash.txt"
45+
git log -n 1 --format="%H" -- "Client" > "$TOOLBUILDDIR/clientdirhash.txt"
46+
cmake -S ../.. -B "$TOOLBUILDDIR"
47+
cmake --build "$TOOLBUILDDIR" --target create_client_dist --config Release
48+
"$TOOLBUILDDIR/DevPackage/Framework/create_client_dist" dist ../../Artifacts/clientdist/clientpackage.zip
4349

4450
go run ../../BuildScripts/createClientSource.go . ../../Artifacts/clientdist/clientsourcepackage.zip
4551

BuildScripts/createClientDist.cpp

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/*++
2+
3+
Copyright (C) 2024 Autodesk Inc.
4+
5+
All rights reserved.
6+
7+
Redistribution and use in source and binary forms, with or without
8+
modification, are permitted provided that the following conditions are met:
9+
* Redistributions of source code must retain the above copyright
10+
notice, this list of conditions and the following disclaimer.
11+
* Redistributions in binary form must reproduce the above copyright
12+
notice, this list of conditions and the following disclaimer in the
13+
documentation and/or other materials provided with the distribution.
14+
* Neither the name of the Autodesk Inc. nor the
15+
names of its contributors may be used to endorse or promote products
16+
derived from this software without specific prior written permission.
17+
18+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21+
DISCLAIMED. IN NO EVENT SHALL AUTODESK INC. BE LIABLE FOR ANY
22+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28+
29+
*/
30+
31+
32+
#include <string>
33+
#include <iostream>
34+
#include <memory>
35+
#include <exception>
36+
#include <vector>
37+
#include <algorithm>
38+
#include <map>
39+
#include <filesystem>
40+
#include <cctype>
41+
42+
#include "PugiXML/pugixml.hpp"
43+
#include "common_importstream_native.hpp"
44+
#include "common_exportstream_native.hpp"
45+
#include "common_portablezipwriter.hpp"
46+
47+
static void writeUsage()
48+
{
49+
std::cout << "Please start with createClientDist <inputpath> <outputfile>" << std::endl;
50+
}
51+
52+
static std::string toLowerString(const std::string& sValue)
53+
{
54+
std::string sResult = sValue;
55+
std::transform(sResult.begin(), sResult.end(), sResult.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
56+
return sResult;
57+
}
58+
59+
static std::string getContentTypeFromExtension(const std::string& sExtension)
60+
{
61+
if (sExtension.empty())
62+
return "";
63+
64+
std::string sExtLower = toLowerString(sExtension);
65+
static const std::map<std::string, std::string> sExtensionMap = {
66+
{ ".ico", "image/x-icon" },
67+
{ ".woff", "font/woff" },
68+
{ ".woff2", "font/woff2" },
69+
{ ".ttf", "font/ttf" },
70+
{ ".png", "image/png" },
71+
{ ".jpg", "image/jpeg" },
72+
{ ".jpeg", "image/jpeg" },
73+
{ ".gif", "image/gif" },
74+
{ ".bmp", "image/bmp" },
75+
{ ".svg", "image/svg+xml" },
76+
{ ".html", "text/html" },
77+
{ ".htm", "text/html" },
78+
{ ".css", "text/css" },
79+
{ ".js", "application/javascript" },
80+
{ ".json", "application/json" },
81+
{ ".xml", "text/xml" },
82+
{ ".txt", "text/plain" },
83+
{ ".md", "text/markdown" }
84+
};
85+
86+
auto iIter = sExtensionMap.find(sExtLower);
87+
if (iIter != sExtensionMap.end())
88+
return iIter->second;
89+
90+
return "";
91+
}
92+
93+
struct SDistEntry
94+
{
95+
std::string m_sURL;
96+
std::string m_sFileName;
97+
uint64_t m_nSize;
98+
std::string m_sContentType;
99+
std::string m_sSourcePath;
100+
};
101+
102+
class CStringXMLWriter : public pugi::xml_writer
103+
{
104+
private:
105+
std::string m_sBuffer;
106+
public:
107+
void write(const void* data, size_t size) override
108+
{
109+
if (size == 0)
110+
return;
111+
const char* pChar = reinterpret_cast<const char*>(data);
112+
m_sBuffer.append(pChar, pChar + size);
113+
}
114+
115+
const std::string& getBuffer() const
116+
{
117+
return m_sBuffer;
118+
}
119+
};
120+
121+
static void addFileToZip(AMCCommon::CPortableZIPWriter& zipWriter, const std::string& sSourcePath, const std::string& sZipPath)
122+
{
123+
AMCCommon::CImportStream_Native importStream(sSourcePath);
124+
auto pEntryStream = zipWriter.createEntry(sZipPath, 0);
125+
126+
const uint64_t nBufferSize = 1024 * 64;
127+
std::vector<uint8_t> buffer;
128+
buffer.resize(nBufferSize);
129+
130+
uint64_t nTotalSize = importStream.retrieveSize();
131+
uint64_t nRemaining = nTotalSize;
132+
133+
while (nRemaining > 0) {
134+
uint64_t nChunk = std::min<uint64_t>(nRemaining, nBufferSize);
135+
uint64_t nReadBytes = importStream.readBuffer(buffer.data(), nChunk, true);
136+
if (nReadBytes != nChunk)
137+
throw std::runtime_error("could not read full data from " + sSourcePath);
138+
139+
pEntryStream->writeBuffer(buffer.data(), nReadBytes);
140+
nRemaining -= nReadBytes;
141+
}
142+
143+
zipWriter.closeEntry();
144+
}
145+
146+
int main(int argc, char* argv[])
147+
{
148+
try
149+
{
150+
if (argc < 3) {
151+
writeUsage();
152+
return 1;
153+
}
154+
155+
std::filesystem::path inputPath = std::filesystem::path(argv[1]);
156+
std::string sOutputFileName = argv[2];
157+
158+
if (!std::filesystem::exists(inputPath) || !std::filesystem::is_directory(inputPath))
159+
throw std::runtime_error("input directory does not exist: " + inputPath.u8string());
160+
161+
std::vector<SDistEntry> entries;
162+
163+
for (auto const& entry : std::filesystem::recursive_directory_iterator(inputPath)) {
164+
if (!entry.is_regular_file())
165+
continue;
166+
167+
std::string sFileName = entry.path().filename().u8string();
168+
std::string sExtension = entry.path().extension().u8string();
169+
if (toLowerString(sExtension) == ".map")
170+
continue;
171+
172+
std::string sRelativePath = std::filesystem::relative(entry.path(), inputPath).generic_u8string();
173+
std::string sURL = sRelativePath;
174+
if (sURL == "index.html")
175+
sURL = "";
176+
177+
SDistEntry distEntry;
178+
distEntry.m_sURL = sURL;
179+
distEntry.m_sFileName = sFileName;
180+
distEntry.m_nSize = entry.file_size();
181+
distEntry.m_sContentType = getContentTypeFromExtension(sExtension);
182+
distEntry.m_sSourcePath = entry.path().u8string();
183+
184+
std::cout << "Adding " << distEntry.m_sSourcePath << " (" << distEntry.m_nSize << " bytes) as " << distEntry.m_sURL << std::endl;
185+
186+
entries.push_back(distEntry);
187+
}
188+
189+
pugi::xml_document packageDoc;
190+
auto rootNode = packageDoc.append_child("package");
191+
rootNode.append_attribute("xmlns").set_value("http://schemas.autodesk.com/amc/resourcepackage/2020/07");
192+
193+
for (auto& distEntry : entries) {
194+
auto entryNode = rootNode.append_child("entry");
195+
entryNode.append_attribute("name").set_value(distEntry.m_sURL.c_str());
196+
entryNode.append_attribute("filename").set_value(distEntry.m_sFileName.c_str());
197+
entryNode.append_attribute("size").set_value(std::to_string(distEntry.m_nSize).c_str());
198+
entryNode.append_attribute("contenttype").set_value(distEntry.m_sContentType.c_str());
199+
}
200+
201+
CStringXMLWriter xmlWriter;
202+
packageDoc.save(xmlWriter, " ", pugi::format_raw | pugi::format_no_declaration, pugi::encoding_utf8);
203+
std::string packageXMLString = xmlWriter.getBuffer();
204+
205+
AMCCommon::PExportStream pExportStream = std::make_shared<AMCCommon::CExportStream_Native>(sOutputFileName);
206+
AMCCommon::CPortableZIPWriter zipWriter(pExportStream, true);
207+
208+
for (auto& distEntry : entries) {
209+
addFileToZip(zipWriter, distEntry.m_sSourcePath, distEntry.m_sFileName);
210+
}
211+
212+
{
213+
auto pEntryStream = zipWriter.createEntry("package.xml", 0);
214+
pEntryStream->writeBuffer(packageXMLString.c_str(), packageXMLString.length());
215+
zipWriter.closeEntry();
216+
}
217+
218+
zipWriter.writeDirectory();
219+
return 0;
220+
}
221+
catch (std::exception& E)
222+
{
223+
std::cout << "Fatal error: " << E.what() << std::endl;
224+
return -1;
225+
}
226+
catch (...)
227+
{
228+
std::cout << "Unhandled fatal exception!" << std::endl;
229+
return -1;
230+
}
231+
}

0 commit comments

Comments
 (0)