Skip to content

Commit

Permalink
feat: added lazy sync functionality to only do a sync, if the config …
Browse files Browse the repository at this point in the history
…has changed since the last sync. Added extra field to lock file in order to keep track of config changes.
  • Loading branch information
Fritz Durchardt committed Aug 7, 2023
1 parent bc7a968 commit edd9918
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 4 deletions.
50 changes: 47 additions & 3 deletions pkg/vendir/cmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
package cmd

import (
"crypto/sha256"
"encoding/hex"
"fmt"
"gopkg.in/yaml.v3"
"os"
"path/filepath"
"strings"
Expand All @@ -30,6 +33,7 @@ type SyncOptions struct {

Directories []string
Locked bool
Lazy bool

Chdir string
AllowAllSymlinkDestinations bool
Expand All @@ -50,13 +54,45 @@ func NewSyncCmd(o *SyncOptions) *cobra.Command {

cmd.Flags().StringSliceVarP(&o.Directories, "directory", "d", nil, "Sync specific directory (format: dir/sub-dir[=local-dir])")
cmd.Flags().BoolVarP(&o.Locked, "locked", "l", false, "Consult lock file to pull exact references (e.g. use git sha instead of branch name)")
cmd.Flags().BoolVar(&o.Lazy, "lazy", false, "Only fetch remote if vendir.yaml diverges from lock file")

cmd.Flags().StringVar(&o.Chdir, "chdir", "", "Set current directory for process")
cmd.Flags().BoolVar(&o.AllowAllSymlinkDestinations, "dangerous-allow-all-symlink-destinations", false, "Symlinks to all destinations are allowed")

return cmd
}

func configUnchanged(vendirConfig ctlconf.Config, lockConfig ctlconf.LockConfig) bool {
for _, dir := range vendirConfig.Directories {
for _, content := range dir.Contents {
if !matchesLockConfig(dir.Path, content, lockConfig) {
return false
}
}
}
return true
}

func matchesLockConfig(dir string, content ctlconf.DirectoryContents, lockConfig ctlconf.LockConfig) bool {
for _, lockDir := range lockConfig.Directories {
for _, lockContent := range lockDir.Contents {
if lockDir.Path == dir && lockContent.Path == content.Path {
yaml, err := yaml.Marshal(content)
if err != nil {
return false
}
hash := sha256.Sum256(yaml)
hashStr := hex.EncodeToString(hash[:])

if hashStr == lockContent.Hash {
return true
}
}
}
}
return false
}

func (o *SyncOptions) Run() error {
if len(o.Chdir) > 0 {
err := os.Chdir(o.Chdir)
Expand Down Expand Up @@ -95,13 +131,21 @@ func (o *SyncOptions) Run() error {
o.ui.PrintBlock(configBs)
}

// If syncing against a lock file, apply lock information
// on top of existing config
if o.Locked {
if o.Lazy && ctlconf.LockFileExists(o.LockFile) {
existingLockConfig, err := ctlconf.NewLockConfigFromFile(o.LockFile)
if err != nil {
return err
}
if configUnchanged(conf, existingLockConfig) {
o.ui.PrintLinef("No changes in vendir.yaml since last sync. No need to sync.")
return nil
}
}

// If syncing against a lock file, apply lock information
// on top of existing config
if o.Locked {
existingLockConfig, err := ctlconf.NewLockConfigFromFile(o.LockFile)

err = conf.Lock(existingLockConfig)
if err != nil {
Expand Down
7 changes: 7 additions & 0 deletions pkg/vendir/config/lock_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ func NewLockConfig() LockConfig {
}
}

func LockFileExists(path string) bool {
if _, err := os.Stat(path); err != nil {
return false
}
return true
}

func NewLockConfigFromFile(path string) (LockConfig, error) {
bs, err := os.ReadFile(path)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/vendir/config/lock_directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type LockDirectory struct {

type LockDirectoryContents struct {
Path string `json:"path"`
Hash string `json:"hash"`

Git *LockDirectoryContentsGit `json:"git,omitempty"`
Hg *LockDirectoryContentsHg `json:"hg,omitempty"`
Expand Down
15 changes: 14 additions & 1 deletion pkg/vendir/directory/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
package directory

import (
"crypto/sha256"
"encoding/hex"
"fmt"
"gopkg.in/yaml.v3"
"os"
"path/filepath"

Expand Down Expand Up @@ -57,7 +60,17 @@ func (d *Directory) Sync(syncOpts SyncOpts) (ctlconf.LockDirectory, error) {
return lockConfig, err
}

lockDirContents := ctlconf.LockDirectoryContents{Path: contents.Path}
yaml, err := yaml.Marshal(contents)
if err != nil {
return lockConfig, err
}
hash := sha256.Sum256(yaml)
hashStr := hex.EncodeToString(hash[:])

lockDirContents := ctlconf.LockDirectoryContents{
Path: contents.Path,
Hash: hashStr,
}

skipFileFilter := false
skipNewRootPath := false
Expand Down

0 comments on commit edd9918

Please sign in to comment.