Skip to content

Commit 236309f

Browse files
authored
Better templates file handling (copying, renaming, replacing content) (#497)
1 parent f05175d commit 236309f

File tree

3 files changed

+131
-38
lines changed

3 files changed

+131
-38
lines changed

commandLine/src/projects/baseProject.h

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
#include "ofAddon.h"
66
#include "ofFileUtils.h"
77
#include "pugixml.hpp"
8-
98
#include <map>
9+
10+
1011
namespace fs = of::filesystem;
1112

1213
class baseProject {
@@ -79,6 +80,9 @@ class baseProject {
7980
bool bMakeRelative = false;
8081

8182

83+
84+
85+
8286
// this shouldn't be called by anyone. call "create(...), save" etc
8387
private:
8488

@@ -100,4 +104,73 @@ class baseProject {
100104
//cached addons - if an addon is requested more than once, avoid loading from disk as it's quite slow
101105
std::unordered_map<std::string,std::unordered_map<std::string, ofAddon>> addonsCache; //indexed by [platform][supplied path]
102106
bool isAddonInCache(const std::string & addonPath, const std::string platform); //is this addon in the mem cache?
107+
108+
static void replaceAll(std::string& str, const std::string& from, const std::string& to) {
109+
if(from.empty())
110+
return;
111+
size_t start_pos = 0;
112+
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
113+
str.replace(start_pos, from.length(), to);
114+
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
115+
}
116+
}
117+
118+
struct copyTemplateFile {
119+
public:
120+
fs::path from;
121+
fs::path to;
122+
std::vector <std::pair <string, string> > findReplaces;
123+
124+
bool run() {
125+
// needed for mingw only. maybe a ifdef here.
126+
if (fs::exists(from)) {
127+
#if defined(__MINGW32__) || defined(__MINGW64__)
128+
if (fs::exists(to)) {
129+
fs::remove(to);
130+
}
131+
#endif
132+
133+
if (findReplaces.size()) {
134+
// Load file, replace contents, write to destination.
135+
136+
std::ifstream fileFrom(from);
137+
std::string contents((std::istreambuf_iterator<char>(fileFrom)), std::istreambuf_iterator<char>());
138+
fileFrom.close();
139+
140+
for (auto & f : findReplaces) {
141+
replaceAll(contents, f.first, f.second);
142+
}
143+
144+
std::ofstream fileTo(to);
145+
try{
146+
fileTo << contents;
147+
}catch(std::exception & e){
148+
std::cout << "Error saving to " << to << " : " << e.what() << std::endl;
149+
return false;
150+
}catch(...){
151+
std::cout << "Error saving to " << to << std::endl;
152+
return false;
153+
}
154+
155+
} else {
156+
// straight copy
157+
try {
158+
fs::copy(from, to, fs::copy_options::overwrite_existing);
159+
}
160+
catch(fs::filesystem_error & e) {
161+
std::cout << "error copying template file " << from << " : " << to << std::endl;
162+
std::cout << e.what() << std::endl;
163+
return false;
164+
}
165+
}
166+
} else {
167+
return false;
168+
}
169+
170+
return true;
171+
// std::cout << "----" << std::endl;
172+
}
173+
};
174+
175+
vector <copyTemplateFile> copyTemplateFiles;
103176
};

commandLine/src/projects/visualStudioProject.cpp

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,46 +8,72 @@ bool visualStudioProject::createProjectFile(){
88
// alert("visualStudioProject::createProjectFile");
99

1010
ensureDllDirectoriesExist();
11+
solution = projectDir / (projectName + ".sln");
1112

12-
solution = projectDir / (projectName + ".sln");
13-
fs::path project { projectDir / (projectName + ".vcxproj") };
14-
fs::path user { projectDir / (projectName + ".vcxproj.user") };
15-
fs::path filters { projectDir / (projectName + ".vcxproj.filters") };
13+
std::pair <string, string> replacements;
14+
if (!fs::equivalent(getOFRoot(), fs::path{ "../../.." })) {
15+
string root { getOFRoot().string() };
16+
string relRootWindows { convertStringToWindowsSeparator(root) + "\\" };
17+
18+
replacements = { "..\\..\\..\\", relRootWindows };
19+
} else {
20+
// cout << "equivalent to default ../../.." << endl;
21+
}
22+
23+
// solution
24+
copyTemplateFiles.push_back({
25+
templatePath / "emptyExample.sln",
26+
projectDir / (projectName + ".sln"),
27+
{
28+
{ "emptyExample", projectName },
29+
replacements
30+
}
31+
});
32+
33+
// project
34+
copyTemplateFiles.push_back({
35+
templatePath / "emptyExample.vcxproj",
36+
projectDir / (projectName + ".vcxproj"),
37+
{
38+
{ "emptyExample", projectName },
39+
replacements
40+
}
1641

17-
fs::copy(templatePath / "emptyExample.vcxproj", project, fs::copy_options::overwrite_existing);
18-
fs::copy(templatePath / "emptyExample.vcxproj.user", user, fs::copy_options::overwrite_existing);
19-
fs::copy(templatePath / "emptyExample.sln", solution, fs::copy_options::overwrite_existing);
20-
fs::copy(templatePath / "emptyExample.vcxproj.filters", filters, fs::copy_options::overwrite_existing);
42+
});
43+
44+
// user
45+
copyTemplateFiles.push_back({
46+
templatePath / "emptyExample.vcxproj.user",
47+
projectDir / (projectName + ".vcxproj.user"),
48+
{{ "emptyExample", projectName }}
49+
50+
});
51+
52+
// filters
53+
copyTemplateFiles.push_back({
54+
templatePath / "emptyExample.vcxproj.filters",
55+
projectDir / (projectName + ".vcxproj.filters")
56+
});
57+
58+
// icon
59+
copyTemplateFiles.push_back({
60+
templatePath / "icon.rc",
61+
projectDir / "icon.rc"
62+
});
63+
64+
for (auto & c : copyTemplateFiles) {
65+
c.run();
66+
}
2167

22-
fs::copy(templatePath / "icon.rc", projectDir / "icon.rc", fs::copy_options::overwrite_existing);
68+
69+
fs::path filters { projectDir / (projectName + ".vcxproj.filters") };
2370

2471
pugi::xml_parse_result result = filterXmlDoc.load_file(filters.c_str());
2572
if (result.status==pugi::status_ok) {
2673
ofLogVerbose() << "loaded filter ";
2774
} else {
2875
ofLogVerbose() << "problem loading filter ";
2976
}
30-
31-
findandreplaceInTexfile(solution, "emptyExample", projectName);
32-
findandreplaceInTexfile(user, "emptyExample", projectName);
33-
findandreplaceInTexfile(project, "emptyExample", projectName);
34-
35-
36-
if (!fs::equivalent(getOFRoot(), fs::path{ "../../.." })) {
37-
string root { getOFRoot().string() };
38-
string relRootWindows { convertStringToWindowsSeparator(root) + "\\" };
39-
40-
// sln has windows paths:
41-
// alert ("replacing root with " + relRootWindows, 36);
42-
findandreplaceInTexfile(solution, "..\\..\\..\\", relRootWindows);
43-
44-
// vcx has unixy paths:
45-
//..\..\..\libs
46-
findandreplaceInTexfile(project, "..\\..\\..\\", relRootWindows);
47-
} else {
48-
// cout << "equivalent to default ../../.." << endl;
49-
}
50-
5177
return true;
5278
}
5379

@@ -205,7 +231,7 @@ void visualStudioProject::addSrc(const fs::path & srcFile, const fs::path & fold
205231
nodeAdded.append_child("Filter").append_child(pugi::node_pcdata).set_value(folder.c_str());*/
206232

207233
} else if (ext == ".storyboard" || ext == ".mm") {
208-
// Do not add files for other platforms
234+
// Do not add files for other platforms
209235
} else{
210236
appendValue(doc, "ClCompile", "Include", srcFileString);
211237

commandLine/src/utils/Utils.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,3 @@ bool ofIsPathInPath(const fs::path & path, const fs::path & base);
113113
Idea: create an object to hold the origin and destination files, with renames where needed
114114
and string substitution, so we can avoid opening and writing multiple times the same file, less ssd wear.
115115
*/
116-
struct fromToReplace {
117-
public:
118-
fs::path from;
119-
fs::path to;
120-
std::vector <std::pair <string, string> > findReplaces;
121-
};

0 commit comments

Comments
 (0)