-
Notifications
You must be signed in to change notification settings - Fork 242
/
Copy pathinit.go
170 lines (152 loc) · 4.9 KB
/
init.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package init
import (
"bytes"
"context"
_ "embed"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"github.com/go-errors/errors"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/utils"
"github.com/tidwall/jsonc"
)
var (
vscodeDir = ".vscode"
extensionsPath = filepath.Join(vscodeDir, "extensions.json")
settingsPath = filepath.Join(vscodeDir, "settings.json")
intellijDir = ".idea"
denoPath = filepath.Join(intellijDir, "deno.xml")
//go:embed templates/.gitignore
initGitignore []byte
//go:embed templates/.vscode/extensions.json
vscodeExtensions string
//go:embed templates/.vscode/settings.json
vscodeSettings string
//go:embed templates/.idea/deno.xml
intelliJDeno string
)
func Run(ctx context.Context, fsys afero.Fs, createVscodeSettings, createIntellijSettings *bool, params utils.InitParams) error {
// 1. Write `config.toml`.
if err := utils.InitConfig(params, fsys); err != nil {
if errors.Is(err, os.ErrExist) {
utils.CmdSuggestion = fmt.Sprintf("Run %s to overwrite existing config file.", utils.Aqua("supabase init --force"))
}
return err
}
// 2. Append to `.gitignore`.
if utils.IsGitRepo() {
if err := updateGitIgnore(utils.GitIgnorePath, fsys); err != nil {
return err
}
}
// 3. Generate VS Code settings.
if createVscodeSettings != nil {
if *createVscodeSettings {
return writeVscodeConfig(fsys)
}
} else if createIntellijSettings != nil {
if *createIntellijSettings {
return writeIntelliJConfig(fsys)
}
} else {
console := utils.NewConsole()
if isVscode, err := console.PromptYesNo(ctx, "Generate VS Code settings for Deno?", false); err != nil {
return err
} else if isVscode {
return writeVscodeConfig(fsys)
}
if isIntelliJ, err := console.PromptYesNo(ctx, "Generate IntelliJ Settings for Deno?", false); err != nil {
return err
} else if isIntelliJ {
return writeIntelliJConfig(fsys)
}
}
return nil
}
func updateGitIgnore(ignorePath string, fsys afero.Fs) error {
var contents []byte
if contained, err := afero.FileContainsBytes(fsys, ignorePath, initGitignore); contained {
return nil
} else if err == nil {
// Add a line break when appending
contents = append(contents, '\n')
} else if !errors.Is(err, os.ErrNotExist) {
return errors.Errorf("failed to read git ignore file: %w", err)
}
f, err := fsys.OpenFile(ignorePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return errors.Errorf("failed to create git ignore file: %w", err)
}
defer f.Close()
if _, err := f.Write(append(contents, initGitignore...)); err != nil {
return errors.Errorf("failed to write git ignore file: %w", err)
}
return nil
}
type VSCodeSettings map[string]interface{}
func loadUserSettings(path string, fsys afero.Fs) (VSCodeSettings, error) {
data, err := afero.ReadFile(fsys, path)
if err != nil {
return nil, errors.Errorf("failed to load settings file: %w", err)
}
data = jsonc.ToJSONInPlace(data)
// Parse and unmarshal JSON file.
var userSettings VSCodeSettings
dec := json.NewDecoder(bytes.NewReader(data))
if err := dec.Decode(&userSettings); err != nil {
return nil, errors.Errorf("failed to parse settings: %w", err)
}
return userSettings, nil
}
func saveUserSettings(path string, settings VSCodeSettings, fsys afero.Fs) error {
// Open our jsonFile
jsonFile, err := fsys.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return errors.Errorf("failed to create settings file: %w", err)
}
defer jsonFile.Close()
// Marshal JSON to file.
enc := json.NewEncoder(jsonFile)
enc.SetIndent("", " ")
if err := enc.Encode(settings); err != nil {
return errors.Errorf("failed to save settings: %w", err)
}
return nil
}
func updateJsonFile(path string, template string, fsys afero.Fs) error {
userSettings, err := loadUserSettings(path, fsys)
if errors.Is(err, os.ErrNotExist) || errors.Is(err, io.EOF) {
return afero.WriteFile(fsys, path, []byte(template), 0644)
} else if err != nil {
return err
}
// Merge template into user settings.
if err := json.Unmarshal([]byte(template), &userSettings); err != nil {
return errors.Errorf("failed to copy template: %w", err)
}
return saveUserSettings(path, userSettings, fsys)
}
func writeVscodeConfig(fsys afero.Fs) error {
// Create VS Code settings for Deno.
if err := utils.MkdirIfNotExistFS(fsys, vscodeDir); err != nil {
return err
}
if err := updateJsonFile(extensionsPath, vscodeExtensions, fsys); err != nil {
return err
}
if err := updateJsonFile(settingsPath, vscodeSettings, fsys); err != nil {
return err
}
fmt.Println("Generated VS Code settings in " + utils.Bold(settingsPath) + ". Please install the recommended extension!")
return nil
}
func writeIntelliJConfig(fsys afero.Fs) error {
if err := utils.WriteFile(denoPath, []byte(intelliJDeno), fsys); err != nil {
return err
}
fmt.Println("Generated IntelliJ settings in " + utils.Bold(denoPath) + ". Please install the Deno plugin!")
return nil
}