@@ -50,6 +50,7 @@ bool readListFromValMap(TDst *pDst, const TMap &vm, const char *key)
5050// / transformation properties set on cmd-line
5151struct TransformerProps {
5252 TStringList prefixCmd; // /< cmd-line operands
53+ bool shellForm; // /< if true, write shell form of RUN lines
5354 bool verbose; // /< if true, print in/out of each transformation
5455};
5556
@@ -162,20 +163,50 @@ void appendShellExec(TStringList *pExecList, const std::string &str)
162163 pExecList->push_back (str);
163164}
164165
165- // / precede each back-slash and each quote by back-slash
166- std::string runQuoteArg (std::string arg)
166+ // / precede selected special chars by back-slash
167+ std::string runQuoteArg (std::string arg, const bool escapeTick= false )
167168{
168169 boost::algorithm::replace_all (arg, " \\ " , " \\\\ " );
169170 boost::algorithm::replace_all (arg, " \" " , " \\\" " );
170171 boost::algorithm::replace_all (arg, " \n " , " \\ n" );
171172 boost::algorithm::replace_all (arg, " \t " , " \\ t" );
173+
174+ if (escapeTick)
175+ boost::algorithm::replace_all (arg, " '" , " \\ '" );
176+
172177 return arg;
173178}
174179
180+ // / construct "'cmd' 'arg1' 'arg2' ..." from execList
181+ std::string runShellCmdFromExecList (const TStringList &execList)
182+ {
183+ std::string cmd;
184+
185+ int i = 0 ;
186+ for (const std::string &arg : execList) {
187+ if (i++)
188+ // space-separator
189+ cmd += " " ;
190+
191+ const std::string quoted = runQuoteArg (arg, /* escapeTick */ true );
192+ if (quoted != arg)
193+ // construct $'...'
194+ cmd += " $" ;
195+
196+ // append the quoted arg
197+ cmd += " '" + quoted + " '" ;
198+ }
199+
200+ return cmd;
201+ }
202+
175203// / construct transformed RUN command from execList
176204std::string DockerFileTransformer::runCmdFromExecList (
177205 const TStringList &execList)
178206{
207+ if (this ->tp_ .shellForm )
208+ return runShellCmdFromExecList (execList);
209+
179210 // construct ["cmd", "arg1", "arg2", ...] from execList
180211 std::string runLine = " [" ;
181212 int i = 0 ;
@@ -337,6 +368,8 @@ int main(int argc, char *argv[])
337368 desc.add_options ()
338369 (" in-place,i" , po::value<std::string>(),
339370 " modify the specified file in-place" )
371+ (" shell-form" , " write transformed RUN lines using the shell form"
372+ " (rather than exec form, which is the default format)" )
340373 (" verbose" , " print transformations to standard error output" );
341374
342375 desc.add_options ()
@@ -376,6 +409,7 @@ int main(int argc, char *argv[])
376409
377410 // read cmd-line flags
378411 TransformerProps tp;
412+ tp.shellForm = !!vm.count (" shell-form" );
379413 tp.verbose = !!vm.count (" verbose" );
380414
381415 // read the prefix command
0 commit comments