@@ -27,34 +27,115 @@ func runSetup(args []string, stdout io.Writer) error {
2727 if apiURL == "" || apiKey == "" {
2828 return fmt .Errorf ("server and key are required (use --server/--key or STINT_API_URL/STINT_API_KEY)" )
2929 }
30- if err := writeSetupConfig (* stintConfig , apiURL , apiKey , true ); err != nil {
31- return fmt .Errorf ("write stint config: %w" , err )
30+ stintWrite , err := prepareSetupConfig (* stintConfig , apiURL , apiKey , true )
31+ if err != nil {
32+ return fmt .Errorf ("prepare stint config: %w" , err )
3233 }
33- if err := writeSetupConfig (* wakaConfig , apiURL , apiKey , false ); err != nil {
34- return fmt .Errorf ("write wakatime config: %w" , err )
34+ defer stintWrite .cleanup ()
35+ wakaWrite , err := prepareSetupConfig (* wakaConfig , apiURL , apiKey , false )
36+ if err != nil {
37+ return fmt .Errorf ("prepare wakatime config: %w" , err )
38+ }
39+ defer wakaWrite .cleanup ()
40+ if err := commitSetupConfigs (stintWrite , wakaWrite ); err != nil {
41+ return err
3542 }
3643 fmt .Fprintf (stdout , "wrote %s and %s\n " , expandHome (* stintConfig ), expandHome (* wakaConfig ))
3744 return nil
3845}
3946
4047func writeSetupConfig (path , apiURL , apiKey string , native bool ) error {
48+ write , err := prepareSetupConfig (path , apiURL , apiKey , native )
49+ if err != nil {
50+ return err
51+ }
52+ defer write .cleanup ()
53+ return write .commit ()
54+ }
55+
56+ type preparedSetupConfig struct {
57+ path string
58+ tmpPath string
59+ oldBytes []byte
60+ hadOld bool
61+ committed bool
62+ }
63+
64+ func prepareSetupConfig (path , apiURL , apiKey string , native bool ) (preparedSetupConfig , error ) {
4165 path = expandHome (path )
4266 if err := os .MkdirAll (filepath .Dir (path ), 0o755 ); err != nil {
43- return err
67+ return preparedSetupConfig {}, err
4468 }
4569 cfg , err := LoadConfig (path )
4670 if err != nil {
47- return err
71+ return preparedSetupConfig {}, err
4872 }
4973 cfg .Set ("settings" , "api_url" , apiURL )
5074 cfg .Set ("settings" , "api_key" , apiKey )
5175 if native {
5276 cfg .Set ("settings" , "offline" , "true" )
5377 }
54- return cfg .Write (path )
78+ prepared := preparedSetupConfig {path : path }
79+ if oldBytes , err := os .ReadFile (path ); err == nil {
80+ prepared .oldBytes = oldBytes
81+ prepared .hadOld = true
82+ } else if ! os .IsNotExist (err ) {
83+ return preparedSetupConfig {}, err
84+ }
85+ tmp , err := os .CreateTemp (filepath .Dir (path ), filepath .Base (path )+ ".tmp-*" )
86+ if err != nil {
87+ return preparedSetupConfig {}, err
88+ }
89+ prepared .tmpPath = tmp .Name ()
90+ if err := tmp .Close (); err != nil {
91+ prepared .cleanup ()
92+ return preparedSetupConfig {}, err
93+ }
94+ if err := cfg .Write (prepared .tmpPath ); err != nil {
95+ prepared .cleanup ()
96+ return preparedSetupConfig {}, err
97+ }
98+ return prepared , nil
99+ }
100+
101+ func commitSetupConfigs (configs ... preparedSetupConfig ) error {
102+ var committed []preparedSetupConfig
103+ for _ , config := range configs {
104+ if err := config .commit (); err != nil {
105+ for i := len (committed ) - 1 ; i >= 0 ; i -- {
106+ _ = committed [i ].restore ()
107+ }
108+ return err
109+ }
110+ committed = append (committed , config )
111+ }
112+ return nil
113+ }
114+
115+ func (p * preparedSetupConfig ) commit () error {
116+ if err := os .Rename (p .tmpPath , p .path ); err != nil {
117+ return err
118+ }
119+ p .committed = true
120+ return nil
121+ }
122+
123+ func (p preparedSetupConfig ) restore () error {
124+ if p .hadOld {
125+ return os .WriteFile (p .path , p .oldBytes , 0o600 )
126+ }
127+ if err := os .Remove (p .path ); err != nil && ! os .IsNotExist (err ) {
128+ return err
129+ }
130+ return nil
131+ }
132+
133+ func (p preparedSetupConfig ) cleanup () {
134+ if ! p .committed && p .tmpPath != "" {
135+ _ = os .Remove (p .tmpPath )
136+ }
55137}
56138
57- func loadNativeConfig () Config {
58- cfg , _ := LoadConfig (DefaultStintConfigPath ())
59- return cfg
139+ func loadNativeConfig () (Config , error ) {
140+ return LoadConfig (DefaultStintConfigPath ())
60141}
0 commit comments