Skip to content

Commit 638751f

Browse files
Spencer Browersbrow
authored andcommitted
refactor: Restore and Sync now share code through the sync function.
1 parent 39dc586 commit 638751f

File tree

2 files changed

+65
-64
lines changed

2 files changed

+65
-64
lines changed

app/env_file.go

Lines changed: 64 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package app
22

33
import (
44
"crypto/sha256"
5+
"errors"
56
"fmt"
67
"os"
78
"os/exec"
@@ -24,7 +25,7 @@ type EnvFileSyncResult int
2425
const (
2526
// The struct has been updated from the filesystem
2627
// and should be updated in the database.
27-
Updated EnvFileSyncResult = iota
28+
BackedUp EnvFileSyncResult = iota
2829
// The filesystem has been restored to match the struct
2930
// no further action is required.
3031
Restored
@@ -34,6 +35,13 @@ const (
3435
Noop
3536
)
3637

38+
type syncDirection int
39+
40+
const (
41+
TrustDatabase syncDirection = iota
42+
TrustFilesystem
43+
)
44+
3745
func NewEnvFile(path string) EnvFile {
3846
// Get absolute path and directory
3947
absPath, err := filepath.Abs(path)
@@ -96,85 +104,78 @@ func getGitRemotes(dir string) []string {
96104
return remotes
97105
}
98106

99-
// Try to reconcile the EnvFile with the filesystem.
100-
//
101-
// If Updated is returned, [Db.Insert] should be called on file.
102-
func (file *EnvFile) Sync() (result EnvFileSyncResult, err error) {
103-
// TODO: If the directory doesn't exist, look for other directories with the same remote(s)
104-
// TODO: If one is found, update file.Dir and File.Path
105-
// TODO: If nothing if found, return an error
106-
// TODO: If more than one is found, return a different error
107-
108-
// Check if the path exists in the file system
109-
_, err = os.Stat(file.Path)
110-
if err == nil {
111-
contents, err := os.ReadFile(file.Path)
107+
// Reconcile the state of the database with the state of the filesystem, using
108+
// dir to determine which side to use a the source of truth
109+
func (f *EnvFile) sync(dir syncDirection) (result EnvFileSyncResult, err error) {
110+
// How Sync should work
111+
//
112+
// If the directory doesn't exist, look for other directories with the same remote(s)
113+
// -> If one is found, update file.Dir and File.Path, then continue with "changed" flag
114+
// -> If multiple are found, return an error
115+
// -> If none are found, return a different error
116+
117+
// Ensure the directory exists
118+
if _, err := os.Stat(f.Dir); err != nil {
119+
return Error, fmt.Errorf("directory missing")
120+
}
121+
122+
if _, err := os.Stat(f.Path); err != nil {
123+
if errors.Is(err, os.ErrNotExist) {
124+
if err := os.WriteFile(f.Path, []byte(f.contents), 0644); err != nil {
125+
return Error, fmt.Errorf("failed to write file: %w", err)
126+
}
127+
128+
return Restored, err
129+
} else {
130+
return Error, err
131+
}
132+
} else {
133+
// File exists, check its hash
134+
contents, err := os.ReadFile(f.Path)
112135
if err != nil {
113136
return Error, fmt.Errorf("failed to read file for SHA comparison: %w", err)
114137
}
115138

116-
// Check if sha matches by reading the current file and calculating its hash
117139
hash := sha256.Sum256(contents)
118140
currentSha := fmt.Sprintf("%x", hash)
119-
if file.Sha256 == currentSha {
120-
// Nothing to do
141+
142+
// Compare the hashes
143+
if currentSha == f.Sha256 {
121144
return Noop, nil
122145
} else {
123-
if err = file.Backup(); err != nil {
124-
return Error, err
125-
} else {
126-
return Updated, nil
146+
switch dir {
147+
case TrustDatabase:
148+
if err := os.WriteFile(f.Path, []byte(f.contents), 0644); err != nil {
149+
return Error, fmt.Errorf("failed to write file: %w", err)
150+
}
151+
return Restored, nil
152+
case TrustFilesystem:
153+
// Overwrite the database
154+
if err = f.Backup(); err != nil {
155+
return Error, err
156+
} else {
157+
return BackedUp, nil
158+
}
159+
default:
160+
panic("unknown sync direction")
127161
}
128162
}
129-
} else {
130-
if err = file.Restore(); err != nil {
131-
return Error, err
132-
} else {
133-
return Restored, nil
134-
}
135163
}
136164
}
137165

166+
// Try to reconcile the EnvFile with the filesystem.
167+
//
168+
// If Updated is returned, [Db.Insert] should be called on file.
169+
func (file *EnvFile) Sync() (result EnvFileSyncResult, err error) {
170+
return file.sync(TrustFilesystem)
171+
}
172+
138173
// Install the file into the file system. If the file already exists,
139174
// it will be overwritten.
140175
func (file EnvFile) Restore() error {
141-
// TODO: Duplicate work is being done when called from the Sync function.
142-
if _, err := os.Stat(file.Path); err == nil {
143-
// file already exists
176+
_, err := file.sync(TrustDatabase)
144177

145-
// Read existing file and calculate its hash
146-
existingContents, err := os.ReadFile(file.Path)
147-
if err != nil {
148-
return fmt.Errorf("failed to read existing file for hash comparison: %w", err)
149-
}
150-
151-
hash := sha256.Sum256(existingContents)
152-
existingSha := fmt.Sprintf("%x", hash)
153-
154-
if existingSha == file.Sha256 {
155-
return fmt.Errorf("file already exists: %s", file.Path)
156-
} else {
157-
if err := os.WriteFile(file.Path, []byte(file.contents), 0644); err != nil {
158-
return fmt.Errorf("failed to write file: %w", err)
159-
}
160-
161-
return nil
162-
}
163-
} else {
164-
// file doesn't exist
165-
166-
// Ensure the directory exists
167-
if _, err := os.Stat(file.Dir); err != nil {
168-
return fmt.Errorf("directory missing")
169-
}
170-
171-
// Write the contents to the file
172-
if err := os.WriteFile(file.Path, []byte(file.contents), 0644); err != nil {
173-
return fmt.Errorf("failed to write file: %w", err)
174-
}
175-
176-
return nil
177-
}
178+
return err
178179
}
179180

180181
// Update the EnvFile using the file system.

cmd/sync.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var syncCmd = &cobra.Command{
3636

3737
var status string
3838
switch changed {
39-
case app.Updated:
39+
case app.BackedUp:
4040
status = "Backed Up"
4141
if err := db.Insert(file); err != nil {
4242
return err

0 commit comments

Comments
 (0)