Home | History | Annotate | Download | only in localize
      1 #include "Perforce.h"
      2 #include "log.h"
      3 #include <string.h>
      4 #include <cstdio>
      5 #include <stdlib.h>
      6 #include <sstream>
      7 #include <sys/types.h>
      8 #include <unistd.h>
      9 #include <stdlib.h>
     10 #include <string.h>
     11 #include <sys/wait.h>
     12 #include <cstdio>
     13 
     14 using namespace std;
     15 
     16 extern char** environ;
     17 
     18 int
     19 Perforce::RunCommand(const string& cmd, string* result, bool printOnFailure)
     20 {
     21     int err;
     22     int outPipe[2];
     23     int errPipe[2];
     24     pid_t pid;
     25 
     26     log_printf("Perforce::RunCommand: %s\n", cmd.c_str());
     27 
     28     err = pipe(outPipe);
     29     err |= pipe(errPipe);
     30     if (err == -1) {
     31         printf("couldn't create pipe. exiting.\n");
     32         exit(1);
     33         return -1;
     34     }
     35 
     36     pid = fork();
     37     if (pid == -1) {
     38         printf("couldn't fork. eixiting\n");
     39         exit(1);
     40         return -1;
     41     }
     42     else if (pid == 0) {
     43         char const* args[] = {
     44             "/bin/sh",
     45             "-c",
     46             cmd.c_str(),
     47             NULL
     48         };
     49         close(outPipe[0]);
     50         close(errPipe[0]);
     51         dup2(outPipe[1], 1);
     52         dup2(errPipe[1], 2);
     53         execve(args[0], (char* const*)args, environ);
     54         // done
     55     }
     56 
     57     close(outPipe[1]);
     58     close(errPipe[1]);
     59 
     60     result->clear();
     61 
     62     char buf[1024];
     63 
     64     // stdout
     65     while (true) {
     66         size_t amt = read(outPipe[0], buf, sizeof(buf));
     67         result->append(buf, amt);
     68         if (amt <= 0) {
     69             break;
     70         }
     71     }
     72 
     73     // stderr -- the messages are short so it ought to just fit in the buffer
     74     string error;
     75     while (true) {
     76         size_t amt = read(errPipe[0], buf, sizeof(buf));
     77         error.append(buf, amt);
     78         if (amt <= 0) {
     79             break;
     80         }
     81     }
     82 
     83     close(outPipe[0]);
     84     close(errPipe[0]);
     85 
     86     waitpid(pid, &err, 0);
     87     if (WIFEXITED(err)) {
     88         err = WEXITSTATUS(err);
     89     } else {
     90         err = -1;
     91     }
     92     if (err != 0 && printOnFailure) {
     93         write(2, error.c_str(), error.length());
     94     }
     95     return err;
     96 }
     97 
     98 int
     99 Perforce::GetResourceFileNames(const string& version, const string& base,
    100                                 const vector<string>& apps, vector<string>* results,
    101                                 bool printOnFailure)
    102 {
    103     int err;
    104     string text;
    105     stringstream cmd;
    106 
    107     cmd << "p4 files";
    108 
    109     const size_t I = apps.size();
    110     for (size_t i=0; i<I; i++) {
    111         cmd << " \"" << base << '/' << apps[i] << "/res/values/strings.xml@" << version << '"';
    112     }
    113 
    114     err = RunCommand(cmd.str(), &text, printOnFailure);
    115 
    116     const char* str = text.c_str();
    117     while (*str) {
    118         const char* lineend = strchr(str, '\n');
    119         if (lineend == str) {
    120             str++;
    121             continue;
    122         }
    123         if (lineend-str > 1023) {
    124             fprintf(stderr, "line too long!\n");
    125             return 1;
    126         }
    127 
    128         string s(str, lineend-str);
    129 
    130         char filename[1024];
    131         char edit[1024];
    132         int count = sscanf(str, "%[^#]#%*d - %s change %*d %*[^\n]\n", filename, edit);
    133 
    134         if (count == 2 && 0 != strcmp("delete", edit)) {
    135             results->push_back(string(filename));
    136         }
    137 
    138         str = lineend + 1;
    139     }
    140 
    141     return err;
    142 }
    143 
    144 int
    145 Perforce::GetFile(const string& file, const string& version, string* result,
    146         bool printOnFailure)
    147 {
    148     stringstream cmd;
    149     cmd << "p4 print -q \"" << file << '@' << version << '"';
    150     return RunCommand(cmd.str(), result, printOnFailure);
    151 }
    152 
    153 string
    154 Perforce::GetCurrentChange(bool printOnFailure)
    155 {
    156     int err;
    157     string text;
    158 
    159     err = RunCommand("p4 changes -m 1 \\#have", &text, printOnFailure);
    160     if (err != 0) {
    161         return "";
    162     }
    163 
    164     long long n;
    165     int count = sscanf(text.c_str(), "Change %lld on", &n);
    166     if (count != 1) {
    167         return "";
    168     }
    169 
    170     char result[100];
    171     sprintf(result, "%lld", n);
    172 
    173     return string(result);
    174 }
    175 
    176 static int
    177 do_files(const string& op, const vector<string>& files, bool printOnFailure)
    178 {
    179     string text;
    180     stringstream cmd;
    181 
    182     cmd << "p4 " << op;
    183 
    184     const size_t I = files.size();
    185     for (size_t i=0; i<I; i++) {
    186         cmd << " \"" << files[i] << "\"";
    187     }
    188 
    189     return Perforce::RunCommand(cmd.str(), &text, printOnFailure);
    190 }
    191 
    192 int
    193 Perforce::EditFiles(const vector<string>& files, bool printOnFailure)
    194 {
    195     return do_files("edit", files, printOnFailure);
    196 }
    197 
    198 int
    199 Perforce::AddFiles(const vector<string>& files, bool printOnFailure)
    200 {
    201     return do_files("add", files, printOnFailure);
    202 }
    203 
    204 int
    205 Perforce::DeleteFiles(const vector<string>& files, bool printOnFailure)
    206 {
    207     return do_files("delete", files, printOnFailure);
    208 }
    209 
    210 string
    211 Perforce::Where(const string& depotPath, bool printOnFailure)
    212 {
    213     int err;
    214     string text;
    215     string cmd = "p4 where ";
    216     cmd += depotPath;
    217 
    218     err = RunCommand(cmd, &text, printOnFailure);
    219     if (err != 0) {
    220         return "";
    221     }
    222 
    223     size_t index = text.find(' ');
    224     if (index == text.npos) {
    225         return "";
    226     }
    227     index = text.find(' ', index+1)+1;
    228     if (index == text.npos) {
    229         return "";
    230     }
    231 
    232     return text.substr(index, text.length()-index-1);
    233 }
    234 
    235