From f56cdd8afe138e20dd4eba7dc5c53d1b19f218c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8E=B3=20Bo=20HOU?= Date: Tue, 31 Dec 2024 12:40:32 +0100 Subject: [PATCH] Enable sync policy for extra remotes --- cmd/update.go | 1 + internal/backend/package-source.go | 3 +- internal/updater/cmd-updater.go | 77 ++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/cmd/update.go b/cmd/update.go index 7358f3b..9d583a8 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -76,6 +76,7 @@ Check the update of %s and its commands. Timeout: updateFlags.Timeout, EnableCI: enableCI, PackageLockFile: packageLockFile, + SyncPolicy: "always", // TODO: use constant instead of string } cmdUpdater.CheckUpdateAsync() err := cmdUpdater.Update() diff --git a/internal/backend/package-source.go b/internal/backend/package-source.go index d55b86f..119b33e 100644 --- a/internal/backend/package-source.go +++ b/internal/backend/package-source.go @@ -54,7 +54,7 @@ func NewManagedSource(name, repoDir, remoteBaseURL string, syncPolicy string) *P RemoteBaseURL: remoteBaseURL, RemoteRegistryURL: fmt.Sprintf("%s/index.json", remoteBaseURL), IsManaged: true, - SyncPolicy: SYNC_POLICY_ALWAYS, + SyncPolicy: syncPolicy, } } @@ -71,6 +71,7 @@ func (src *PackageSource) InitUpdater(user *user.User, timeout time.Duration, en PackageLockFile: lockFile, VerifyChecksum: verifyChecksum, VerifySignature: verifySignature, + SyncPolicy: src.SyncPolicy, } return src.Updater } diff --git a/internal/updater/cmd-updater.go b/internal/updater/cmd-updater.go index d08fea5..b39f7b0 100644 --- a/internal/updater/cmd-updater.go +++ b/internal/updater/cmd-updater.go @@ -2,7 +2,10 @@ package updater import ( "encoding/json" + "errors" "fmt" + "os" + "path" "sync" "time" @@ -34,6 +37,7 @@ type CmdUpdater struct { PackageLockFile string VerifyChecksum bool VerifySignature bool + SyncPolicy string } func (u *CmdUpdater) CheckUpdateAsync() { @@ -57,6 +61,16 @@ func (u *CmdUpdater) Update() error { errPool := []error{} + // check if we are following the syncPolicy + // TODO: for now we check the sync policy to block update during the update phase, + // This is no optimal, as we still check remote repository in check update async. + // We should move the sync policy check to the check update async, which will save + // time to check the remote repo in order to make the check done in the timeout period. + if err := u.reachSyncSchedule(); err != nil { + log.Info(err.Error()) + return err + } + remoteRepo, err := u.getRemoteRepository() if err != nil { // TODO: handle error here @@ -138,6 +152,12 @@ func (u *CmdUpdater) Update() error { } if len(errPool) == 0 { + // update the sync timestamp + err := u.UpdateSyncTimestamp() + if err != nil { + log.Error(err) + } + fmt.Println("Update done! Enjoy coding!") return nil } else { @@ -265,3 +285,60 @@ func (u *CmdUpdater) LoadLockedPackages(lockFile string) (map[string]string, err } return lockedPkgs, nil } + +// check sync policy +func (u *CmdUpdater) reachSyncSchedule() error { + // check if we are following the syncPolicy + if u.SyncPolicy == "never" { + return errors.New(fmt.Sprintf("Remote '%s': Sync policy is set to never, no update will be performed", u.LocalRepo.Name())) + } + // now load the sync timestamp + localRepoFolder, err := u.LocalRepo.RepositoryFolder() + if err != nil { + return err + } + data, err := os.ReadFile(path.Join(localRepoFolder, "sync.timestamp")) + if err != nil { + // error read the file, we assume the sync time is passed + return nil + } + syncTime, err := time.Parse(time.RFC3339, string(data)) + if err != nil { + return err + } + + // now check if we passed the sync time + if time.Now().Before(syncTime) { + return errors.New(fmt.Sprintf("Remote '%s': Not yet reach the sync time", u.LocalRepo.Name())) + } + + return nil +} + +func (u *CmdUpdater) UpdateSyncTimestamp() error { + localRepoFolder, err := u.LocalRepo.RepositoryFolder() + if err != nil { + return err + } + + var delay time.Duration = 24 + switch u.SyncPolicy { + case "always": + return errors.New(fmt.Sprintf("Remote '%s': Sync policy is set to always, no need to update the sync timestamp", u.LocalRepo.Name())) + case "never": + return errors.New(fmt.Sprintf("Remote '%s': Sync policy is set to never, no need to update the sync timestamp", u.LocalRepo.Name())) + case "hourly": + delay = 1 + case "daily": + delay = 24 + case "weekly": + delay = 24 * 7 + case "monthly": + delay = 24 * 30 + } + + err = os.WriteFile(path.Join(localRepoFolder, "sync.timestamp"), []byte(time.Now().Add(time.Hour*delay).Format(time.RFC3339)), 0644) + + log.Infof("Remote '%s': Sync timestamp updated to %s", u.LocalRepo.Name(), time.Now().Add(time.Hour*delay).Format(time.RFC3339)) + return err +}