mirror of
https://github.com/sbrow/envr.git
synced 2025-12-29 23:47:39 -05:00
Compare commits
4 Commits
5eaf691dcd
...
06e0d8067c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06e0d8067c | ||
| 4db0a4d33d | |||
| 638751fb48 | |||
| 39dc586d3c |
31
CHANGELOG.md
31
CHANGELOG.md
@@ -1,5 +1,36 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.2.0](https://github.com/sbrow/envr/compare/v0.1.1...v0.2.0) (2025-11-10)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* Dir is now derived from Path rather than stored in the DB. Your DB will need to be updated.
|
||||||
|
* **scan:** The config value `scan.Exclude` is now a list rather than a string.
|
||||||
|
* **check:** Renamed the `check` command to `deps`.
|
||||||
|
* The config value `scan.Include` is now a list rather than a string.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Added new `check` command. ([cbd74f3](https://github.com/sbrow/envr/commit/cbd74f387e2e330b2557d07dd82ba05cc91300ac))
|
||||||
|
* **config:** The default config now filters out more junk. ([15be62b](https://github.com/sbrow/envr/commit/15be62b5a2a5a735b90b074497d645c5a2cfced8))
|
||||||
|
* **init:** Added a `--force` flag for overwriting an existing config. ([169653d](https://github.com/sbrow/envr/commit/169653d7566f63730fb9da80a18330a566223be9))
|
||||||
|
* Multiple scan includes are now supported. ([4273fa5](https://github.com/sbrow/envr/commit/4273fa58956d8736271a0af66202dca481126fe4))
|
||||||
|
* **scan:** Added support for multiple exports. ([f43705c](https://github.com/sbrow/envr/commit/f43705cd53c6d87aef1f69df4e474441f25c1dc7))
|
||||||
|
* **sync:** envr can now detect if directories have moved. ([4db0a4d](https://github.com/sbrow/envr/commit/4db0a4d33d2b6a79d13b36a8e8631f895e8fef8d))
|
||||||
|
* **sync:** Now checks files for mismatched hashes before replacing. ([8074f7a](https://github.com/sbrow/envr/commit/8074f7ae6dfa54e931a198257f3f8e6d0cfe353a))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **check:** `fd` now correctly gets marked as found. ([17ce49c](https://github.com/sbrow/envr/commit/17ce49cd2d33942282c6f54ce819ac25978f6b7c))
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* **check:** Renamed the `check` command to `deps`. ([c9c34ce](https://github.com/sbrow/envr/commit/c9c34ce771653da214635f1df1fef1f23265c552))
|
||||||
|
* Dir is no longer stored in the database. ([0fef74a](https://github.com/sbrow/envr/commit/0fef74a9bba0fbf3c34b66c2095955e6eee7047b))
|
||||||
|
|
||||||
## [0.1.1](https://github.com/sbrow/envr/compare/v0.1.0...v0.1.1) (2025-11-05)
|
## [0.1.1](https://github.com/sbrow/envr/compare/v0.1.0...v0.1.1) (2025-11-05)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ be run on a cron.
|
|||||||
- 🔍 **Smart Scanning**: Automatically discover and import `.env` files in your
|
- 🔍 **Smart Scanning**: Automatically discover and import `.env` files in your
|
||||||
home directory.
|
home directory.
|
||||||
- ✨ **Interactive CLI**: User-friendly prompts for file selection and management.
|
- ✨ **Interactive CLI**: User-friendly prompts for file selection and management.
|
||||||
|
- 🗂️ **Rename Detection**: Automatically finds and updates renamed/moved
|
||||||
|
repositories.
|
||||||
|
|
||||||
## TODOS
|
## TODOS
|
||||||
|
- [x] Rename Detection: automatically update moved files.
|
||||||
- [ ] 🗂️ **Rename Detection**: Automatically handle renamed repositories.
|
|
||||||
- [ ] Allow use of keys from `ssh-agent`
|
- [ ] Allow use of keys from `ssh-agent`
|
||||||
- [x] Allow configuration of ssh key.
|
- [x] Allow configuration of ssh key.
|
||||||
- [x] Allow multiple ssh keys.
|
- [x] Allow multiple ssh keys.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -235,3 +236,32 @@ func (s SshKeyPair) recipient() (age.Recipient, error) {
|
|||||||
|
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use fd to find all git roots in the config's search paths
|
||||||
|
func (c Config) findGitRoots() (paths []string, err error) {
|
||||||
|
searchPaths, err := c.searchPaths()
|
||||||
|
if err != nil {
|
||||||
|
return []string{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, searchPath := range searchPaths {
|
||||||
|
allCmd := exec.Command("fd", "-H", "-t", "d", "^\\.git$", searchPath)
|
||||||
|
allOutput, err := allCmd.Output()
|
||||||
|
if err != nil {
|
||||||
|
return paths, err
|
||||||
|
}
|
||||||
|
|
||||||
|
allFiles := strings.Split(strings.TrimSpace(string(allOutput)), "\n")
|
||||||
|
if len(allFiles) == 1 && allFiles[0] == "" {
|
||||||
|
allFiles = []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, file := range allFiles {
|
||||||
|
allFiles[i] = path.Dir(path.Clean(file))
|
||||||
|
}
|
||||||
|
|
||||||
|
paths = append(paths, allFiles...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths, nil
|
||||||
|
}
|
||||||
|
|||||||
35
app/db.go
35
app/db.go
@@ -1,5 +1,6 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
|
// TODO: app/db.go should be reviewed.
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -149,9 +150,9 @@ func (db *Db) List() (results []EnvFile, err error) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
var envFile EnvFile
|
var envFile EnvFile
|
||||||
var remotesJson []byte
|
var remotesJson []byte
|
||||||
for rows.Next() {
|
|
||||||
err := rows.Scan(&envFile.Path, &remotesJson, &envFile.Sha256, &envFile.contents)
|
err := rows.Scan(&envFile.Path, &remotesJson, &envFile.Sha256, &envFile.contents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -386,3 +387,35 @@ func (db *Db) CanScan() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If true, [Db.Insert] should be called on the [EnvFile] that generated
|
||||||
|
// the given result
|
||||||
|
func (db Db) UpdateRequired(status EnvFileSyncResult) bool {
|
||||||
|
return status&(BackedUp|DirUpdated) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *Db) Sync(file *EnvFile) (result EnvFileSyncResult, err error) {
|
||||||
|
// TODO: This results in findMovedDirs being called multiple times.
|
||||||
|
return file.sync(TrustFilesystem, db)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Looks for git directories that share one or more git remotes with
|
||||||
|
// the given file.
|
||||||
|
func (db Db) findMovedDirs(file *EnvFile) (movedDirs []string, err error) {
|
||||||
|
if err = db.Features().validateFeatures(Fd, Git); err != nil {
|
||||||
|
return movedDirs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
gitRoots, err := db.cfg.findGitRoots()
|
||||||
|
if err != nil {
|
||||||
|
return movedDirs, err
|
||||||
|
} else {
|
||||||
|
for _, dir := range gitRoots {
|
||||||
|
if file.sharesRemote(getGitRemotes(dir)) {
|
||||||
|
movedDirs = append(movedDirs, dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return movedDirs, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
176
app/env_file.go
176
app/env_file.go
@@ -2,14 +2,17 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EnvFile struct {
|
type EnvFile struct {
|
||||||
|
// TODO: Should use FileName in the struct and derive from the path.
|
||||||
Path string
|
Path string
|
||||||
// Dir is derived from Path, and is not stored in the database.
|
// Dir is derived from Path, and is not stored in the database.
|
||||||
Dir string
|
Dir string
|
||||||
@@ -22,16 +25,30 @@ type EnvFile struct {
|
|||||||
type EnvFileSyncResult int
|
type EnvFileSyncResult int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// The struct has been updated from the filesystem
|
|
||||||
// and should be updated in the database.
|
|
||||||
Updated EnvFileSyncResult = iota
|
|
||||||
// The filesystem has been restored to match the struct
|
|
||||||
// no further action is required.
|
|
||||||
Restored
|
|
||||||
Error
|
|
||||||
// The filesystem contents matches the struct
|
// The filesystem contents matches the struct
|
||||||
// no further action is required.
|
// no further action is required.
|
||||||
Noop
|
Noop EnvFileSyncResult = 0
|
||||||
|
// The directory changed, but the file contents matched.
|
||||||
|
// The database must be updated.
|
||||||
|
DirUpdated EnvFileSyncResult = 1
|
||||||
|
// The filesystem has been restored to match the struct
|
||||||
|
// no further action is required.
|
||||||
|
Restored EnvFileSyncResult = 1 << 1
|
||||||
|
// The filesystem has been restored to match the struct.
|
||||||
|
// The directory changed, so the database must be updated
|
||||||
|
RestoredAndDirUpdated EnvFileSyncResult = Restored | DirUpdated
|
||||||
|
// The struct has been updated from the filesystem
|
||||||
|
// and should be updated in the database.
|
||||||
|
BackedUp EnvFileSyncResult = 1 << 2
|
||||||
|
Error EnvFileSyncResult = 1 << 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Determines the source of truth when calling [EnvFile.Sync] or [EnvFile.Restore]
|
||||||
|
type syncDirection int
|
||||||
|
|
||||||
|
const (
|
||||||
|
TrustDatabase syncDirection = iota
|
||||||
|
TrustFilesystem
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewEnvFile(path string) EnvFile {
|
func NewEnvFile(path string) EnvFile {
|
||||||
@@ -96,81 +113,116 @@ func getGitRemotes(dir string) []string {
|
|||||||
return remotes
|
return remotes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install the file into the file system. If the file already exists,
|
// Reconcile the state of the database with the state of the filesystem, using
|
||||||
// it will be overwritten.
|
// dir to determine which side to use a the source of truth.
|
||||||
func (file EnvFile) Restore() error {
|
func (f *EnvFile) sync(dir syncDirection, db *Db) (result EnvFileSyncResult, err error) {
|
||||||
// TODO: Duplicate work is being done when called from the Sync function.
|
if result != Noop {
|
||||||
if _, err := os.Stat(file.Path); err == nil {
|
panic("Invalid state")
|
||||||
// file already exists
|
}
|
||||||
|
|
||||||
// Read existing file and calculate its hash
|
if _, err := os.Stat(f.Dir); err != nil {
|
||||||
existingContents, err := os.ReadFile(file.Path)
|
// Directory doesn't exist
|
||||||
|
|
||||||
|
var movedDirs []string
|
||||||
|
|
||||||
|
if db != nil {
|
||||||
|
movedDirs, err = db.findMovedDirs(f)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to read existing file for hash comparison: %w", err)
|
return Error, err
|
||||||
}
|
|
||||||
|
|
||||||
hash := sha256.Sum256(existingContents)
|
|
||||||
existingSha := fmt.Sprintf("%x", hash)
|
|
||||||
|
|
||||||
if existingSha == file.Sha256 {
|
|
||||||
return fmt.Errorf("file already exists: %s", file.Path)
|
|
||||||
} else {
|
} else {
|
||||||
if err := os.WriteFile(file.Path, []byte(file.contents), 0644); err != nil {
|
switch len(movedDirs) {
|
||||||
return fmt.Errorf("failed to write file: %w", err)
|
case 0:
|
||||||
|
return Error, fmt.Errorf("directory missing")
|
||||||
|
case 1:
|
||||||
|
f.updateDir(movedDirs[0])
|
||||||
|
result |= DirUpdated
|
||||||
|
default:
|
||||||
|
return Error, fmt.Errorf("multiple directories found")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if _, err := os.Stat(f.Path); err != nil {
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
if err := os.WriteFile(f.Path, []byte(f.contents), 0644); err != nil {
|
||||||
|
return Error, fmt.Errorf("failed to write file: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result | Restored, nil
|
||||||
|
} else {
|
||||||
|
return Error, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// file doesn't exist
|
// File exists, check its hash
|
||||||
|
contents, err := os.ReadFile(f.Path)
|
||||||
// Ensure the directory exists
|
if err != nil {
|
||||||
if _, err := os.Stat(file.Dir); err != nil {
|
return Error, fmt.Errorf("failed to read file for SHA comparison: %w", err)
|
||||||
return fmt.Errorf("directory missing")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the contents to the file
|
hash := sha256.Sum256(contents)
|
||||||
if err := os.WriteFile(file.Path, []byte(file.contents), 0644); err != nil {
|
currentSha := fmt.Sprintf("%x", hash)
|
||||||
return fmt.Errorf("failed to write file: %w", err)
|
|
||||||
|
// Compare the hashes
|
||||||
|
if currentSha == f.Sha256 {
|
||||||
|
// No op, or DirUpdated
|
||||||
|
return result, nil
|
||||||
|
} else {
|
||||||
|
switch dir {
|
||||||
|
case TrustDatabase:
|
||||||
|
if err := os.WriteFile(f.Path, []byte(f.contents), 0644); err != nil {
|
||||||
|
return Error, fmt.Errorf("failed to write file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return result | Restored, nil
|
||||||
|
case TrustFilesystem:
|
||||||
|
// Overwrite the database
|
||||||
|
if err = f.Backup(); err != nil {
|
||||||
|
return Error, err
|
||||||
|
} else {
|
||||||
|
return BackedUp, nil
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unknown sync direction")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *EnvFile) sharesRemote(remotes []string) bool {
|
||||||
|
rMap := make(map[string]bool)
|
||||||
|
for _, remote := range f.Remotes {
|
||||||
|
rMap[remote] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, remote := range remotes {
|
||||||
|
if rMap[remote] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *EnvFile) updateDir(newDir string) {
|
||||||
|
f.Dir = newDir
|
||||||
|
f.Path = path.Join(newDir, path.Base(f.Path))
|
||||||
|
f.Remotes = getGitRemotes(newDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to reconcile the EnvFile with the filesystem.
|
// Try to reconcile the EnvFile with the filesystem.
|
||||||
//
|
//
|
||||||
// If Updated is returned, [Db.Insert] should be called on file.
|
// If Updated is returned, [Db.Insert] should be called on file.
|
||||||
func (file *EnvFile) Sync() (result EnvFileSyncResult, err error) {
|
func (file *EnvFile) Sync() (result EnvFileSyncResult, err error) {
|
||||||
// Check if the path exists in the file system
|
return file.sync(TrustFilesystem, nil)
|
||||||
_, err = os.Stat(file.Path)
|
|
||||||
if err == nil {
|
|
||||||
contents, err := os.ReadFile(file.Path)
|
|
||||||
if err != nil {
|
|
||||||
return Error, fmt.Errorf("failed to read file for SHA comparison: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if sha matches by reading the current file and calculating its hash
|
// Install the file into the file system. If the file already exists,
|
||||||
hash := sha256.Sum256(contents)
|
// it will be overwritten.
|
||||||
currentSha := fmt.Sprintf("%x", hash)
|
func (file EnvFile) Restore() error {
|
||||||
if file.Sha256 == currentSha {
|
_, err := file.sync(TrustDatabase, nil)
|
||||||
// Nothing to do
|
|
||||||
return Noop, nil
|
return err
|
||||||
} else {
|
|
||||||
if err = file.Backup(); err != nil {
|
|
||||||
return Error, err
|
|
||||||
} else {
|
|
||||||
return Updated, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err = file.Restore(); err != nil {
|
|
||||||
return Error, err
|
|
||||||
} else {
|
|
||||||
return Restored, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the EnvFile using the file system.
|
// Update the EnvFile using the file system.
|
||||||
|
|||||||
@@ -1,9 +1,20 @@
|
|||||||
package app
|
package app
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type MissingFeatureError struct {
|
||||||
|
feature AvailableFeatures
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MissingFeatureError) Error() string {
|
||||||
|
return fmt.Sprintf("Missing \"%s\" feature", m.feature)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Features should really be renamed to Binaries
|
||||||
|
|
||||||
// Represents which binaries are present in $PATH.
|
// Represents which binaries are present in $PATH.
|
||||||
// Used to fail safely when required features are unavailable
|
// Used to fail safely when required features are unavailable
|
||||||
type AvailableFeatures int
|
type AvailableFeatures int
|
||||||
@@ -30,3 +41,20 @@ func checkFeatures() (feats AvailableFeatures) {
|
|||||||
|
|
||||||
return feats
|
return feats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a MissingFeature error if the given features aren't present.
|
||||||
|
func (a AvailableFeatures) validateFeatures(features ...AvailableFeatures) error {
|
||||||
|
var missing AvailableFeatures
|
||||||
|
|
||||||
|
for _, feat := range features {
|
||||||
|
if a&feat == 0 {
|
||||||
|
missing |= feat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if missing == 0 {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return &MissingFeatureError{missing}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ var backupCmd = &cobra.Command{
|
|||||||
record := app.NewEnvFile(path)
|
record := app.NewEnvFile(path)
|
||||||
|
|
||||||
if err := db.Insert(record); err != nil {
|
if err := db.Insert(record); err != nil {
|
||||||
panic(err)
|
return err
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("Saved %s into the database", path)
|
fmt.Printf("Saved %s into the database", path)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
22
cmd/sync.go
22
cmd/sync.go
@@ -10,12 +10,12 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: Detect when file paths have moved and update accordingly.
|
|
||||||
var syncCmd = &cobra.Command{
|
var syncCmd = &cobra.Command{
|
||||||
Use: "sync",
|
Use: "sync",
|
||||||
Short: "Update or restore your env backups",
|
Short: "Update or restore your env backups",
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
db, err := app.Open()
|
db, err := app.Open()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
@@ -33,16 +33,19 @@ var syncCmd = &cobra.Command{
|
|||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
// Syncronize the filesystem with the database.
|
// Syncronize the filesystem with the database.
|
||||||
changed, err := file.Sync()
|
oldPath := file.Path
|
||||||
|
changed, err := db.Sync(&file)
|
||||||
|
|
||||||
var status string
|
var status string
|
||||||
switch changed {
|
switch changed {
|
||||||
case app.Updated:
|
case app.BackedUp:
|
||||||
status = "Backed Up"
|
status = "Backed Up"
|
||||||
if err := db.Insert(file); err != nil {
|
if err := db.Insert(file); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case app.Restored:
|
case app.Restored:
|
||||||
|
fallthrough
|
||||||
|
case app.RestoredAndDirUpdated:
|
||||||
status = "Restored"
|
status = "Restored"
|
||||||
case app.Error:
|
case app.Error:
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@@ -51,10 +54,23 @@ var syncCmd = &cobra.Command{
|
|||||||
status = err.Error()
|
status = err.Error()
|
||||||
case app.Noop:
|
case app.Noop:
|
||||||
status = "OK"
|
status = "OK"
|
||||||
|
case app.DirUpdated:
|
||||||
|
status = "Moved"
|
||||||
default:
|
default:
|
||||||
panic("Unknown result")
|
panic("Unknown result")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if changed&app.DirUpdated == app.DirUpdated {
|
||||||
|
if err := db.Delete(oldPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if db.UpdateRequired(changed) {
|
||||||
|
if err := db.Insert(file); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
results = append(results, syncResult{
|
results = append(results, syncResult{
|
||||||
Path: file.Path,
|
Path: file.Path,
|
||||||
Status: status,
|
Status: status,
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
packages.default = pkgs.buildGoModule rec {
|
packages.default = pkgs.buildGoModule rec {
|
||||||
pname = "envr";
|
pname = "envr";
|
||||||
version = "0.1.1";
|
version = "0.2.0";
|
||||||
src = ./.;
|
src = ./.;
|
||||||
# If the build complains, uncomment this line
|
# If the build complains, uncomment this line
|
||||||
# vendorHash = "sha256:0000000000000000000000000000000000000000000000000000";
|
# vendorHash = "sha256:0000000000000000000000000000000000000000000000000000";
|
||||||
|
|||||||
Reference in New Issue
Block a user