@@ -3,6 +3,7 @@ package regresql
33import (
44 "fmt"
55 "os"
6+ "time"
67)
78
89/*
@@ -92,7 +93,7 @@ case and add a value for each parameter. `)
9293Update updates the expected files from the queries and their parameters.
9394Each query runs in its own transaction that rolls back (unless commit is true).
9495*/
95- func Update (root string , runFilter string , commit , noRestore bool ) {
96+ func Update (root string , runFilter string , commit , noRestore , forceRestore bool ) {
9697 config , err := ReadConfig (root )
9798 ignorePatterns := []string {}
9899 if err == nil {
@@ -107,7 +108,7 @@ func Update(root string, runFilter string, commit, noRestore bool) {
107108 os .Exit (3 )
108109 }
109110
110- autoRestore (config , root , noRestore )
111+ autoRestore (config , root , noRestore , forceRestore )
111112
112113 if err := TestConnectionString (config .PgUri ); err != nil {
113114 fmt .Print (err .Error ())
@@ -135,7 +136,7 @@ the regresql update command again to reset the expected output files.
135136 ` )
136137}
137138
138- func autoRestore (cfg config , root string , noRestore bool ) {
139+ func autoRestore (cfg config , root string , noRestore , forceRestore bool ) {
139140 if noRestore || ! ShouldAutoRestore (cfg .Snapshot ) {
140141 return
141142 }
@@ -144,22 +145,53 @@ func autoRestore(cfg config, root string, noRestore bool) {
144145 fmt .Printf ("Error: snapshot file not found: %s\n \n Run 'regresql snapshot build' to create a snapshot, or use '--no-restore' to skip\n " , snapshotPath )
145146 os .Exit (1 )
146147 }
147- fmt .Printf ("Restoring snapshot: %s\n " , snapshotPath )
148+
149+ snapshotsDir := GetSnapshotsDir (root )
150+ targetDB := cfg .Snapshot .RestoreDatabase
151+
152+ if ! forceRestore {
153+ needsRestore , reason := NeedsRestore (snapshotsDir , snapshotPath , targetDB )
154+ if ! needsRestore {
155+ state , _ := ReadRestoreState (snapshotsDir )
156+ fmt .Printf ("Skipping restore: snapshot unchanged since %s (restored in %.1fs)\n \n " ,
157+ state .RestoredAt .Local ().Format ("2006-01-02 15:04:05" ),
158+ float64 (state .DurationMillis )/ 1000 )
159+ return
160+ }
161+ fmt .Printf ("Restoring snapshot: %s (%s)\n " , snapshotPath , reason )
162+ } else {
163+ fmt .Printf ("Restoring snapshot: %s (forced)\n " , snapshotPath )
164+ }
165+
166+ start := time .Now ()
148167 opts := RestoreOptions {
149168 InputPath : snapshotPath ,
150169 Clean : true ,
151- TargetDatabase : cfg . Snapshot . RestoreDatabase ,
170+ TargetDatabase : targetDB ,
152171 }
153172 if err := RestoreSnapshot (cfg .PgUri , opts ); err != nil {
154173 fmt .Printf ("Error: failed to restore snapshot: %s\n " , err )
155174 os .Exit (1 )
156175 }
157- fmt .Println ()
176+ duration := time .Since (start )
177+
178+ stat , _ := os .Stat (snapshotPath )
179+ state := & RestoreState {
180+ SnapshotPath : snapshotPath ,
181+ SnapshotMtime : stat .ModTime (),
182+ SnapshotSize : stat .Size (),
183+ Database : targetDB ,
184+ RestoredAt : time .Now ().UTC (),
185+ DurationMillis : duration .Milliseconds (),
186+ }
187+ WriteRestoreState (snapshotsDir , state )
188+
189+ fmt .Printf ("Restored in %.1fs\n \n " , duration .Seconds ())
158190}
159191
160192// Test runs regression tests for all queries.
161193// Each query runs in its own transaction that rolls back (unless commit is true).
162- func Test (root , runFilter , formatName , outputPath string , commit , noRestore bool ) {
194+ func Test (root , runFilter , formatName , outputPath string , commit , noRestore , forceRestore bool ) {
163195 config , err := ReadConfig (root )
164196 ignorePatterns := []string {}
165197 if err == nil {
@@ -177,7 +209,7 @@ func Test(root, runFilter, formatName, outputPath string, commit, noRestore bool
177209 // Cache config for plan quality analysis
178210 SetGlobalConfig (config )
179211
180- autoRestore (config , root , noRestore )
212+ autoRestore (config , root , noRestore , forceRestore )
181213
182214 // Validate schema hasn't changed since last snapshot build
183215 if err := ValidateSchemaHash (root ); err != nil {
0 commit comments