21
21
#include " util/process_wrapper/system.h"
22
22
#include " util/process_wrapper/utils.h"
23
23
24
- using CharType = process_wrapper::System::StrType::value_type;
24
+ using namespace process_wrapper ;
25
+ using CharType = System::StrType::value_type;
26
+
27
+ static int process_param_file (System::StrType& path,
28
+ System::Arguments& collected_args,
29
+ const std::vector<Subst>& subst_mappings) {
30
+ System::StrVecType args;
31
+ if (!ReadFileToVec (path, args)) {
32
+ std::cerr << " Cannot read param file " << ToUtf8 (path) << " \n " ;
33
+ return -1 ;
34
+ }
35
+ for (System::StrType& arg : args) {
36
+ // Expand tokens into each argument (since some paths might embed `${pwd}`
37
+ // that we need to resolve from the subsitution mappings).
38
+ ReplaceTokens (arg, subst_mappings);
39
+
40
+ // If this is a param file, expand it into the top-level arguments by
41
+ // recursing into its content.
42
+ if (arg.size () > 0 && arg.substr (0 , 1 ) == PW_SYS_STR (" @" )) {
43
+ System::StrType path = arg.substr (1 );
44
+ int res = process_param_file (path, collected_args, subst_mappings);
45
+ if (res != 0 ) {
46
+ return res;
47
+ }
48
+ } else {
49
+ collected_args.push_back (arg);
50
+ }
51
+ }
52
+ return 0 ;
53
+ }
25
54
26
55
// Simple process wrapper allowing us to not depend on the shell to run a
27
56
// process to perform basic operations like capturing the output or having
28
57
// the $pwd used in command line arguments or environment variables
29
58
int PW_MAIN (int argc, const CharType* argv[], const CharType* envp[]) {
30
- using namespace process_wrapper ;
31
-
32
59
System::EnvironmentBlock environment_block;
33
60
// Taking all environment variables from the current process
34
61
// and sending them down to the child process
@@ -38,8 +65,6 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
38
65
39
66
System::EnvironmentBlock environment_file_block;
40
67
41
- using Subst = std::pair<System::StrType, System::StrType>;
42
-
43
68
System::StrType exec_path;
44
69
std::vector<Subst> subst_mappings;
45
70
std::vector<Subst> stamp_mappings;
@@ -53,7 +78,7 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
53
78
System::Arguments file_arguments;
54
79
55
80
// Processing current process argument list until -- is encountered
56
- // everthing after gets sent down to the child process
81
+ // everything after gets sent down to the child process
57
82
for (int i = 1 ; i < argc; ++i) {
58
83
System::StrType arg = argv[i];
59
84
if (++i == argc) {
@@ -79,7 +104,8 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
79
104
if (value == PW_SYS_STR (" ${pwd}" )) {
80
105
value = System::GetWorkingDirectory ();
81
106
}
82
- subst_mappings.push_back ({std::move (key), std::move (value)});
107
+ subst_mappings.push_back ({PW_SYS_STR (" ${" ) + key + PW_SYS_STR (" }" ),
108
+ std::move (value)});
83
109
} else if (arg == PW_SYS_STR (" --volatile-status-file" )) {
84
110
if (!volatile_status_file.empty ()) {
85
111
std::cerr << " process wrapper error: \" --volatile-status-file\" can "
@@ -90,11 +116,11 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
90
116
return -1 ;
91
117
}
92
118
} else if (arg == PW_SYS_STR (" --env-file" )) {
93
- if (!ReadFileToArray (argv[i], environment_file_block)) {
119
+ if (!ReadFileToVec (argv[i], environment_file_block)) {
94
120
return -1 ;
95
121
}
96
122
} else if (arg == PW_SYS_STR (" --arg-file" )) {
97
- if (!ReadFileToArray (argv[i], file_arguments)) {
123
+ if (!ReadFileToVec (argv[i], file_arguments)) {
98
124
return -1 ;
99
125
}
100
126
} else if (arg == PW_SYS_STR (" --touch-file" )) {
@@ -143,7 +169,7 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
143
169
for (++i; i < argc; ++i) {
144
170
arguments.push_back (argv[i]);
145
171
}
146
- // after we consume all arguments we append the files arguments
172
+ // After we have consumed all arguments add the files arguments the them.
147
173
for (const System::StrType& file_arg : file_arguments) {
148
174
arguments.push_back (file_arg);
149
175
}
@@ -154,13 +180,39 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
154
180
}
155
181
}
156
182
183
+ // Go through the arguments and make sure that we process param files so that
184
+ // we can flatten potential recursive param files within them.
185
+ for (System::StrType& arg : arguments) {
186
+ if (arg.size () > 0 && arg.substr (0 , 1 ) == PW_SYS_STR (" @" )) {
187
+ // This is a param file, process it separately.
188
+ System::StrType path = arg.substr (1 );
189
+ System::Arguments processed_args;
190
+ if (process_param_file (path, processed_args, subst_mappings) != 0 ) {
191
+ std::cerr << " Failure to process arguments list\n " ;
192
+ return -1 ;
193
+ }
194
+
195
+ // Create a new param file so that we don't need to edit the original one
196
+ // that Bazel created.
197
+ System::StrType new_path = path + PW_SYS_STR (" .expanded" );
198
+ if (!WriteVecToFile (new_path, processed_args)) {
199
+ std::cerr << " Cannot write params to file " << ToUtf8 (new_path) << " \n " ;
200
+ return -1 ;
201
+ }
202
+
203
+ // Replace the params file arg with the new one.
204
+ arg = PW_SYS_STR (" @" ) + new_path;
205
+ } else {
206
+ // Expand tokens into each argument (since some paths might embed `${pwd}`
207
+ // that we need to resolve from the subsitution mappings).
208
+ ReplaceTokens (arg, subst_mappings);
209
+ }
210
+ }
211
+
157
212
// Stamp any format string in an environment variable block
158
- for (const Subst& stamp : stamp_mappings) {
159
- System::StrType token = PW_SYS_STR (" {" );
160
- token += stamp.first ;
161
- token.push_back (' }' );
213
+ if (stamp_mappings.size ()) {
162
214
for (System::StrType& env : environment_file_block) {
163
- ReplaceToken (env, token, stamp. second );
215
+ ReplaceTokens (env, stamp_mappings );
164
216
}
165
217
}
166
218
@@ -171,19 +223,9 @@ int PW_MAIN(int argc, const CharType* argv[], const CharType* envp[]) {
171
223
environment_file_block.begin (),
172
224
environment_file_block.end ());
173
225
174
- if (subst_mappings.size ()) {
175
- for (const Subst& subst : subst_mappings) {
176
- System::StrType token = PW_SYS_STR (" ${" );
177
- token += subst.first ;
178
- token.push_back (' }' );
179
- for (System::StrType& arg : arguments) {
180
- ReplaceToken (arg, token, subst.second );
181
- }
182
-
183
- for (System::StrType& env : environment_block) {
184
- ReplaceToken (env, token, subst.second );
185
- }
186
- }
226
+ // Expand tokens in environment
227
+ for (System::StrType& env : environment_block) {
228
+ ReplaceTokens (env, subst_mappings);
187
229
}
188
230
189
231
// Have the last values added take precedence over the first.
0 commit comments