diff options
Diffstat (limited to 'tools/localize/Perforce.cpp')
-rw-r--r-- | tools/localize/Perforce.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/tools/localize/Perforce.cpp b/tools/localize/Perforce.cpp new file mode 100644 index 0000000..3184dfc --- /dev/null +++ b/tools/localize/Perforce.cpp @@ -0,0 +1,228 @@ +#include "Perforce.h" +#include "log.h" +#include <sstream> +#include <sys/types.h> +#include <unistd.h> +#include <sys/wait.h> + +using namespace std; + +extern char** environ; + +int +Perforce::RunCommand(const string& cmd, string* result, bool printOnFailure) +{ + int err; + int outPipe[2]; + int errPipe[2]; + pid_t pid; + + log_printf("Perforce::RunCommand: %s\n", cmd.c_str()); + + err = pipe(outPipe); + err |= pipe(errPipe); + if (err == -1) { + printf("couldn't create pipe. exiting.\n"); + exit(1); + return -1; + } + + pid = fork(); + if (pid == -1) { + printf("couldn't fork. eixiting\n"); + exit(1); + return -1; + } + else if (pid == 0) { + char const* args[] = { + "/bin/sh", + "-c", + cmd.c_str(), + NULL + }; + close(outPipe[0]); + close(errPipe[0]); + dup2(outPipe[1], 1); + dup2(errPipe[1], 2); + execve(args[0], (char* const*)args, environ); + // done + } + + close(outPipe[1]); + close(errPipe[1]); + + result->clear(); + + char buf[1024]; + + // stdout + while (true) { + size_t amt = read(outPipe[0], buf, sizeof(buf)); + result->append(buf, amt); + if (amt <= 0) { + break; + } + } + + // stderr -- the messages are short so it ought to just fit in the buffer + string error; + while (true) { + size_t amt = read(errPipe[0], buf, sizeof(buf)); + error.append(buf, amt); + if (amt <= 0) { + break; + } + } + + close(outPipe[0]); + close(errPipe[0]); + + waitpid(pid, &err, 0); + if (WIFEXITED(err)) { + err = WEXITSTATUS(err); + } else { + err = -1; + } + if (err != 0 && printOnFailure) { + write(2, error.c_str(), error.length()); + } + return err; +} + +int +Perforce::GetResourceFileNames(const string& version, const string& base, + const vector<string>& apps, vector<string>* results, + bool printOnFailure) +{ + int err; + string text; + stringstream cmd; + + cmd << "p4 files"; + + const size_t I = apps.size(); + for (size_t i=0; i<I; i++) { + cmd << " \"" << base << '/' << apps[i] << "/res/values/strings.xml@" << version << '"'; + } + + err = RunCommand(cmd.str(), &text, printOnFailure); + + const char* str = text.c_str(); + while (*str) { + const char* lineend = strchr(str, '\n'); + if (lineend == str) { + str++; + continue; + } + if (lineend-str > 1023) { + fprintf(stderr, "line too long!\n"); + return 1; + } + + string s(str, lineend-str); + + char filename[1024]; + char edit[1024]; + int count = sscanf(str, "%[^#]#%*d - %s change %*d %*[^\n]\n", filename, edit); + + if (count == 2 && 0 != strcmp("delete", edit)) { + results->push_back(string(filename)); + } + + str = lineend + 1; + } + + return err; +} + +int +Perforce::GetFile(const string& file, const string& version, string* result, + bool printOnFailure) +{ + stringstream cmd; + cmd << "p4 print -q \"" << file << '@' << version << '"'; + return RunCommand(cmd.str(), result, printOnFailure); +} + +string +Perforce::GetCurrentChange(bool printOnFailure) +{ + int err; + string text; + + err = RunCommand("p4 changes -m 1 \\#have", &text, printOnFailure); + if (err != 0) { + return ""; + } + + long long n; + int count = sscanf(text.c_str(), "Change %lld on", &n); + if (count != 1) { + return ""; + } + + char result[100]; + sprintf(result, "%lld", n); + + return string(result); +} + +static int +do_files(const string& op, const vector<string>& files, bool printOnFailure) +{ + string text; + stringstream cmd; + + cmd << "p4 " << op; + + const size_t I = files.size(); + for (size_t i=0; i<I; i++) { + cmd << " \"" << files[i] << "\""; + } + + return Perforce::RunCommand(cmd.str(), &text, printOnFailure); +} + +int +Perforce::EditFiles(const vector<string>& files, bool printOnFailure) +{ + return do_files("edit", files, printOnFailure); +} + +int +Perforce::AddFiles(const vector<string>& files, bool printOnFailure) +{ + return do_files("add", files, printOnFailure); +} + +int +Perforce::DeleteFiles(const vector<string>& files, bool printOnFailure) +{ + return do_files("delete", files, printOnFailure); +} + +string +Perforce::Where(const string& depotPath, bool printOnFailure) +{ + int err; + string text; + string cmd = "p4 where "; + cmd += depotPath; + + err = RunCommand(cmd, &text, printOnFailure); + if (err != 0) { + return ""; + } + + size_t index = text.find(' '); + if (index == text.npos) { + return ""; + } + index = text.find(' ', index+1)+1; + if (index == text.npos) { + return ""; + } + + return text.substr(index, text.length()-index-1); +} + |