forked from oelmekki/pgrebase
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
142 lines (116 loc) · 2.74 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package main
import (
"fmt"
"os"
"log"
"time"
)
var Cfg Config
/*
* Usage :
* DATABASE_URL=url pgrebase [-w] sql_dir/
*/
func ParseConfig() {
if err := Cfg.Parse() ; err != nil {
fmt.Printf( "Error: %v\n", err )
Usage()
}
}
/*
* Expected target structure:
*
* <sql_dir>/
* functions/
* triggers/
* types/
* views/
*
* At least one of functions/triggers/types/views/ should exist.
*
*/
func CheckSanity() {
sanity := Sanity{}
if err := sanity.Check() ; err != nil {
fmt.Printf( "Error: %v\n", err )
Usage()
}
}
/*
* Give user a chance to know what went wrong
*/
func Usage() {
usage := `
PgRebase-1.1.0
USAGE:
DATABASE_URL=url pgrebase [-w] <sql_directory>
PgRebase is a tool that allows you to easily handle your postgres codebase for
functions, triggers, types and views.
Your expected to provide a postgresql connection url as DATABASE_URL and
a sql directory as <sql_directory>.
<sql_directory> should be structured that way:
<sql_directory>/
├── functions/
├── triggers/
├── types/
└── views/
At least one of functions/triggers/types/views should exist.
OPTIONS:
-w: enter watch mode.
In watch mode, pgrebase will keep watching for file changes and will
automatically reload your sql code when it happens.
`;
fmt.Println( usage )
os.Exit(1)
}
/*
* Start the actual work
*/
func Process() ( err error ) {
if err = LoadTypes() ; err != nil { return err }
if err = LoadViews() ; err != nil { return err }
if err = LoadFunctions() ; err != nil { return err }
if err = LoadTriggers() ; err != nil { return err }
return
}
/*
* Fire a watcher, will die as soon something changed
*/
func StartWatching( errorChan chan error, doneChan chan bool ) ( err error ) {
watcher := Watcher{ Done: doneChan, Error: errorChan }
go watcher.Start()
return
}
/*
* Process events from watchers
*/
func WatchTheWatcher() {
fmt.Println( "Watching filesystem for changes..." )
errorChan := make( chan error )
doneChan := make( chan bool )
if err := StartWatching( errorChan, doneChan ) ; err != nil { log.Fatal( err ) }
for {
select {
case <-doneChan:
time.Sleep( 300 * time.Millisecond ) // without this, new file watcher is started faster than file writing has ended
Cfg.ScanFiles()
if err := Process() ; err != nil {
fmt.Printf( "Error: %v\n", err )
}
if err := StartWatching( errorChan, doneChan ) ; err != nil { log.Fatal( err ) }
case err := <-errorChan:
fmt.Printf( "Error: %v\n", err )
if err := StartWatching( errorChan, doneChan ) ; err != nil { log.Fatal( err ) }
}
}
}
func main() {
ParseConfig()
CheckSanity()
if err := Process() ; err != nil {
fmt.Printf( "Error: %v\n", err )
os.Exit(1)
}
if Cfg.WatchMode {
WatchTheWatcher()
}
}