diff --git a/buildtool.cpp b/buildtool.cpp
index 1de8d68bce7c7f18aef8e0f2654e9e913b3070b6..538a6faa51c92a1619081bace877a7bc92082552 100644 (file)
--- a/buildtool.cpp
+++ b/buildtool.cpp
*
*/
-#define BUILDTOOL_VERSION "BuildTool v0.9.5"
+#define BUILDTOOL_VERSION "BuildTool v0.9.9"
#include <stdio.h>
#include <fcntl.h>
/**
* If this prefix is seen in a substitution, use as a
* pkg-config 'libs' query
- * example: <property pkg-config="pcl"/>
+ * example: <property pkg-config-libs="pcl"/>
* ${pcl.gtkmm}
*/
String pclPrefix;
+ /**
+ * If this prefix is seen in a substitution, use as a
+ * Subversion "svn info" query
+ * example: <property subversion="svn"/>
+ * ${svn.Revision}
+ */
+ String svnPrefix;
+
+/**
+ * Execute the "svn info" command and parse the result.
+ * This is a simple, small class. Define here, because it
+ * is used by MakeBase implementation methods.
+ */
+class SvnInfo : public MakeBase
+{
+public:
+
+#if 0
+ /**
+ * Safe way. Execute "svn info --xml" and parse the result. Search for
+ * elements/attributes. Safe from changes in format.
+ */
+ bool query(const String &name, String &res)
+ {
+ String cmd = "svn info --xml";
+
+ String outString, errString;
+ bool ret = executeCommand(cmd.c_str(), "", outString, errString);
+ if (!ret)
+ {
+ error("error executing '%s': %s", cmd.c_str(), errString.c_str());
+ return false;
+ }
+ Parser parser;
+ Element *elem = parser.parse(outString);
+ if (!elem)
+ {
+ error("error parsing 'svn info' xml result: %s", outString.c_str());
+ return false;
+ }
+
+ res = elem->getTagValue(name);
+ if (res.size()==0)
+ {
+ res = elem->getTagAttribute("entry", name);
+ }
+ return true;
+ }
+#else
+
+
+ /**
+ * Universal way. Parse the file directly. Not so safe from
+ * changes in format.
+ */
+ bool query(const String &name, String &res)
+ {
+ String fileName = resolve(".svn/entries");
+ String nFileName = getNativePath(fileName);
+
+ std::map<String, String> properties;
+
+ FILE *f = fopen(nFileName.c_str(), "r");
+ if (!f)
+ {
+ error("could not open SVN 'entries' file");
+ return false;
+ }
+
+ const char *fieldNames[] =
+ {
+ "format-nbr",
+ "name",
+ "kind",
+ "revision",
+ "url",
+ "repos",
+ "schedule",
+ "text-time",
+ "checksum",
+ "committed-date",
+ "committed-rev",
+ "last-author",
+ "has-props",
+ "has-prop-mods",
+ "cachable-props",
+ };
+
+ for (int i=0 ; i<15 ; i++)
+ {
+ inbuf[0] = '\0';
+ if (feof(f) || !fgets(inbuf, 255, f))
+ break;
+ properties[fieldNames[i]] = trim(inbuf);
+ }
+ fclose(f);
+
+ res = properties[name];
+
+ return true;
+ }
+
+private:
+
+ char inbuf[256];
+
+#endif
+
+};
+
+
+
+
+
/**
* Print a printf()-like formatted error message
return false;
result = val;
}
+ else if (svnPrefix.size() > 0 &&
+ varname.compare(0, svnPrefix.size(), svnPrefix) == 0)
+ {
+ varname = varname.substr(svnPrefix.size());
+ String val;
+ SvnInfo svnInfo;
+ if (varname == "revision")
+ {
+ if (!svnInfo.query(varname, val))
+ return "";
+ result = "r"+val;
+ }
+ if (!svnInfo.query(varname, val))
+ return false;
+ result = val;
+ }
else
{
std::map<String, String>::iterator iter;
#endif
removeFromStatCache(native);
+
+ return true;
}
}
-
-
-
//########################################################################
//# D E P T O O L
//########################################################################
bool verbose = parent.evalBool(verboseOpt, false);
bool quiet = parent.evalBool(quietOpt, false);
bool failOnError = parent.evalBool(failOnErrorOpt, true);
- struct stat finfo;
switch (delType)
{
case DEL_FILE:
char *fname = (char *)fullName.c_str();
if (!quiet && verbose)
taskstatus("path: %s", fname);
- if (!removeFile(fullName)) return false;
+ if (failOnError && !removeFile(fullName))
+ {
+ //error("Could not delete file '%s'", fullName.c_str());
+ return false;
+ }
return true;
}
case DEL_DIR:
String fullDir = parent.resolve(dirName);
if (!quiet && verbose)
taskstatus("path: %s", fullDir.c_str());
- if (!removeDirectory(fullDir))
+ if (failOnError && !removeDirectory(fullDir))
+ {
+ //error("Could not delete directory '%s'", fullDir.c_str());
return false;
+ }
return true;
}
}
virtual bool execute()
{
String fileName = parent.eval(fileNameOpt, "");
+ bool force = parent.evalBool(forceOpt, false);
String text = parent.eval(textOpt, "");
taskstatus("%s", fileName.c_str());
String fullName = parent.resolve(fileName);
- if (!isNewerThan(parent.getURI().getPath(), fullName))
+ if (!force && !isNewerThan(parent.getURI().getPath(), fullName))
{
- //trace("skipped <makefile>");
+ taskstatus("skipped");
return true;
}
String fullNative = getNativePath(fullName);
{
if (!parent.getAttribute(elem, "file", fileNameOpt))
return false;
+ if (!parent.getAttribute(elem, "force", forceOpt))
+ return false;
if (fileNameOpt.size() == 0)
{
error("<makefile> requires 'file=\"filename\"' attribute");
private:
String fileNameOpt;
+ String forceOpt;
String textOpt;
};
pcPrefix = "pc.";
pccPrefix = "pcc.";
pclPrefix = "pcl.";
+ svnPrefix = "svn.";
properties.clear();
for (unsigned int i = 0 ; i < allTasks.size() ; i++)
delete allTasks[i];
pclPrefix = attrVal;
pclPrefix.push_back('.');
}
+ else if (attrName == "subversion")
+ {
+ if (attrVal.find('.') != attrVal.npos)
+ {
+ error("subversion prefix cannot have a '.' in it");
+ return false;
+ }
+ svnPrefix = attrVal;
+ svnPrefix.push_back('.');
+ }
}
return true;