@@ -111,6 +111,15 @@ type dbOpts struct {
111
111
}
112
112
113
113
func main() {
114
+
// Use another function to allow the use of defer for cleanup, as
115
+
// os.Exit() does not run deferred functions
116
+
if err := run(); err != nil {
117
+
l.Fatalln(err)
118
+
os.Exit(1)
119
+
}
120
+
}
121
+
122
+
func run() error {
114
123
// Parse commanline arguments first so that we can quit if we
115
124
// have shown usage or version string. We may have to load a
116
125
// non default configuration file
@@ -126,15 +135,13 @@ func main() {
126
135
// check the result
127
136
if len(pce.LegacyConfig) > 0 {
128
137
if err := convertLegacyConfFile(pce.LegacyConfig); err != nil {
129
-
l.Fatalln(err)
130
-
os.Exit(1)
138
+
return err
131
139
}
132
140
}
133
-
os.Exit(0)
134
-
} else {
135
-
l.Fatalln(err)
136
-
os.Exit(1)
141
+
return nil
137
142
}
143
+
144
+
return err
138
145
}
139
146
140
147
// Enable verbose mode or quiet mode as soon as possible
@@ -144,8 +151,7 @@ func main() {
144
151
// file to be absent
145
152
configOpts, err := loadConfigurationFile(cliOpts.CfgFile)
146
153
if err != nil && cliOpts.CfgFile != defaultCfgFile {
147
-
l.Fatalln(err)
148
-
os.Exit(1)
154
+
return err
149
155
}
150
156
151
157
// override options from the configuration file with ones from
@@ -167,10 +173,10 @@ func main() {
167
173
}
168
174
169
175
if err := decryptDirectory(opts.Directory, opts.CipherPassphrase, opts.Jobs, globs); err != nil {
170
-
l.Fatalln(err)
171
-
os.Exit(1)
176
+
return err
172
177
}
173
-
os.Exit(0)
178
+
179
+
return nil
174
180
}
175
181
176
182
// Remember when we start so that a purge interval of 0s won't remove the dumps we
@@ -184,30 +190,31 @@ func main() {
184
190
// Ensure that pg_dump accepts the options we will give it
185
191
pgDumpVersion := pgToolVersion("pg_dump")
186
192
if pgDumpVersion < 80400 {
187
-
l.Fatalln("provided pg_dump is older than 8.4, unable use it.")
188
-
os.Exit(1)
193
+
return fmt.Errorf("provided pg_dump is older than 8.4, unable use it.")
189
194
}
190
195
191
196
// Parse the connection information
192
197
l.Verboseln("processing input connection parameters")
193
198
conninfo, err := prepareConnInfo(opts.Host, opts.Port, opts.Username, opts.ConnDb)
194
199
if err != nil {
195
-
l.Fatalln("could not compute connection string:", err)
196
-
os.Exit(1)
200
+
return fmt.Errorf("could not compute connection string: %w", err)
197
201
}
198
202
203
+
defer postBackupHook(opts.PostHook)
199
204
if err := preBackupHook(opts.PreHook); err != nil {
200
-
postBackupHook(opts.PostHook)
201
-
os.Exit(1)
205
+
return err
202
206
}
203
207
204
208
// Use another goroutine to compute checksum of other files than
205
209
// dumps. We just have to send the paths of files to it.
206
210
producedFiles := make(chan string)
207
211
208
-
// To stop gracefully, we would close the channel and tell the main
209
-
// goroutine it's done
210
-
ppDone := make(chan bool, 1)
212
+
var wg sync.WaitGroup
213
+
214
+
wg.Add(1)
215
+
defer wg.Wait()
216
+
defer close(producedFiles)
217
+
211
218
go func() {
212
219
for {
213
220
file, more := <-producedFiles
@@ -236,23 +243,17 @@ func main() {
236
243
}
237
244
}
238
245
}
239
-
ppDone <- true
246
+
wg.Done()
240
247
}()
241
248
242
249
l.Infoln("dumping globals")
243
250
if err := dumpGlobals(opts.Directory, opts.TimeFormat, conninfo, producedFiles); err != nil {
244
-
l.Fatalln("pg_dumpall -g failed:", err)
245
-
postBackupHook(opts.PostHook)
246
-
os.Exit(1)
251
+
return fmt.Errorf("pg_dumpall -g failed: %w", err)
247
252
}
248
253
249
254
db, err := dbOpen(conninfo)
250
255
if err != nil {
251
-
l.Fatalln("connection to PostgreSQL failed:", err)
252
-
postBackupHook(opts.PostHook)
253
-
close(producedFiles)
254
-
<-ppDone
255
-
os.Exit(1)
256
+
return fmt.Errorf("connection to PostgreSQL failed: %w", err)
256
257
}
257
258
defer db.Close()
258
259
@@ -262,42 +263,22 @@ func main() {
262
263
if errors.As(err, &verr) {
263
264
l.Warnln(err)
264
265
} else {
265
-
db.Close()
266
-
l.Fatalln("could not dump configuration parameters:", err)
267
-
postBackupHook(opts.PostHook)
268
-
close(producedFiles)
269
-
<-ppDone
270
-
os.Exit(1)
266
+
return fmt.Errorf("could not dump configuration parameters: %w", err)
271
267
}
272
268
}
273
269
274
270
if err := dumpConfigFiles(opts.Directory, opts.TimeFormat, db, producedFiles); err != nil {
275
-
db.Close()
276
-
l.Fatalln("could not dump configuration files:", err)
277
-
postBackupHook(opts.PostHook)
278
-
close(producedFiles)
279
-
<-ppDone
280
-
os.Exit(1)
271
+
return fmt.Errorf("could not dump configuration files: %w", err)
281
272
}
282
273
283
274
databases, err := listDatabases(db, opts.WithTemplates, opts.ExcludeDbs, opts.Dbnames)
284
275
if err != nil {
285
-
l.Fatalln(err)
286
-
db.Close()
287
-
postBackupHook(opts.PostHook)
288
-
close(producedFiles)
289
-
<-ppDone
290
-
os.Exit(1)
276
+
return err
291
277
}
292
278
l.Verboseln("databases to dump:", databases)
293
279
294
280
if err := pauseReplicationWithTimeout(db, opts.PauseTimeout); err != nil {
295
-
db.Close()
296
-
l.Fatalln(err)
297
-
postBackupHook(opts.PostHook)
298
-
close(producedFiles)
299
-
<-ppDone
300
-
os.Exit(1)
281
+
return err
301
282
}
302
283
303
284
exitCode := 0
@@ -446,10 +427,11 @@ func main() {
446
427
}
447
428
}
448
429
449
-
postBackupHook(opts.PostHook)
450
-
close(producedFiles)
451
-
<-ppDone
452
-
os.Exit(exitCode)
430
+
if exitCode != 0 {
431
+
return fmt.Errorf("some operation failed")
432
+
}
433
+
434
+
return nil
453
435
}
454
436
455
437
func defaultDbOpts(opts options) *dbOpts {
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4