• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
RunCommand(const string & cmd,string * result,bool printOnFailure)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
GetResourceFileNames(const string & version,const string & base,const vector<string> & apps,vector<string> * results,bool printOnFailure)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
GetFile(const string & file,const string & version,string * result,bool printOnFailure)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
GetCurrentChange(bool printOnFailure)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
do_files(const string & op,const vector<string> & files,bool printOnFailure)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
EditFiles(const vector<string> & files,bool printOnFailure)193 Perforce::EditFiles(const vector<string>& files, bool printOnFailure)
194 {
195     return do_files("edit", files, printOnFailure);
196 }
197 
198 int
AddFiles(const vector<string> & files,bool printOnFailure)199 Perforce::AddFiles(const vector<string>& files, bool printOnFailure)
200 {
201     return do_files("add", files, printOnFailure);
202 }
203 
204 int
DeleteFiles(const vector<string> & files,bool printOnFailure)205 Perforce::DeleteFiles(const vector<string>& files, bool printOnFailure)
206 {
207     return do_files("delete", files, printOnFailure);
208 }
209 
210 string
Where(const string & depotPath,bool printOnFailure)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