Skip to content

Better templates file handling (copying, renaming, replacing content) #497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 74 additions & 1 deletion commandLine/src/projects/baseProject.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
#include "ofAddon.h"
#include "ofFileUtils.h"
#include "pugixml.hpp"

#include <map>


namespace fs = of::filesystem;

class baseProject {
Expand Down Expand Up @@ -79,6 +80,9 @@ class baseProject {
bool bMakeRelative = false;





// this shouldn't be called by anyone. call "create(...), save" etc
private:

Expand All @@ -100,4 +104,73 @@ class baseProject {
//cached addons - if an addon is requested more than once, avoid loading from disk as it's quite slow
std::unordered_map<std::string,std::unordered_map<std::string, ofAddon>> addonsCache; //indexed by [platform][supplied path]
bool isAddonInCache(const std::string & addonPath, const std::string platform); //is this addon in the mem cache?

static void replaceAll(std::string& str, const std::string& from, const std::string& to) {
if(from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
}
}

struct copyTemplateFile {
public:
fs::path from;
fs::path to;
std::vector <std::pair <string, string> > findReplaces;

bool run() {
// needed for mingw only. maybe a ifdef here.
if (fs::exists(from)) {
#if defined(__MINGW32__) || defined(__MINGW64__)
if (fs::exists(to)) {
fs::remove(to);
}
#endif

if (findReplaces.size()) {
// Load file, replace contents, write to destination.

std::ifstream fileFrom(from);
std::string contents((std::istreambuf_iterator<char>(fileFrom)), std::istreambuf_iterator<char>());
fileFrom.close();

for (auto & f : findReplaces) {
replaceAll(contents, f.first, f.second);
}

std::ofstream fileTo(to);
try{
fileTo << contents;
}catch(std::exception & e){
std::cout << "Error saving to " << to << " : " << e.what() << std::endl;
return false;
}catch(...){
std::cout << "Error saving to " << to << std::endl;
return false;
}

} else {
// straight copy
try {
fs::copy(from, to, fs::copy_options::overwrite_existing);
}
catch(fs::filesystem_error & e) {
std::cout << "error copying template file " << from << " : " << to << std::endl;
std::cout << e.what() << std::endl;
return false;
}
}
} else {
return false;
}

return true;
// std::cout << "----" << std::endl;
}
};

vector <copyTemplateFile> copyTemplateFiles;
};
88 changes: 57 additions & 31 deletions commandLine/src/projects/visualStudioProject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,72 @@ bool visualStudioProject::createProjectFile(){
// alert("visualStudioProject::createProjectFile");

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

solution = projectDir / (projectName + ".sln");
fs::path project { projectDir / (projectName + ".vcxproj") };
fs::path user { projectDir / (projectName + ".vcxproj.user") };
fs::path filters { projectDir / (projectName + ".vcxproj.filters") };
std::pair <string, string> replacements;
if (!fs::equivalent(getOFRoot(), fs::path{ "../../.." })) {
string root { getOFRoot().string() };
string relRootWindows { convertStringToWindowsSeparator(root) + "\\" };

replacements = { "..\\..\\..\\", relRootWindows };
} else {
// cout << "equivalent to default ../../.." << endl;
}

// solution
copyTemplateFiles.push_back({
templatePath / "emptyExample.sln",
projectDir / (projectName + ".sln"),
{
{ "emptyExample", projectName },
replacements
}
});

// project
copyTemplateFiles.push_back({
templatePath / "emptyExample.vcxproj",
projectDir / (projectName + ".vcxproj"),
{
{ "emptyExample", projectName },
replacements
}

fs::copy(templatePath / "emptyExample.vcxproj", project, fs::copy_options::overwrite_existing);
fs::copy(templatePath / "emptyExample.vcxproj.user", user, fs::copy_options::overwrite_existing);
fs::copy(templatePath / "emptyExample.sln", solution, fs::copy_options::overwrite_existing);
fs::copy(templatePath / "emptyExample.vcxproj.filters", filters, fs::copy_options::overwrite_existing);
});

// user
copyTemplateFiles.push_back({
templatePath / "emptyExample.vcxproj.user",
projectDir / (projectName + ".vcxproj.user"),
{{ "emptyExample", projectName }}

});

// filters
copyTemplateFiles.push_back({
templatePath / "emptyExample.vcxproj.filters",
projectDir / (projectName + ".vcxproj.filters")
});

// icon
copyTemplateFiles.push_back({
templatePath / "icon.rc",
projectDir / "icon.rc"
});

for (auto & c : copyTemplateFiles) {
c.run();
}

fs::copy(templatePath / "icon.rc", projectDir / "icon.rc", fs::copy_options::overwrite_existing);

fs::path filters { projectDir / (projectName + ".vcxproj.filters") };

pugi::xml_parse_result result = filterXmlDoc.load_file(filters.c_str());
if (result.status==pugi::status_ok) {
ofLogVerbose() << "loaded filter ";
} else {
ofLogVerbose() << "problem loading filter ";
}

findandreplaceInTexfile(solution, "emptyExample", projectName);
findandreplaceInTexfile(user, "emptyExample", projectName);
findandreplaceInTexfile(project, "emptyExample", projectName);


if (!fs::equivalent(getOFRoot(), fs::path{ "../../.." })) {
string root { getOFRoot().string() };
string relRootWindows { convertStringToWindowsSeparator(root) + "\\" };

// sln has windows paths:
// alert ("replacing root with " + relRootWindows, 36);
findandreplaceInTexfile(solution, "..\\..\\..\\", relRootWindows);

// vcx has unixy paths:
//..\..\..\libs
findandreplaceInTexfile(project, "..\\..\\..\\", relRootWindows);
} else {
// cout << "equivalent to default ../../.." << endl;
}

return true;
}

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

} else if (ext == ".storyboard" || ext == ".mm") {
// Do not add files for other platforms
// Do not add files for other platforms
} else{
appendValue(doc, "ClCompile", "Include", srcFileString);

Expand Down
6 changes: 0 additions & 6 deletions commandLine/src/utils/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,3 @@ bool ofIsPathInPath(const fs::path & path, const fs::path & base);
Idea: create an object to hold the origin and destination files, with renames where needed
and string substitution, so we can avoid opening and writing multiple times the same file, less ssd wear.
*/
struct fromToReplace {
public:
fs::path from;
fs::path to;
std::vector <std::pair <string, string> > findReplaces;
};