@@ -62,6 +62,7 @@ func mainerr() (retErr error) {
62
62
mainUsage (os .Stderr )
63
63
}
64
64
var envVars envVarsFlag
65
+ fUpdate := fs .Bool ("u" , false , "update archive file if a cmp fails" )
65
66
fWork := fs .Bool ("work" , false , "print temporary work directory and do not remove when done" )
66
67
fVerbose := fs .Bool ("v" , false , "run tests verbosely" )
67
68
fs .Var (& envVars , "e" , "pass through environment variable to script (can appear multiple times)" )
@@ -84,6 +85,20 @@ func mainerr() (retErr error) {
84
85
files = []string {"-" }
85
86
}
86
87
88
+ // If we are only reading from stdin, -u cannot be specified. It seems a bit
89
+ // bizarre to invoke testscript with '-' and a regular file, but hey. In
90
+ // that case the -u flag will only apply to the regular file and we assume
91
+ // the user knows it.
92
+ onlyReadFromStdin := true
93
+ for _ , f := range files {
94
+ if f != "-" {
95
+ onlyReadFromStdin = false
96
+ }
97
+ }
98
+ if onlyReadFromStdin && * fUpdate {
99
+ return fmt .Errorf ("cannot use -u when reading from stdin" )
100
+ }
101
+
87
102
dirNames := make (map [string ]int )
88
103
for _ , filename := range files {
89
104
// TODO make running files concurrent by default? If we do, note we'll need to do
@@ -103,7 +118,7 @@ func mainerr() (retErr error) {
103
118
if err := os .Mkdir (runDir , 0777 ); err != nil {
104
119
return fmt .Errorf ("failed to create a run directory within %v for %v: %v" , td , renderFilename (filename ), err )
105
120
}
106
- if err := run (runDir , filename , * fVerbose , envVars .vals ); err != nil {
121
+ if err := run (runDir , filename , * fUpdate , * fVerbose , envVars .vals ); err != nil {
107
122
return err
108
123
}
109
124
}
@@ -162,7 +177,11 @@ func renderFilename(filename string) string {
162
177
return filename
163
178
}
164
179
165
- func run (runDir , filename string , verbose bool , envVars []string ) error {
180
+ // run runs the testscript archive in filename within the temporary runDir.
181
+ // verbose causes the output to be verbose (akin to go test -v) and update
182
+ // sets the UpdateScripts parameter passed to testscript.Run such that any
183
+ // updates to the archive get written back to filename
184
+ func run (runDir , filename string , update bool , verbose bool , envVars []string ) error {
166
185
var ar * txtar.Archive
167
186
var err error
168
187
@@ -204,12 +223,15 @@ func run(runDir, filename string, verbose bool, envVars []string) error {
204
223
return fmt .Errorf ("failed to write .gomodproxy files: %v" , err )
205
224
}
206
225
207
- if err := ioutil .WriteFile (filepath .Join (runDir , "script.txt" ), txtar .Format (& script ), 0666 ); err != nil {
208
- return fmt .Errorf ("failed to write script for %v: %v" , filename , err )
226
+ scriptFile := filepath .Join (runDir , "script.txt" )
227
+
228
+ if err := ioutil .WriteFile (scriptFile , txtar .Format (& script ), 0666 ); err != nil {
229
+ return fmt .Errorf ("failed to write script for %v: %v" , renderFilename (filename ), err )
209
230
}
210
231
211
232
p := testscript.Params {
212
- Dir : runDir ,
233
+ Dir : runDir ,
234
+ UpdateScripts : update ,
213
235
}
214
236
215
237
if _ , err := exec .LookPath ("go" ); err == nil {
@@ -282,5 +304,28 @@ func run(runDir, filename string, verbose bool, envVars []string) error {
282
304
return fmt .Errorf ("error running %v in %v\n " , renderFilename (filename ), runDir )
283
305
}
284
306
307
+ if update && filename != "-" {
308
+ // Parse the (potentially) updated scriptFile as an archive, then merge
309
+ // with the original archive, retaining order. Then write the archive
310
+ // back to the source file
311
+ source , err := ioutil .ReadFile (scriptFile )
312
+ if err != nil {
313
+ return fmt .Errorf ("failed to read from script file %v for -update: %v" , scriptFile , err )
314
+ }
315
+ updatedAr := txtar .Parse (source )
316
+ updatedFiles := make (map [string ]txtar.File )
317
+ for _ , f := range updatedAr .Files {
318
+ updatedFiles [f .Name ] = f
319
+ }
320
+ for i , f := range ar .Files {
321
+ if newF , ok := updatedFiles [f .Name ]; ok {
322
+ ar .Files [i ] = newF
323
+ }
324
+ }
325
+ if err := ioutil .WriteFile (filename , txtar .Format (ar ), 0666 ); err != nil {
326
+ return fmt .Errorf ("failed to write script back to %v for -update: %v" , renderFilename (filename ), err )
327
+ }
328
+ }
329
+
285
330
return nil
286
331
}
0 commit comments