@@ -10,6 +10,7 @@ import (
10
10
"fmt"
11
11
"io"
12
12
"os"
13
+ "regexp"
13
14
"strconv"
14
15
"strings"
15
16
"sync"
@@ -377,9 +378,14 @@ func (tm *tasksManager) watch(task *task, terminal *terminal.Term) {
377
378
go func () {
378
379
defer stdout .Close ()
379
380
380
- fileName := tm .prebuildLogFileName (task )
381
- // TODO(janx): If the file already exists (from a parent prebuild), extract its "time saved", and log that below
382
- // (instead, or in addition to, the incremental prebuild time).
381
+ var (
382
+ fileName = tm .prebuildLogFileName (task )
383
+ oldFileName = fileName + "-old"
384
+ )
385
+ if _ , err := os .Stat (fileName ); err == nil {
386
+ // If the file already exists (from a parent prebuild), temporarily move it so that it doesn't get truncated.
387
+ _ = os .Rename (fileName , oldFileName )
388
+ }
383
389
file , err := os .Create (fileName )
384
390
var fileWriter * bufio.Writer
385
391
if err != nil {
@@ -391,12 +397,14 @@ func (tm *tasksManager) watch(task *task, terminal *terminal.Term) {
391
397
fileWriter = bufio .NewWriter (file )
392
398
defer fileWriter .Flush ()
393
399
}
400
+ // Import any parent prebuild logs and parse their total duration if available
401
+ parentElapsed := importParentLogAndGetDuration (oldFileName , fileWriter )
394
402
395
403
buf := make ([]byte , 4096 )
396
404
for {
397
405
n , err := stdout .Read (buf )
398
406
if err == io .EOF {
399
- elapsed := time .Since (start )
407
+ elapsed := time .Since (start ) + parentElapsed
400
408
duration := ""
401
409
if elapsed >= 1 * time .Minute {
402
410
elapsedInMinutes := strconv .Itoa (int (elapsed .Minutes ()))
@@ -425,6 +433,45 @@ func (tm *tasksManager) watch(task *task, terminal *terminal.Term) {
425
433
}()
426
434
}
427
435
436
+ func importParentLogAndGetDuration (fileName string , fileWriter * bufio.Writer ) time.Duration {
437
+ if _ , err := os .Stat (fileName ); err != nil {
438
+ return 0
439
+ }
440
+ defer os .Remove (fileName )
441
+
442
+ file , err := os .Open (fileName )
443
+ if err != nil {
444
+ return 0
445
+ }
446
+ defer file .Close ()
447
+
448
+ defer fileWriter .WriteString ("♻️ Re-running this task as an incremental workspace prebuild\n \n " )
449
+
450
+ scanner := bufio .NewScanner (file )
451
+ for scanner .Scan () {
452
+ l := scanner .Text ()
453
+ if strings .Contains (l , "🤙 This task ran as a workspace prebuild" ) {
454
+ break
455
+ }
456
+ fileWriter .WriteString (l + "\n " )
457
+ }
458
+ if ! scanner .Scan () {
459
+ return 0
460
+ }
461
+ reg , err := regexp .Compile (`🎉 Well done on saving (\d+) minute` )
462
+ if err != nil {
463
+ return 0
464
+ }
465
+ res := reg .FindStringSubmatch (scanner .Text ())
466
+ if res == nil {
467
+ return 0
468
+ }
469
+ if elapsedInMinutes , err := strconv .Atoi (res [1 ]); err == nil {
470
+ return time .Duration (elapsedInMinutes ) * time .Minute
471
+ }
472
+ return 0
473
+ }
474
+
428
475
type composeCommandOptions struct {
429
476
commands []* string
430
477
format string
0 commit comments