From 019e8d328186671e817dd54e8e5f11e0ffbb311d Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Mon, 25 Mar 2024 15:12:34 -0400 Subject: [PATCH 01/11] Refactor Package methods that don't depened on the Package Signed-off-by: Gavin Zhao --- builder/build.go | 11 ++++- builder/chroot.go | 2 +- builder/index.go | 2 +- builder/manager.go | 2 +- builder/overlay.go | 27 ++++++++++++ builder/repos.go | 100 ++++++++++++++++++++++----------------------- builder/util.go | 35 ---------------- 7 files changed, 87 insertions(+), 92 deletions(-) diff --git a/builder/build.go b/builder/build.go index bddaf2a..65262a6 100644 --- a/builder/build.go +++ b/builder/build.go @@ -513,10 +513,17 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro } // Bring up the root - if err := p.ActivateRoot(overlay); err != nil { + if err := overlay.ActivateRoot(); err != nil { return err } + // Add build user if needed + if p.Type == PackageTypeYpkg { + if err := AddBuildUser(overlay.MountPoint); err != nil { + return err + } + } + // Ensure source assets are in place if err := p.CopyAssets(history, overlay); err != nil { return fmt.Errorf("Failed to copy required source assets, reason: %w\n", err) @@ -541,7 +548,7 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro } // Get the repos in place before asserting anything - if err := p.ConfigureRepos(notif, overlay, pman, profile); err != nil { + if err := pman.ConfigureRepos(notif, overlay, profile); err != nil { return fmt.Errorf("Configuring repositories failed, reason: %w\n", err) } diff --git a/builder/chroot.go b/builder/chroot.go index cf385c8..6ab334e 100644 --- a/builder/chroot.go +++ b/builder/chroot.go @@ -42,7 +42,7 @@ func (p *Package) Chroot(notif PidNotifier, pman *EopkgManager, overlay *Overlay ChrootEnvironment = env - if err := p.ActivateRoot(overlay); err != nil { + if err := overlay.ActivateRoot(); err != nil { return err } diff --git a/builder/index.go b/builder/index.go index 6bbce1e..24d7163 100644 --- a/builder/index.go +++ b/builder/index.go @@ -53,7 +53,7 @@ func (p *Package) Index(notif PidNotifier, dir string, overlay *Overlay) error { return err } - if err := p.ActivateRoot(overlay); err != nil { + if err := overlay.ActivateRoot(); err != nil { return err } diff --git a/builder/manager.go b/builder/manager.go index 30d96f1..0107c3a 100644 --- a/builder/manager.go +++ b/builder/manager.go @@ -300,7 +300,7 @@ func (m *Manager) Cleanup() { } if m.pkg != nil { - m.pkg.DeactivateRoot(m.overlay) + m.overlay.DeactivateRoot() } // Deactivation may have started something off, kill them too diff --git a/builder/overlay.go b/builder/overlay.go index 2509f60..4094dd0 100644 --- a/builder/overlay.go +++ b/builder/overlay.go @@ -315,3 +315,30 @@ func (o *Overlay) ConfigureNetworking() error { return nil } + +// DeactivateRoot will tear down the previously activated root. +func (overlay *Overlay) DeactivateRoot() { + MurderDeathKill(overlay.MountPoint) + + mountMan := disk.GetMountManager() + + commands.SetStdin(nil) + overlay.Unmount() + slog.Debug("Requesting unmount of all remaining mountpoints") + mountMan.UnmountAll() +} + +// ActivateRoot will do the hard work of actually bring up the overlayfs +// system to allow manipulation of the roots for builds, etc. +func (overlay *Overlay) ActivateRoot() error { + slog.Debug("Configuring overlay storage") + + // Now mount the overlayfs + if err := overlay.Mount(); err != nil { + return err + } + + slog.Debug("Bringing up virtual filesystems") + + return overlay.MountVFS() +} diff --git a/builder/repos.go b/builder/repos.go index baee58c..11131d0 100644 --- a/builder/repos.go +++ b/builder/repos.go @@ -30,8 +30,49 @@ const ( BindRepoDir = "/hostRepos" ) -// addLocalRepo will try to add the repo and bind mount it into the target. -func (p *Package) addLocalRepo(notif PidNotifier, o *Overlay, pkgManager *EopkgManager, repo *Repo) error { +func (e *EopkgManager) addRepos(notif PidNotifier, o *Overlay, repos []*Repo) error { + if len(repos) < 1 { + return nil + } + + for _, repo := range repos { + if repo.Local { + slog.Debug("Adding local repo to system", "name", repo.Name, "uri", repo.URI) + + if err := e.addLocalRepo(notif, o, repo); err != nil { + return fmt.Errorf("Failed to add local repo to system %s, reason: %w\n", repo.Name, err) + } + + continue + } + + slog.Debug("Adding repo to system", "name", repo.Name, "uri", repo.URI) + + if err := e.AddRepo(repo.Name, repo.URI); err != nil { + return fmt.Errorf("Failed to add repo to system %s, reason: %w\n", repo.Name, err) + } + } + + return nil +} + +func (e *EopkgManager) removeRepos(repos []string) error { + if len(repos) < 1 { + return nil + } + + for _, id := range repos { + slog.Debug("Removing repository", "repo", id) + + if err := e.RemoveRepo(id); err != nil { + return fmt.Errorf("Failed to remove repository %s, reason: %w\n", id, err) + } + } + + return nil +} + +func (e *EopkgManager) addLocalRepo(notif PidNotifier, o *Overlay, repo *Repo) error { // Ensure the source exists too. Sorta helpful like that. if !PathExists(repo.URI) { return fmt.Errorf("Local repo does not exist") @@ -75,56 +116,11 @@ func (p *Package) addLocalRepo(notif PidNotifier, o *Overlay, pkgManager *EopkgM // Now add the local repo chrootLocal := filepath.Join(BindRepoDir, repo.Name, "eopkg-index.xml.xz") - return pkgManager.AddRepo(repo.Name, chrootLocal) -} - -func (p *Package) removeRepos(pkgManager *EopkgManager, repos []string) error { - if len(repos) < 1 { - return nil - } - - for _, id := range repos { - slog.Debug("Removing repository", "repo", id) - - if err := pkgManager.RemoveRepo(id); err != nil { - return fmt.Errorf("Failed to remove repository %s, reason: %w\n", id, err) - } - } - - return nil -} - -// addRepos will add the specified filtered set of repos to the rootfs. -func (p *Package) addRepos(notif PidNotifier, o *Overlay, pkgManager *EopkgManager, repos []*Repo) error { - if len(repos) < 1 { - return nil - } - - for _, repo := range repos { - if repo.Local { - slog.Debug("Adding local repo to system", "name", repo.Name, "uri", repo.URI) - - if err := p.addLocalRepo(notif, o, pkgManager, repo); err != nil { - return fmt.Errorf("Failed to add local repo to system %s, reason: %w\n", repo.Name, err) - } - - continue - } - - slog.Debug("Adding repo to system", "name", repo.Name, "uri", repo.URI) - - if err := pkgManager.AddRepo(repo.Name, repo.URI); err != nil { - return fmt.Errorf("Failed to add repo to system %s, reason: %w\n", repo.Name, err) - } - } - - return nil + return e.AddRepo(repo.Name, chrootLocal) } -// ConfigureRepos will attempt to configure the repos according to the configuration -// of the manager. -func (p *Package) ConfigureRepos(notif PidNotifier, o *Overlay, pkgManager *EopkgManager, profile *Profile) error { - repos, err := pkgManager.GetRepos() +func (e *EopkgManager) ConfigureRepos(notif PidNotifier, o *Overlay, profile *Profile) error { + repos, err := e.GetRepos() if err != nil { return err } @@ -140,7 +136,7 @@ func (p *Package) ConfigureRepos(notif PidNotifier, o *Overlay, pkgManager *Eopk removals = append(removals, profile.RemoveRepos...) } - if err := p.removeRepos(pkgManager, removals); err != nil { + if err := e.removeRepos(removals); err != nil { return err } @@ -156,5 +152,5 @@ func (p *Package) ConfigureRepos(notif PidNotifier, o *Overlay, pkgManager *Eopk } } - return p.addRepos(notif, o, pkgManager, addRepos) + return e.addRepos(notif, o, addRepos) } diff --git a/builder/util.go b/builder/util.go index b9a11f7..fa5050f 100644 --- a/builder/util.go +++ b/builder/util.go @@ -33,7 +33,6 @@ import ( "time" "github.com/getsolus/libosdev/commands" - "github.com/getsolus/libosdev/disk" ) // ChrootEnvironment is the env used by ChrootExec calls. @@ -48,40 +47,6 @@ type PidNotifier interface { SetActivePID(pid int) } -// ActivateRoot will do the hard work of actually bring up the overlayfs -// system to allow manipulation of the roots for builds, etc. -func (p *Package) ActivateRoot(overlay *Overlay) error { - slog.Debug("Configuring overlay storage") - - // Now mount the overlayfs - if err := overlay.Mount(); err != nil { - return err - } - - // Add build user - if p.Type == PackageTypeYpkg { - if err := AddBuildUser(overlay.MountPoint); err != nil { - return err - } - } - - slog.Debug("Bringing up virtual filesystems") - - return overlay.MountVFS() -} - -// DeactivateRoot will tear down the previously activated root. -func (p *Package) DeactivateRoot(overlay *Overlay) { - MurderDeathKill(overlay.MountPoint) - - mountMan := disk.GetMountManager() - - commands.SetStdin(nil) - overlay.Unmount() - slog.Debug("Requesting unmount of all remaining mountpoints") - mountMan.UnmountAll() -} - // MurderDeathKill will find all processes with a root matching the given root // and set about killing them, to assist in clean closing. func MurderDeathKill(root string) error { From 315952a3c64ddbad5fce59777026814081297e14 Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Mon, 25 Mar 2024 18:35:19 -0400 Subject: [PATCH 02/11] Initial layers create code Signed-off-by: Gavin Zhao --- builder/build.go | 5 ++ builder/layer.go | 116 +++++++++++++++++++++++++++++++++++++++++++++++ builder/main.go | 8 ++++ 3 files changed, 129 insertions(+) create mode 100644 builder/layer.go diff --git a/builder/build.go b/builder/build.go index 65262a6..41b2835 100644 --- a/builder/build.go +++ b/builder/build.go @@ -229,6 +229,11 @@ func (p *Package) CopyAssets(h *PackageHistory, o *Overlay) error { return h.WriteXML(histPath) } +func (p *Package) calcHashAndDeps() (hash string, deps []string, profile *Profile) { + hash = LayersFakeHash + return +} + // PrepYpkg will do the initial leg work of preparing us for a ypkg build. func (p *Package) PrepYpkg(notif PidNotifier, usr *UserInfo, pman *EopkgManager, overlay *Overlay, h *PackageHistory) error { slog.Debug("Writing packager file") diff --git a/builder/layer.go b/builder/layer.go new file mode 100644 index 0000000..a3ae7ad --- /dev/null +++ b/builder/layer.go @@ -0,0 +1,116 @@ +package builder + +import ( + "fmt" + "log/slog" + "path/filepath" + "strings" +) + +type Layer struct { + hash string + deps []string + profile *Profile + back *BackingImage +} + +func (l *Layer) BasePath() string { + return filepath.Join(LayersDir, l.hash) +} + +func (l *Layer) RequestOverlay(notif PidNotifier, pman *EopkgManager) (err error, ovly *Overlay) { + if PathExists(filepath.Join(l.BasePath(), "content")) { + return l.Create(notif, pman) + } else { + return + } +} + +func (l *Layer) Create(notif PidNotifier, pman *EopkgManager) (err error, ovly *Overlay) { + basePath := l.BasePath() + contentPath := filepath.Join(basePath, "content") + + depsOverlay := Overlay{ + Back: l.back, + Package: nil, + BaseDir: basePath, + WorkDir: filepath.Join(basePath, "work"), + UpperDir: contentPath, + ImgDir: filepath.Join(basePath, "img"), + MountPoint: filepath.Join(basePath, "union"), + LockPath: filepath.Join(basePath, "lock"), + EnableTmpfs: false, + mountedImg: false, + mountedOverlay: false, + mountedVFS: false, + mountedTmpfs: false, + } + + if err = depsOverlay.CleanExisting(); err != nil { + err = fmt.Errorf("Failed to cleanup existing overlay (if exists), reason: %w", err) + return + } + + if err = depsOverlay.EnsureDirs(); err != nil { + err = fmt.Errorf("Failed to ensure dirs for overlay, reason: %w", err) + return + } + + // Mount overlay + if err = depsOverlay.ActivateRoot(); err != nil { + err = fmt.Errorf("Failed to activate overlay, reason: %w", err) + return + } + defer depsOverlay.DeactivateRoot() + + // Init pman + if err = pman.Init(); err != nil { + err = fmt.Errorf("Failed to init pman, reason: %w", err) + return + } + defer pman.Cleanup() + + // Bring up dbus to do Things + slog.Debug("Starting D-BUS") + + if err = pman.StartDBUS(); err != nil { + err = fmt.Errorf("Failed to start d-bus, reason: %w", err) + return + } + + // Get the repos in place before asserting anything + if err = pman.ConfigureRepos(notif, &depsOverlay, l.profile); err != nil { + err = fmt.Errorf("Configuring repositories failed, reason: %w", err) + return + } + + // Now, install/upgrade everything! + slog.Debug("Upgrading system base and other core packages") + + if err = pman.Upgrade(); err != nil { + err = fmt.Errorf("Failed to upgrade layer rootfs, reason: %w", err) + return + } + + slog.Debug("Asserting system.devel component installation") + if err = pman.InstallComponent("system.devel"); err != nil { + err = fmt.Errorf("Failed to assert system.devel in layer, reason: %w", err) + return + } + + // Install our dependencies + cmd := fmt.Sprintf("eopkg it -y %s", strings.Join(l.deps, " ")) + if DisableColors { + cmd += " -n" + } + + slog.Debug("Installing dependencies") + + if err = ChrootExec(notif, depsOverlay.MountPoint, cmd); err != nil { + err = fmt.Errorf("Failed to install dependencies, reason: %w", err) + return + } + notif.SetActivePID(0) + + return +} diff --git a/builder/main.go b/builder/main.go index cd04d16..9ff59e7 100644 --- a/builder/main.go +++ b/builder/main.go @@ -47,6 +47,14 @@ const ( ImageRootsDir = "/var/lib/solbuild/roots" ) +const ( + // LayersDir is where container layers are cached, identified by their + // sha256 hashes, e.g. `/var/cache/solbuild/layers/3c0de53d6017469...` + LayersDir = "/var/cache/solbuild/layers" + // sha256sum | awk '{ print $1 }' | xxd -r -p | base64 + LayersFakeHash = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +) + const ( // PackageCacheDirectory is where we share packages between all builders. PackageCacheDirectory = "/var/lib/solbuild/packages" From a5a83ca9f099f016c8ee255a2c90c3f4dbbd9c0a Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Sat, 30 Mar 2024 18:02:19 -0400 Subject: [PATCH 03/11] Overlays/Mounting working, need to hook up dep calculation Signed-off-by: Gavin Zhao --- Makefile | 5 ++- builder/build.go | 103 +++++++++++++++++++++++++++------------------ builder/layer.go | 51 +++++++++++++++++++--- builder/overlay.go | 11 ++++- builder/util.go | 23 ++++++++++ go.mod | 3 ++ go.sum | 96 +++++++++++------------------------------- 7 files changed, 169 insertions(+), 123 deletions(-) diff --git a/Makefile b/Makefile index dc7b1e8..c0f36d2 100644 --- a/Makefile +++ b/Makefile @@ -53,4 +53,7 @@ release: .PHONY: clean clean: - rm -rf $(CURDIR)/bin + rm -rvf $(CURDIR)/bin + rm -rvf $(CURDIR)/*.eopkg + rm -rvf $(CURDIR)/pspec_x86_64.xml + rm -rvf $(CURDIR)/abi* diff --git a/builder/build.go b/builder/build.go index 41b2835..6aa6201 100644 --- a/builder/build.go +++ b/builder/build.go @@ -229,8 +229,11 @@ func (p *Package) CopyAssets(h *PackageHistory, o *Overlay) error { return h.WriteXML(histPath) } -func (p *Package) calcHashAndDeps() (hash string, deps []string, profile *Profile) { - hash = LayersFakeHash +func (p *Package) calcDeps(profile *Profile) (deps []string) { + // hash = LayersFakeHash + deps = append(deps, "rust") + deps = append(deps, "cargo") + deps = append(deps, "llvm") return } @@ -251,32 +254,32 @@ func (p *Package) PrepYpkg(notif PidNotifier, usr *UserInfo, pman *EopkgManager, return fmt.Errorf("Failed to write packager file %s, reason: %w\n", fp, err) } - wdir := p.GetWorkDirInternal() - ymlFile := filepath.Join(wdir, filepath.Base(p.Path)) + // wdir := p.GetWorkDirInternal() + // ymlFile := filepath.Join(wdir, filepath.Base(p.Path)) - cmd := fmt.Sprintf("ypkg-install-deps --eopkg-cmd='%s' -f %s", installCommand, ymlFile) - if DisableColors { - cmd += " -n" - } + // cmd := fmt.Sprintf("ypkg-install-deps --eopkg-cmd='%s' -f %s", installCommand, ymlFile) + // if DisableColors { + // cmd += " -n" + // } - // Install build dependencies - slog.Debug("Installing build dependencies", "file", ymlFile) + // // Install build dependencies + // slog.Debug("Installing build dependencies", "file", ymlFile) - if err := ChrootExec(notif, overlay.MountPoint, cmd); err != nil { - return fmt.Errorf("Failed to install build dependencies %s, reason: %w\n", ymlFile, err) - } + // if err := ChrootExec(notif, overlay.MountPoint, cmd); err != nil { + // return fmt.Errorf("Failed to install build dependencies %s, reason: %w\n", ymlFile, err) + // } - notif.SetActivePID(0) + // notif.SetActivePID(0) - // Cleanup now - slog.Debug("Stopping D-BUS") + // // Cleanup now + // slog.Debug("Stopping D-BUS") - if err := pman.StopDBUS(); err != nil { - return fmt.Errorf("Failed to stop d-bus, reason: %w\n", err) - } + // if err := pman.StopDBUS(); err != nil { + // return fmt.Errorf("Failed to stop d-bus, reason: %w\n", err) + // } // Chwn the directory before bringing up sources - cmd = fmt.Sprintf("chown -R %s:%s %s", BuildUser, BuildUser, BuildUserHome) + cmd := fmt.Sprintf("chown -R %s:%s %s", BuildUser, BuildUser, BuildUserHome) if err := ChrootExec(notif, overlay.MountPoint, cmd); err != nil { return fmt.Errorf("Failed to set home directory permissions, reason: %w\n", err) } @@ -512,6 +515,24 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro ChrootEnvironment = env + // Set up layers caching, only for YPKG + if p.Type == PackageTypeYpkg { + deps := p.calcDeps(profile) + layer := Layer{ + deps: deps, + profile: profile, + back: overlay.Back, + } + + contentPath, err := layer.RequestOverlay(notif) + if err != nil { + return err + } + overlay.LayerDir = contentPath + } else { + return errors.New("Under testing of layers feature, XML build is not enabled yet.") + } + // Set up environment if err := overlay.CleanExisting(); err != nil { return err @@ -540,34 +561,34 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro return err } - // Set up package manager - if err := pman.Init(); err != nil { - return err - } + // // Set up package manager + // if err := pman.Init(); err != nil { + // return err + // } - // Bring up dbus to do Things - slog.Debug("Starting D-BUS") + // // Bring up dbus to do Things + // slog.Debug("Starting D-BUS") - if err := pman.StartDBUS(); err != nil { - return fmt.Errorf("Failed to start d-bus, reason: %w\n", err) - } + // if err := pman.StartDBUS(); err != nil { + // return fmt.Errorf("Failed to start d-bus, reason: %w\n", err) + // } - // Get the repos in place before asserting anything - if err := pman.ConfigureRepos(notif, overlay, profile); err != nil { - return fmt.Errorf("Configuring repositories failed, reason: %w\n", err) - } + // // Get the repos in place before asserting anything + // if err := pman.ConfigureRepos(notif, overlay, profile); err != nil { + // return fmt.Errorf("Configuring repositories failed, reason: %w\n", err) + // } - slog.Debug("Upgrading system base") + // slog.Debug("Upgrading system base") - if err := pman.Upgrade(); err != nil { - return fmt.Errorf("Failed to upgrade rootfs, reason: %w\n", err) - } + // if err := pman.Upgrade(); err != nil { + // return fmt.Errorf("Failed to upgrade rootfs, reason: %w\n", err) + // } - slog.Debug("Asserting system.devel component installation") + // slog.Debug("Asserting system.devel component installation") - if err := pman.InstallComponent("system.devel"); err != nil { - return fmt.Errorf("Failed to assert system.devel, reason: %w\n", err) - } + // if err := pman.InstallComponent("system.devel"); err != nil { + // return fmt.Errorf("Failed to assert system.devel, reason: %w\n", err) + // } // Ensure all directories are in place if err := p.CreateDirs(overlay); err != nil { diff --git a/builder/layer.go b/builder/layer.go index a3ae7ad..b999906 100644 --- a/builder/layer.go +++ b/builder/layer.go @@ -1,34 +1,69 @@ package builder import ( + "encoding/base64" + "encoding/json" "fmt" "log/slog" "path/filepath" "strings" + + "github.com/zeebo/blake3" ) type Layer struct { - hash string deps []string profile *Profile back *BackingImage } +func (l Layer) MarshalJSON() ([]byte, error) { + var imageHash string + var err error + if PathExists(l.back.ImagePath) { + if imageHash, err = hashFile(l.back.ImagePath); err != nil { + return nil, err + } + // } else if PathExists(l.back.ImagePath) { + // if imageHash, err = hashFile(l.back.ImagePath); err != nil { + // return + // } + } else { + return nil, fmt.Errorf("Backing image doens't exist at %s", l.back.ImagePath) + } + + return json.Marshal(struct { + Deps []string + ImageHash string + }{Deps: l.deps, ImageHash: imageHash}) +} + +func (l *Layer) Hash() string { + jsonBytes, err := json.Marshal(l) + if err != nil { + return LayersFakeHash + } else { + hashBytes := blake3.Sum256(jsonBytes) + return base64.StdEncoding.EncodeToString(hashBytes[:]) + } +} + func (l *Layer) BasePath() string { - return filepath.Join(LayersDir, l.hash) + return filepath.Join(LayersDir, l.Hash()) } -func (l *Layer) RequestOverlay(notif PidNotifier, pman *EopkgManager) (err error, ovly *Overlay) { - if PathExists(filepath.Join(l.BasePath(), "content")) { - return l.Create(notif, pman) +func (l *Layer) RequestOverlay(notif PidNotifier) (contentPath string, err error) { + contentPath = filepath.Join(l.BasePath(), "content") + if !PathExists(contentPath) || l.Hash() == LayersFakeHash { + return l.Create(notif) } else { return } } -func (l *Layer) Create(notif PidNotifier, pman *EopkgManager) (err error, ovly *Overlay) { +func (l *Layer) Create(notif PidNotifier) (contentPath string, err error) { basePath := l.BasePath() - contentPath := filepath.Join(basePath, "content") + contentPath = filepath.Join(basePath, "content") depsOverlay := Overlay{ Back: l.back, @@ -63,6 +98,8 @@ func (l *Layer) Create(notif PidNotifier, pman *EopkgManager) (err error, ovly * } defer depsOverlay.DeactivateRoot() + pman := NewEopkgManager(notif, depsOverlay.MountPoint) + // Init pman if err = pman.Init(); err != nil { err = fmt.Errorf("Failed to init pman, reason: %w", err) diff --git a/builder/overlay.go b/builder/overlay.go index 4094dd0..8da17c1 100644 --- a/builder/overlay.go +++ b/builder/overlay.go @@ -38,6 +38,7 @@ type Overlay struct { BaseDir string // BaseDir is the base directory containing the root WorkDir string // WorkDir is the overlayfs workdir lock UpperDir string // UpperDir is where real inode changes happen (tmp) + LayerDir string ImgDir string // Where the profile is mounted (ro) MountPoint string // The actual mount point for the union'd directories LockPath string // Path to the lockfile for this overlay @@ -167,12 +168,18 @@ func (o *Overlay) Mount() error { o.mountedImg = true // Now mount the overlayfs - slog.Debug("Mounting overlayfs", "upper", o.UpperDir, "lower", o.ImgDir, + var lowerDir string + if len(o.LayerDir) == 0 { + lowerDir = o.ImgDir + } else { + lowerDir = o.LayerDir + ":" + o.ImgDir + } + slog.Debug("Mounting overlayfs", "upper", o.UpperDir, "lower", lowerDir, "workdir", o.WorkDir, "target", o.MountPoint) // Mounting overlayfs.. err := mountMan.Mount("overlay", o.MountPoint, "overlay", - fmt.Sprintf("lowerdir=%s", o.ImgDir), + fmt.Sprintf("lowerdir=%s", lowerDir), fmt.Sprintf("upperdir=%s", o.UpperDir), fmt.Sprintf("workdir=%s", o.WorkDir)) // Check non-fatal.. diff --git a/builder/util.go b/builder/util.go index fa5050f..dbe8e38 100644 --- a/builder/util.go +++ b/builder/util.go @@ -21,6 +21,7 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + "io" "log/slog" "os" "os/exec" @@ -353,3 +354,25 @@ func ValidMemSize(s string) bool { return false } + +func hashFileBytes(path string) ([]byte, error) { + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + + h := sha256.New() + if _, err := io.Copy(h, f); err != nil { + return nil, err + } + return h.Sum(nil), nil +} + +func hashFile(path string) (string, error) { + bytes, err := hashFileBytes(path) + if err != nil { + return "", err + } + return fmt.Sprintf("%x", bytes), nil +} diff --git a/go.mod b/go.mod index e8f24c8..a958b3b 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,8 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) +require github.com/klauspost/cpuid/v2 v2.0.12 // indirect + require ( dario.cat/mergo v1.0.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect @@ -40,6 +42,7 @@ require ( github.com/skeema/knownhosts v1.3.0 // indirect github.com/solus-project/libosdev v0.0.0-20171113084438-39032fc50772 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect + github.com/zeebo/blake3 v0.2.3 golang.org/x/crypto v0.31.0 // indirect golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect diff --git a/go.sum b/go.sum index e14df0d..b6d4e6a 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,6 @@ github.com/DataDrake/cli-ng/v2 v2.0.2/go.mod h1:bU9YaNNWWVq0eIdDsU3TCe9+7Jb398iB github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78= -github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= @@ -17,51 +15,37 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4= github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4= -github.com/charlievieth/fastwalk v1.0.8 h1:uaoH6cAKSk73aK7aKXqs0+bL+J3Txzd3NGH8tRXgHko= -github.com/charlievieth/fastwalk v1.0.8/go.mod h1:yGy1zbxog41ZVMcKA/i8ojXLFsuayX5VvwhQVoj9PBI= github.com/charlievieth/fastwalk v1.0.9 h1:Odb92AfoReO3oFBfDGT5J+nwgzQPF/gWAw6E6/lkor0= github.com/charlievieth/fastwalk v1.0.9/go.mod h1:yGy1zbxog41ZVMcKA/i8ojXLFsuayX5VvwhQVoj9PBI= github.com/cheggaaa/pb/v3 v3.1.5 h1:QuuUzeM2WsAqG2gMqtzaWithDJv0i+i6UlnwSCI4QLk= github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6jM60XI= -github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY= github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cyphar/filepath-securejoin v0.3.2 h1:QhZu5AxQ+o1XZH0Ye05YzvJ0kAdK6VQc0z9NNMek7gc= -github.com/cyphar/filepath-securejoin v0.3.2/go.mod h1:F7i41x/9cBF7lzCrVsYs9fuzwRZm4NQsGTBdpp6mETc= github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy v1.2.3 h1:xwIyKHbaP5yfT6O9KIeYJR5549MXRQkoQMRXGztz8YQ= +github.com/elazarl/goproxy v1.2.3/go.mod h1:YfEbZtqP4AetfO6d40vWchF3znWX7C7Vd6ZMfdL8z64= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/getsolus/libosdev v0.0.0-20181023041421-9ab0f4b463fd h1:QZoSqUIKIFeqhImxNk1cdY7M4n8JVZxTzuhP+Y0DaK8= github.com/getsolus/libosdev v0.0.0-20181023041421-9ab0f4b463fd/go.mod h1:8P4U+IYO8T6nRPLlC6qv1wMFcc0vK0vMVDCuyiFTTLg= -github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= -github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= +github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= +github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= -github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= -github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8= -github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM= github.com/go-git/go-billy/v5 v5.6.1 h1:u+dcrgaguSSkbjzHwelEjc0Yj300NUevrrPphk/SoRA= github.com/go-git/go-billy/v5 v5.6.1/go.mod h1:0AsLr1z2+Uksi4NlElmMblP5rPcDZNRCD8ujZCRR2BE= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= -github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= -github.com/go-git/go-git/v5 v5.13.0 h1:vLn5wlGIh/X78El6r3Jr+30W16Blk0CTcxTYcYPWi5E= -github.com/go-git/go-git/v5 v5.13.0/go.mod h1:Wjo7/JyVKtQgUNdXYXIepzWfJQkUEIGvkvVkiXRR/zw= github.com/go-git/go-git/v5 v5.13.1 h1:DAQ9APonnlvSWpvolXWIuV6Q6zXy2wHbN4cVlNR5Q+M= github.com/go-git/go-git/v5 v5.13.1/go.mod h1:qryJB4cSBoq3FRoBRf5A77joojuBcmPJ0qu3XXXVixc= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= @@ -75,6 +59,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -89,8 +75,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -100,8 +86,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= @@ -112,77 +98,43 @@ github.com/solus-project/libosdev v0.0.0-20171113084438-39032fc50772/go.mod h1:D github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= +github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= +github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= +github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= +github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= gitlab.com/slxh/go/powerline v0.1.0 h1:/3lwpGRD5yW9HFS/hammtCI4kvtjKw8E1dcpHS9Udx8= gitlab.com/slxh/go/powerline v0.1.0/go.mod h1:vBTN83xoDyGejdTeZkMGs8l/qZvOjpUkRMYrthNhqJE= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 39ebb02dc2120d5359bc418ebb40c9bbfffd35e6 Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Thu, 4 Apr 2024 13:12:55 -0400 Subject: [PATCH 04/11] Initial resolver working Signed-off-by: Gavin Zhao --- builder/build.go | 16 ++++--- builder/layer.go | 40 ++++++++++++----- builder/manager.go | 101 ++++++++++++++++++++++++++++++++++++++++++- builder/pkg.go | 8 ++-- builder/resolver.go | 103 ++++++++++++++++++++++++++++++++++++++++++++ builder/util.go | 13 +++++- go.mod | 2 + go.sum | 4 ++ 8 files changed, 265 insertions(+), 22 deletions(-) create mode 100644 builder/resolver.go diff --git a/builder/build.go b/builder/build.go index 6aa6201..a500f23 100644 --- a/builder/build.go +++ b/builder/build.go @@ -229,12 +229,9 @@ func (p *Package) CopyAssets(h *PackageHistory, o *Overlay) error { return h.WriteXML(histPath) } -func (p *Package) calcDeps(profile *Profile) (deps []string) { +func (p *Package) calcDeps(resolver *Resolver) ([]Dep, error) { // hash = LayersFakeHash - deps = append(deps, "rust") - deps = append(deps, "cargo") - deps = append(deps, "llvm") - return + return resolver.Query(p.Deps, true, true) } // PrepYpkg will do the initial leg work of preparing us for a ypkg build. @@ -500,7 +497,7 @@ func (p *Package) CollectAssets(overlay *Overlay, usr *UserInfo, manifestTarget } // Build will attempt to build the package in the overlayfs system. -func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Profile, pman *EopkgManager, overlay *Overlay, manifestTarget string) error { +func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Profile, pman *EopkgManager, overlay *Overlay, resolver *Resolver, manifestTarget string) error { slog.Debug("Building package", "name", p.Name, "version", p.Version, "release", p.Release, "type", p.Type, "profile", overlay.Back.Name) @@ -517,7 +514,11 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro // Set up layers caching, only for YPKG if p.Type == PackageTypeYpkg { - deps := p.calcDeps(profile) + deps, err := p.calcDeps(resolver) + if err != nil { + return fmt.Errorf("Failed to calculate dependencies: %w", err) + } + layer := Layer{ deps: deps, profile: profile, @@ -529,6 +530,7 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro return err } overlay.LayerDir = contentPath + slog.Info("Using layer", "hash", layer.Hash()) } else { return errors.New("Under testing of layers feature, XML build is not enabled yet.") } diff --git a/builder/layer.go b/builder/layer.go index b999906..630d3cd 100644 --- a/builder/layer.go +++ b/builder/layer.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "log/slog" + "os" "path/filepath" "strings" @@ -12,16 +13,18 @@ import ( ) type Layer struct { - deps []string + deps []Dep profile *Profile back *BackingImage + created bool + hash string } func (l Layer) MarshalJSON() ([]byte, error) { var imageHash string var err error if PathExists(l.back.ImagePath) { - if imageHash, err = hashFile(l.back.ImagePath); err != nil { + if imageHash, err = xxh3128HashFile(l.back.ImagePath); err != nil { return nil, err } // } else if PathExists(l.back.ImagePath) { @@ -33,19 +36,23 @@ func (l Layer) MarshalJSON() ([]byte, error) { } return json.Marshal(struct { - Deps []string + Deps []Dep `json:"deps"` ImageHash string }{Deps: l.deps, ImageHash: imageHash}) } func (l *Layer) Hash() string { - jsonBytes, err := json.Marshal(l) - if err != nil { - return LayersFakeHash - } else { - hashBytes := blake3.Sum256(jsonBytes) - return base64.StdEncoding.EncodeToString(hashBytes[:]) + if l.hash == "" { + jsonBytes, err := json.Marshal(l) + if err != nil { + l.hash = LayersFakeHash + } else { + hashBytes := blake3.Sum256(jsonBytes) + l.hash = base64.StdEncoding.EncodeToString(hashBytes[:]) + } } + return l.hash + } func (l *Layer) BasePath() string { @@ -61,7 +68,15 @@ func (l *Layer) RequestOverlay(notif PidNotifier) (contentPath string, err error } } +func (l *Layer) RemoveIfNotCreated() { + slog.Debug("Layer not fully created, removing...", "path", l.BasePath()) + if !l.created { + os.RemoveAll(l.BasePath()) + } +} + func (l *Layer) Create(notif PidNotifier) (contentPath string, err error) { + slog.Info("Creating layer", "hash", l.Hash()) basePath := l.BasePath() contentPath = filepath.Join(basePath, "content") @@ -136,7 +151,12 @@ func (l *Layer) Create(notif PidNotifier) (contentPath string, err error) { } // Install our dependencies - cmd := fmt.Sprintf("eopkg it -y %s", strings.Join(l.deps, " ")) + pkgs := make([]string, len(l.deps)) + for idx, dep := range l.deps { + pkgs[idx] = dep.Name + } + slog.Debug("Installing dependencies", "size", len(pkgs), "pkgs", pkgs) + cmd := fmt.Sprintf("eopkg it -y %s", strings.Join(pkgs, " ")) if DisableColors { cmd += " -n" } diff --git a/builder/manager.go b/builder/manager.go index 0107c3a..4b62f00 100644 --- a/builder/manager.go +++ b/builder/manager.go @@ -17,19 +17,25 @@ package builder import ( + "encoding/xml" "errors" "fmt" + "io" "log/slog" + "net/http" "os" "os/signal" + "path" "path/filepath" "strings" "sync" "syscall" "time" + "github.com/getsolus/libeopkg/index" "github.com/getsolus/libosdev/disk" "github.com/go-git/go-git/v5" + "github.com/ulikunitz/xz" "github.com/getsolus/solbuild/cli/log" ) @@ -72,6 +78,7 @@ type Manager struct { pkgManager *EopkgManager // Package manager, if any lock *sync.Mutex // Lock on all operations to prevent.. damage. profile *Profile // The profile we've been requested to use + resolver *Resolver lockfile *LockFile // We track the global lock for each operation didStart bool // Whether we got anything done. @@ -394,7 +401,10 @@ func (m *Manager) Build() error { return err } - return m.pkg.Build(m, m.history, m.GetProfile(), m.pkgManager, m.overlay, m.manifestTarget) + m.InitResolver() + slog.Debug("Successfully initialized resolver") + + return m.pkg.Build(m, m.history, m.GetProfile(), m.pkgManager, m.overlay, m.resolver, m.manifestTarget) } // Chroot will enter the build environment to allow users to introspect it. @@ -498,3 +508,92 @@ func (m *Manager) SetTmpfs(enable bool, size string) { m.Config.TmpfsSize = strings.TrimSpace(size) } } + +func (m *Manager) InitResolver() error { + m.resolver = NewResolver() + + if m.profile == nil { + return errors.New("Profile not initialized!") + } + + profile := m.profile + /// nameToUrl := make(map[string]string) + repos := []string{} + + if strings.Contains(profile.Image, "unstable") { + // nameToUrl["Solus"] = "https://cdn.getsol.us/repo/unstable/eopkg-index.xml.xz" + repos = append(repos, "https://cdn.getsol.us/repo/unstable/eopkg-index.xml.xz") + // repos = append(repos, "https://packages.getsol.us/unstable/eopkg-index.xml.xz") + } else if strings.Contains(profile.Image, "stable") { + // nameToUrl["Solus"] = "https://cdn.getsol.us/repo/shannon/eopkg-index.xml.xz" + repos = append(repos, "https://cdn.getsol.us/repo/shannon/eopkg-index.xml.xz") + } else { + slog.Warn("Unrecognized image name, not adding default repo", "image", profile.Image) + } + + // Realistically, remove can only be * or Solus + // for _, remove := range profile.RemoveRepos { + // if remove == "*" { + // repos = []string{} + // continue + // } + + // if idx := slices.Index(repos, remove); idx != -1 { + // repos = slices.Delete(repos, idx, idx+1) + // } else { + // slog.Warn("Cannot remove noexistent repo", "name", remove) + // } + // } + if len(profile.RemoveRepos) != 0 { + repos = []string{} + if len(profile.RemoveRepos) > 1 { + slog.Warn("Unexpectedly requested removing of more than 1 repo", "removes", profile.RemoveRepos) + } + } + + for _, add := range profile.AddRepos { + if repo := profile.Repos[add]; repo != nil { + repos = append(repos, repo.URI) + } else { + slog.Warn("Cannot add nonexistent repo", "name", add) + } + } + + for _, repo := range repos { + slog.Debug("Fetching repo", "url", repo) + + var r io.Reader + ext := path.Ext(repo) + resp, err := http.Get(repo) + if err != nil { + // slog.Error("Failed to fetch", "url", repo, "error", err) + return fmt.Errorf("Failed to fetch %s: %w", repo, err) + } + slog.Debug("Fetched") + + if ext == ".xz" { + // slog.Debug("Decoding .xz") + if r, err = xz.NewReader(resp.Body); err != nil { + // slog.Error("Failed to init xz reader", "error", err) + return fmt.Errorf("Failed to init xz reader for %s: %w", repo, err) + } + } else if ext == ".xml" { + r = resp.Body + } else { + // slog.Error("Unrecognized repo url extension", "url", repo, "ext", ext) + return fmt.Errorf("Unrecognized repo url extension %s for %s", ext, repo) + } + + dec := xml.NewDecoder(r) + var i index.Index + if err := dec.Decode(&i); err != nil { + // slog.Error("Failed to decode index", "error", err) + return fmt.Errorf("Failed to decode index for %s: %w", repo, err) + } + + m.resolver.AddIndex(&i) + slog.Info("Parsed and added repo to resolver", "url", repo) + } + + return nil +} diff --git a/builder/pkg.go b/builder/pkg.go index 5b4ee1b..0624133 100644 --- a/builder/pkg.go +++ b/builder/pkg.go @@ -63,6 +63,7 @@ type Package struct { Sources []source.Source // Each package has 0 or more sources that we fetch CanNetwork bool // Only applicable to ypkg builds CanCCache bool // Flag to enable (s)ccache + Deps []string // Build-time dependencies } // YmlPackage is a parsed ypkg build file. @@ -72,9 +73,9 @@ type YmlPackage struct { Release int `yaml:"release"` Networking bool `yaml:"networking"` // If set to false (default) we disable networking in the build Source []map[string]string `yaml:"source"` - - // Disable (s)ccache for this build. - CCache bool `yaml:"ccache"` + CCache bool `yaml:"ccache"` // Disable (s)ccache for this build. + BuildDeps []string `yaml:"builddeps"` + CheckDeps []string `yaml:"checkdeps"` } // XMLUpdate represents an update in the package history. @@ -225,6 +226,7 @@ func NewYmlPackageFromBytes(by []byte) (*Package, error) { Type: PackageTypeYpkg, CanNetwork: ypkg.Networking, CanCCache: ypkg.CCache, + Deps: append(ypkg.BuildDeps, ypkg.CheckDeps...), } for _, row := range ypkg.Source { diff --git a/builder/resolver.go b/builder/resolver.go new file mode 100644 index 0000000..9dc83c8 --- /dev/null +++ b/builder/resolver.go @@ -0,0 +1,103 @@ +package builder + +import ( + "cmp" + "errors" + "fmt" + "slices" + + "github.com/getsolus/libeopkg/index" +) + +type Resolver struct { + // indices []Index + providers map[string]string + nameToPkg map[string]index.Package +} + +type Dep struct { + Name string `json:"name"` + Hash string `json:"hash"` +} + +func NewResolver() (res *Resolver) { + res = &Resolver{ + providers: make(map[string]string), + nameToPkg: make(map[string]index.Package), + } + return +} + +func (r *Resolver) AddIndex(i *index.Index) { + for _, pkg := range i.Packages { + if _, ok := r.nameToPkg[pkg.Name]; !ok { + r.nameToPkg[pkg.Name] = pkg + } + + if pkg.Provides != nil { + for _, provides := range pkg.Provides.PkgConfig { + provider := fmt.Sprintf("pkgconfig(%s)", provides) + if _, ok := r.providers[provider]; !ok { + r.providers[provider] = pkg.Name + } + } + for _, provides := range pkg.Provides.PkgConfig32 { + provider := fmt.Sprintf("pkgconfig32(%s)", provides) + if _, ok := r.providers[provider]; !ok { + r.providers[provider] = pkg.Name + } + } + } + } +} + +func (r *Resolver) Query(pkgs []string, withBase bool, withDevel bool) (res []Dep, err error) { + visited := make(map[string]bool) + + var dfs func(name string) error + dfs = func(name string) error { + if _, ok := r.providers[name]; ok { + name = r.providers[name] + } + + if visited[name] { + return nil + } + + if _, ok := r.nameToPkg[name]; !ok { + return errors.New("Unable to find provider or package " + name) + } + visited[name] = true + + pkg := r.nameToPkg[name] + res = append(res, Dep{Name: pkg.Name, Hash: pkg.PackageHash}) + for _, dep := range r.nameToPkg[name].RuntimeDependencies { + err = dfs(dep.Name) + if err != nil { + return err + } + } + + return nil + } + + if withBase || withDevel { + for _, pkg := range r.nameToPkg { + if withBase && pkg.PartOf == "system.base" { + dfs(pkg.Name) + } else if withDevel && pkg.PartOf == "system.devel" { + dfs(pkg.Name) + } + } + } + + for _, pkg := range pkgs { + err = dfs(pkg) + if err != nil { + return + } + } + + slices.SortFunc(res, func(a, b Dep) int { return cmp.Compare(a.Name, b.Name) }) + return +} diff --git a/builder/util.go b/builder/util.go index dbe8e38..5fcb3fb 100644 --- a/builder/util.go +++ b/builder/util.go @@ -34,6 +34,7 @@ import ( "time" "github.com/getsolus/libosdev/commands" + "github.com/zeebo/blake3" ) // ChrootEnvironment is the env used by ChrootExec calls. @@ -362,7 +363,7 @@ func hashFileBytes(path string) ([]byte, error) { } defer f.Close() - h := sha256.New() + h := blake3.New() if _, err := io.Copy(h, f); err != nil { return nil, err } @@ -376,3 +377,13 @@ func hashFile(path string) (string, error) { } return fmt.Sprintf("%x", bytes), nil } + +func xxh3128HashFile(path string) (string, error) { + cmd := exec.Command("xxh128sum", path) + + output, err := cmd.CombinedOutput() + if err != nil { + return "", fmt.Errorf("Failed to run xxh128sum %s, reason: %w", path, err) + } + return strings.Split(string(output), " ")[0], nil +} diff --git a/go.mod b/go.mod index a958b3b..ac1810a 100644 --- a/go.mod +++ b/go.mod @@ -9,9 +9,11 @@ require ( github.com/charlievieth/fastwalk v1.0.9 github.com/cheggaaa/pb/v3 v3.1.5 github.com/coreos/go-systemd/v22 v22.5.0 + github.com/getsolus/libeopkg v0.1.1-0.20240404173503-db4343f6b8f8 github.com/getsolus/libosdev v0.0.0-20181023041421-9ab0f4b463fd github.com/go-git/go-billy/v5 v5.6.1 github.com/go-git/go-git/v5 v5.13.1 + github.com/ulikunitz/xz v0.5.12 gitlab.com/slxh/go/powerline v0.1.0 gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index b6d4e6a..5a5ddd9 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/getsolus/libeopkg v0.1.1-0.20240404173503-db4343f6b8f8 h1:I4mFys5UnxS36qT1qN9/5I9kfHZqHrk5fEPQDVh9BZc= +github.com/getsolus/libeopkg v0.1.1-0.20240404173503-db4343f6b8f8/go.mod h1:3bcRCLrRzgeb1bgshVyS5e3Z1uNX7Gi10eqkiioqXgs= github.com/getsolus/libosdev v0.0.0-20181023041421-9ab0f4b463fd h1:QZoSqUIKIFeqhImxNk1cdY7M4n8JVZxTzuhP+Y0DaK8= github.com/getsolus/libosdev v0.0.0-20181023041421-9ab0f4b463fd/go.mod h1:8P4U+IYO8T6nRPLlC6qv1wMFcc0vK0vMVDCuyiFTTLg= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= @@ -100,6 +102,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= +github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= From f6bfb869efc1c795fccef81424f1ef00871dc7ee Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Thu, 4 Apr 2024 17:14:31 -0400 Subject: [PATCH 05/11] Take local repo into account Signed-off-by: Gavin Zhao --- builder/layer.go | 3 ++- builder/manager.go | 54 ++++++++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/builder/layer.go b/builder/layer.go index 630d3cd..6a0e47a 100644 --- a/builder/layer.go +++ b/builder/layer.go @@ -62,8 +62,10 @@ func (l *Layer) BasePath() string { func (l *Layer) RequestOverlay(notif PidNotifier) (contentPath string, err error) { contentPath = filepath.Join(l.BasePath(), "content") if !PathExists(contentPath) || l.Hash() == LayersFakeHash { + slog.Info("Creating layer", "hash", l.Hash()) return l.Create(notif) } else { + slog.Info("Reusing layer", "hash", l.Hash()) return } } @@ -76,7 +78,6 @@ func (l *Layer) RemoveIfNotCreated() { } func (l *Layer) Create(notif PidNotifier) (contentPath string, err error) { - slog.Info("Creating layer", "hash", l.Hash()) basePath := l.BasePath() contentPath = filepath.Join(basePath, "content") diff --git a/builder/manager.go b/builder/manager.go index 4b62f00..a587fc0 100644 --- a/builder/manager.go +++ b/builder/manager.go @@ -401,7 +401,9 @@ func (m *Manager) Build() error { return err } - m.InitResolver() + if err := m.InitResolver(); err != nil { + return err + } slog.Debug("Successfully initialized resolver") return m.pkg.Build(m, m.history, m.GetProfile(), m.pkgManager, m.overlay, m.resolver, m.manifestTarget) @@ -553,7 +555,11 @@ func (m *Manager) InitResolver() error { for _, add := range profile.AddRepos { if repo := profile.Repos[add]; repo != nil { - repos = append(repos, repo.URI) + if repo.Local { + repos = append(repos, fmt.Sprintf("file://%s/eopkg-index.xml", repo.URI)) + } else { + repos = append(repos, repo.URI) + } } else { slog.Warn("Cannot add nonexistent repo", "name", add) } @@ -563,25 +569,37 @@ func (m *Manager) InitResolver() error { slog.Debug("Fetching repo", "url", repo) var r io.Reader - ext := path.Ext(repo) - resp, err := http.Get(repo) - if err != nil { - // slog.Error("Failed to fetch", "url", repo, "error", err) - return fmt.Errorf("Failed to fetch %s: %w", repo, err) - } - slog.Debug("Fetched") - if ext == ".xz" { - // slog.Debug("Decoding .xz") - if r, err = xz.NewReader(resp.Body); err != nil { - // slog.Error("Failed to init xz reader", "error", err) - return fmt.Errorf("Failed to init xz reader for %s: %w", repo, err) + if len(repo) > 7 && repo[0:7] == "file://" { + // Local repo + if file, err := os.Open(repo[7:]); err != nil { + return fmt.Errorf("Failed to open index file %s", repo[7:]) + } else { + r = file } - } else if ext == ".xml" { - r = resp.Body } else { - // slog.Error("Unrecognized repo url extension", "url", repo, "ext", ext) - return fmt.Errorf("Unrecognized repo url extension %s for %s", ext, repo) + // remote repo + ext := path.Ext(repo) + resp, err := http.Get(repo) + if err != nil { + // slog.Error("Failed to fetch", "url", repo, "error", err) + return fmt.Errorf("Failed to fetch %s: %w", repo, err) + } + slog.Debug("Fetched") + + // TODO: do local resolution + if ext == ".xz" { + // slog.Debug("Decoding .xz") + if r, err = xz.NewReader(resp.Body); err != nil { + // slog.Error("Failed to init xz reader", "error", err) + return fmt.Errorf("Failed to init xz reader for %s: %w", repo, err) + } + } else if ext == ".xml" { + r = resp.Body + } else { + // slog.Error("Unrecognized repo url extension", "url", repo, "ext", ext) + return fmt.Errorf("Unrecognized repo url extension %s for %s", ext, repo) + } } dec := xml.NewDecoder(r) From 626791d552b8f90687c738c55a7cc8b69ce5bdd2 Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Fri, 5 Apr 2024 21:11:42 -0400 Subject: [PATCH 06/11] Take emul32 into account when resolving deps Signed-off-by: Gavin Zhao --- builder/build.go | 4 ++-- builder/manager.go | 1 + builder/pkg.go | 3 +++ builder/resolver.go | 18 +++++++++++++++--- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/builder/build.go b/builder/build.go index a500f23..a54dec3 100644 --- a/builder/build.go +++ b/builder/build.go @@ -231,7 +231,7 @@ func (p *Package) CopyAssets(h *PackageHistory, o *Overlay) error { func (p *Package) calcDeps(resolver *Resolver) ([]Dep, error) { // hash = LayersFakeHash - return resolver.Query(p.Deps, true, true) + return resolver.Query(p.Deps, true, true, p.Emul32) } // PrepYpkg will do the initial leg work of preparing us for a ypkg build. @@ -518,6 +518,7 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro if err != nil { return fmt.Errorf("Failed to calculate dependencies: %w", err) } + slog.Debug("Calculated dependencies", "deps", deps) layer := Layer{ deps: deps, @@ -530,7 +531,6 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro return err } overlay.LayerDir = contentPath - slog.Info("Using layer", "hash", layer.Hash()) } else { return errors.New("Under testing of layers feature, XML build is not enabled yet.") } diff --git a/builder/manager.go b/builder/manager.go index a587fc0..002dbab 100644 --- a/builder/manager.go +++ b/builder/manager.go @@ -407,6 +407,7 @@ func (m *Manager) Build() error { slog.Debug("Successfully initialized resolver") return m.pkg.Build(m, m.history, m.GetProfile(), m.pkgManager, m.overlay, m.resolver, m.manifestTarget) + // TODO: should we put layer here, so we can output the hash later? } // Chroot will enter the build environment to allow users to introspect it. diff --git a/builder/pkg.go b/builder/pkg.go index 0624133..615ab30 100644 --- a/builder/pkg.go +++ b/builder/pkg.go @@ -64,6 +64,7 @@ type Package struct { CanNetwork bool // Only applicable to ypkg builds CanCCache bool // Flag to enable (s)ccache Deps []string // Build-time dependencies + Emul32 bool // Whether we are building emul32 packages } // YmlPackage is a parsed ypkg build file. @@ -76,6 +77,7 @@ type YmlPackage struct { CCache bool `yaml:"ccache"` // Disable (s)ccache for this build. BuildDeps []string `yaml:"builddeps"` CheckDeps []string `yaml:"checkdeps"` + Emul32 bool `yaml:"emul32"` } // XMLUpdate represents an update in the package history. @@ -227,6 +229,7 @@ func NewYmlPackageFromBytes(by []byte) (*Package, error) { CanNetwork: ypkg.Networking, CanCCache: ypkg.CCache, Deps: append(ypkg.BuildDeps, ypkg.CheckDeps...), + Emul32: ypkg.Emul32, } for _, row := range ypkg.Source { diff --git a/builder/resolver.go b/builder/resolver.go index 9dc83c8..37dee55 100644 --- a/builder/resolver.go +++ b/builder/resolver.go @@ -51,7 +51,7 @@ func (r *Resolver) AddIndex(i *index.Index) { } } -func (r *Resolver) Query(pkgs []string, withBase bool, withDevel bool) (res []Dep, err error) { +func (r *Resolver) Query(pkgs []string, withBase bool, withDevel bool, emul32 bool) (res []Dep, err error) { visited := make(map[string]bool) var dfs func(name string) error @@ -72,12 +72,18 @@ func (r *Resolver) Query(pkgs []string, withBase bool, withDevel bool) (res []De pkg := r.nameToPkg[name] res = append(res, Dep{Name: pkg.Name, Hash: pkg.PackageHash}) for _, dep := range r.nameToPkg[name].RuntimeDependencies { - err = dfs(dep.Name) - if err != nil { + if err = dfs(dep.Name); err != nil { return err } } + // // Take 32-bit packages into account as well + // if bit32pkg, ok := r.nameToPkg[name+"-32bit"]; ok { + // if err = dfs(bit32pkg.Name); err != nil { + // return err + // } + // } + return nil } @@ -91,6 +97,12 @@ func (r *Resolver) Query(pkgs []string, withBase bool, withDevel bool) (res []De } } + if emul32 { + for _, pkg := range []string{"glibc-32bit-devel", "libgcc-32bit", "libstdc++-32bit"} { + dfs(pkg) + } + } + for _, pkg := range pkgs { err = dfs(pkg) if err != nil { From c85226db13363a7e34bceda6a72c98ace1913568 Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Wed, 10 Apr 2024 10:52:43 -0400 Subject: [PATCH 07/11] Pull in Git for git sources Signed-off-by: Gavin Zhao --- builder/build.go | 6 +++++- builder/pkg.go | 9 +++++++++ builder/resolver.go | 9 ++++++++- builder/source/git.go | 4 ++++ builder/source/main.go | 2 ++ builder/source/simple.go | 4 ++++ 6 files changed, 32 insertions(+), 2 deletions(-) diff --git a/builder/build.go b/builder/build.go index a54dec3..3eab693 100644 --- a/builder/build.go +++ b/builder/build.go @@ -231,7 +231,11 @@ func (p *Package) CopyAssets(h *PackageHistory, o *Overlay) error { func (p *Package) calcDeps(resolver *Resolver) ([]Dep, error) { // hash = LayersFakeHash - return resolver.Query(p.Deps, true, true, p.Emul32) + if p.HasGitSource() { + return resolver.Query(p.Deps, true, true, p.Emul32, []string{"git"}) + } else { + return resolver.Query(p.Deps, true, true, p.Emul32, []string{}) + } } // PrepYpkg will do the initial leg work of preparing us for a ypkg build. diff --git a/builder/pkg.go b/builder/pkg.go index 615ab30..7fdb606 100644 --- a/builder/pkg.go +++ b/builder/pkg.go @@ -257,3 +257,12 @@ func NewYmlPackageFromBytes(by []byte) (*Package, error) { return ret, nil } + +func (p *Package) HasGitSource() bool { + for _, source := range p.Sources { + if source.IsGit() { + return true + } + } + return false +} diff --git a/builder/resolver.go b/builder/resolver.go index 37dee55..cd9a9fb 100644 --- a/builder/resolver.go +++ b/builder/resolver.go @@ -51,7 +51,7 @@ func (r *Resolver) AddIndex(i *index.Index) { } } -func (r *Resolver) Query(pkgs []string, withBase bool, withDevel bool, emul32 bool) (res []Dep, err error) { +func (r *Resolver) Query(pkgs []string, withBase bool, withDevel bool, emul32 bool, extras []string) (res []Dep, err error) { visited := make(map[string]bool) var dfs func(name string) error @@ -110,6 +110,13 @@ func (r *Resolver) Query(pkgs []string, withBase bool, withDevel bool, emul32 bo } } + for _, pkg := range extras { + err = dfs(pkg) + if err != nil { + return + } + } + slices.SortFunc(res, func(a, b Dep) int { return cmp.Compare(a.Name, b.Name) }) return } diff --git a/builder/source/git.go b/builder/source/git.go index 3ca5022..8a3ec8b 100644 --- a/builder/source/git.go +++ b/builder/source/git.go @@ -39,6 +39,10 @@ type GitSource struct { ClonePath string // This is where we will have cloned into } +func (s *GitSource) IsGit() bool { + return true +} + // NewGit will create a new GitSource for the given URI & ref combination. func NewGit(uri, ref string) (*GitSource, error) { // Ensure we have a valid URL first. diff --git a/builder/source/main.go b/builder/source/main.go index f7e3760..314ce55 100644 --- a/builder/source/main.go +++ b/builder/source/main.go @@ -63,6 +63,8 @@ type Source interface { // GetIdentifier will return the appropriate representation for a given // source URL. GetIdentifier() string + + IsGit() bool } // New will return a new source for the specified URL. diff --git a/builder/source/simple.go b/builder/source/simple.go index 25a959a..c174cff 100644 --- a/builder/source/simple.go +++ b/builder/source/simple.go @@ -47,6 +47,10 @@ type SimpleSource struct { url *url.URL } +func (s *SimpleSource) IsGit() bool { + return false +} + // NewSimple will create a new source instance. func NewSimple(uri, validator string, legacy bool) (*SimpleSource, error) { // Ensure the URI is actually valid. From 6fc43b9288e5363f19632ead32cdb57fcf5ce5b9 Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Thu, 13 Jun 2024 22:04:23 -0400 Subject: [PATCH 08/11] Fix missing clang and (s)ccache Signed-off-by: Gavin Zhao --- builder/build.go | 15 ++++++++++++--- builder/pkg.go | 3 +++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/builder/build.go b/builder/build.go index 3eab693..05d67ce 100644 --- a/builder/build.go +++ b/builder/build.go @@ -231,11 +231,20 @@ func (p *Package) CopyAssets(h *PackageHistory, o *Overlay) error { func (p *Package) calcDeps(resolver *Resolver) ([]Dep, error) { // hash = LayersFakeHash + extras := []string{} + if p.HasGitSource() { - return resolver.Query(p.Deps, true, true, p.Emul32, []string{"git"}) - } else { - return resolver.Query(p.Deps, true, true, p.Emul32, []string{}) + extras = append(extras, "git") + } + if p.Clang { + extras = append(extras, "llvm-clang-devel") } + if p.CanCCache { + extras = append(extras, "ccache", "sccache") + } + + slog.Debug("Extra dependencyes from recipe", "extras", extras) + return resolver.Query(p.Deps, true, true, p.Emul32, extras) } // PrepYpkg will do the initial leg work of preparing us for a ypkg build. diff --git a/builder/pkg.go b/builder/pkg.go index 7fdb606..0c2e203 100644 --- a/builder/pkg.go +++ b/builder/pkg.go @@ -65,6 +65,7 @@ type Package struct { CanCCache bool // Flag to enable (s)ccache Deps []string // Build-time dependencies Emul32 bool // Whether we are building emul32 packages + Clang bool // Whether we're using LLVM toolchain } // YmlPackage is a parsed ypkg build file. @@ -78,6 +79,7 @@ type YmlPackage struct { BuildDeps []string `yaml:"builddeps"` CheckDeps []string `yaml:"checkdeps"` Emul32 bool `yaml:"emul32"` + Clang bool `yaml:"clang"` } // XMLUpdate represents an update in the package history. @@ -230,6 +232,7 @@ func NewYmlPackageFromBytes(by []byte) (*Package, error) { CanCCache: ypkg.CCache, Deps: append(ypkg.BuildDeps, ypkg.CheckDeps...), Emul32: ypkg.Emul32, + Clang: ypkg.Clang, } for _, row := range ypkg.Source { From fe37dd61a9e2badece6cf795cb37292c47819105 Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Thu, 13 Jun 2024 22:26:23 -0400 Subject: [PATCH 09/11] Cleanup incomplete layer if error/terminated Signed-off-by: Gavin Zhao --- builder/build.go | 4 ++-- builder/layer.go | 2 +- builder/manager.go | 36 +++++++++++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/builder/build.go b/builder/build.go index 05d67ce..6c1c92a 100644 --- a/builder/build.go +++ b/builder/build.go @@ -229,7 +229,7 @@ func (p *Package) CopyAssets(h *PackageHistory, o *Overlay) error { return h.WriteXML(histPath) } -func (p *Package) calcDeps(resolver *Resolver) ([]Dep, error) { +func (p *Package) CalcDeps(resolver *Resolver) ([]Dep, error) { // hash = LayersFakeHash extras := []string{} @@ -527,7 +527,7 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro // Set up layers caching, only for YPKG if p.Type == PackageTypeYpkg { - deps, err := p.calcDeps(resolver) + deps, err := p.CalcDeps(resolver) if err != nil { return fmt.Errorf("Failed to calculate dependencies: %w", err) } diff --git a/builder/layer.go b/builder/layer.go index 6a0e47a..c277c70 100644 --- a/builder/layer.go +++ b/builder/layer.go @@ -71,8 +71,8 @@ func (l *Layer) RequestOverlay(notif PidNotifier) (contentPath string, err error } func (l *Layer) RemoveIfNotCreated() { - slog.Debug("Layer not fully created, removing...", "path", l.BasePath()) if !l.created { + slog.Debug("Removing incomplete layer", "path", l.BasePath()) os.RemoveAll(l.BasePath()) } } diff --git a/builder/manager.go b/builder/manager.go index 002dbab..d817d58 100644 --- a/builder/manager.go +++ b/builder/manager.go @@ -78,6 +78,7 @@ type Manager struct { pkgManager *EopkgManager // Package manager, if any lock *sync.Mutex // Lock on all operations to prevent.. damage. profile *Profile // The profile we've been requested to use + layer *Layer resolver *Resolver lockfile *LockFile // We track the global lock for each operation @@ -318,6 +319,11 @@ func (m *Manager) Cleanup() { // Unmount anything we may have mounted disk.GetMountManager().UnmountAll() + // Remove the layer if it's unfinished + if m.layer != nil { + m.layer.RemoveIfNotCreated() + } + // Finally clean out the lock files if m.lockfile != nil { if err := m.lockfile.Unlock(); err != nil { @@ -406,10 +412,36 @@ func (m *Manager) Build() error { } slog.Debug("Successfully initialized resolver") + if err := m.prepareLayer(); err != nil { + return fmt.Errorf("Failed to prepare layer: %w", err) + } + return m.pkg.Build(m, m.history, m.GetProfile(), m.pkgManager, m.overlay, m.resolver, m.manifestTarget) // TODO: should we put layer here, so we can output the hash later? } +func (m *Manager) prepareLayer() error { + p := m.pkg + deps, err := p.CalcDeps(m.resolver) + if err != nil { + return fmt.Errorf("Failed to calculate dependencies: %w", err) + } + slog.Debug("Calculated dependencies", "deps", deps) + + m.layer = &Layer{ + deps: deps, + profile: m.profile, + back: m.overlay.Back, + } + + contentPath, err := m.layer.RequestOverlay(m) + if err != nil { + return err + } + m.overlay.LayerDir = contentPath + return nil +} + // Chroot will enter the build environment to allow users to introspect it. func (m *Manager) Chroot() error { if m.IsCancelled() { @@ -572,7 +604,7 @@ func (m *Manager) InitResolver() error { var r io.Reader if len(repo) > 7 && repo[0:7] == "file://" { - // Local repo + // local repo if file, err := os.Open(repo[7:]); err != nil { return fmt.Errorf("Failed to open index file %s", repo[7:]) } else { @@ -586,9 +618,7 @@ func (m *Manager) InitResolver() error { // slog.Error("Failed to fetch", "url", repo, "error", err) return fmt.Errorf("Failed to fetch %s: %w", repo, err) } - slog.Debug("Fetched") - // TODO: do local resolution if ext == ".xz" { // slog.Debug("Decoding .xz") if r, err = xz.NewReader(resp.Body); err != nil { From e44ffa8b7d01eb93005163660e0bfb7e10d7e372 Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Fri, 21 Jun 2024 10:46:57 -0400 Subject: [PATCH 10/11] Use base58 to calculate hash and fix cleanup logic Signed-off-by: Gavin Zhao --- builder/build.go | 23 ----------------------- builder/layer.go | 10 ++++++---- builder/main.go | 2 +- builder/manager.go | 44 ++++++++++++++++++++++---------------------- go.mod | 1 + go.sum | 34 ++++++++++++++++++++++++++++++++++ 6 files changed, 64 insertions(+), 50 deletions(-) diff --git a/builder/build.go b/builder/build.go index 6c1c92a..61f66d5 100644 --- a/builder/build.go +++ b/builder/build.go @@ -525,29 +525,6 @@ func (p *Package) Build(notif PidNotifier, history *PackageHistory, profile *Pro ChrootEnvironment = env - // Set up layers caching, only for YPKG - if p.Type == PackageTypeYpkg { - deps, err := p.CalcDeps(resolver) - if err != nil { - return fmt.Errorf("Failed to calculate dependencies: %w", err) - } - slog.Debug("Calculated dependencies", "deps", deps) - - layer := Layer{ - deps: deps, - profile: profile, - back: overlay.Back, - } - - contentPath, err := layer.RequestOverlay(notif) - if err != nil { - return err - } - overlay.LayerDir = contentPath - } else { - return errors.New("Under testing of layers feature, XML build is not enabled yet.") - } - // Set up environment if err := overlay.CleanExisting(); err != nil { return err diff --git a/builder/layer.go b/builder/layer.go index c277c70..dab26e6 100644 --- a/builder/layer.go +++ b/builder/layer.go @@ -1,7 +1,6 @@ package builder import ( - "encoding/base64" "encoding/json" "fmt" "log/slog" @@ -9,6 +8,7 @@ import ( "path/filepath" "strings" + "github.com/btcsuite/btcutil/base58" "github.com/zeebo/blake3" ) @@ -16,6 +16,7 @@ type Layer struct { deps []Dep profile *Profile back *BackingImage + // Note: created is only set in `RequestOverlay` created bool hash string } @@ -48,11 +49,10 @@ func (l *Layer) Hash() string { l.hash = LayersFakeHash } else { hashBytes := blake3.Sum256(jsonBytes) - l.hash = base64.StdEncoding.EncodeToString(hashBytes[:]) + l.hash = base58.Encode(hashBytes[:]) } } return l.hash - } func (l *Layer) BasePath() string { @@ -65,6 +65,7 @@ func (l *Layer) RequestOverlay(notif PidNotifier) (contentPath string, err error slog.Info("Creating layer", "hash", l.Hash()) return l.Create(notif) } else { + l.created = true slog.Info("Reusing layer", "hash", l.Hash()) return } @@ -72,7 +73,7 @@ func (l *Layer) RequestOverlay(notif PidNotifier) (contentPath string, err error func (l *Layer) RemoveIfNotCreated() { if !l.created { - slog.Debug("Removing incomplete layer", "path", l.BasePath()) + slog.Info("Removing incomplete layer", "path", l.BasePath()) os.RemoveAll(l.BasePath()) } } @@ -170,5 +171,6 @@ func (l *Layer) Create(notif PidNotifier) (contentPath string, err error) { } notif.SetActivePID(0) + l.created = true return } diff --git a/builder/main.go b/builder/main.go index 9ff59e7..33b534a 100644 --- a/builder/main.go +++ b/builder/main.go @@ -51,7 +51,7 @@ const ( // LayersDir is where container layers are cached, identified by their // sha256 hashes, e.g. `/var/cache/solbuild/layers/3c0de53d6017469...` LayersDir = "/var/cache/solbuild/layers" - // sha256sum | awk '{ print $1 }' | xxd -r -p | base64 + // sha256sum | awk '{ print $1 }' | xxd -r -p | base58 LayersFakeHash = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" ) diff --git a/builder/manager.go b/builder/manager.go index d817d58..ee8ed17 100644 --- a/builder/manager.go +++ b/builder/manager.go @@ -420,28 +420,6 @@ func (m *Manager) Build() error { // TODO: should we put layer here, so we can output the hash later? } -func (m *Manager) prepareLayer() error { - p := m.pkg - deps, err := p.CalcDeps(m.resolver) - if err != nil { - return fmt.Errorf("Failed to calculate dependencies: %w", err) - } - slog.Debug("Calculated dependencies", "deps", deps) - - m.layer = &Layer{ - deps: deps, - profile: m.profile, - back: m.overlay.Back, - } - - contentPath, err := m.layer.RequestOverlay(m) - if err != nil { - return err - } - m.overlay.LayerDir = contentPath - return nil -} - // Chroot will enter the build environment to allow users to introspect it. func (m *Manager) Chroot() error { if m.IsCancelled() { @@ -646,3 +624,25 @@ func (m *Manager) InitResolver() error { return nil } + +func (m *Manager) prepareLayer() error { + p := m.pkg + deps, err := p.CalcDeps(m.resolver) + if err != nil { + return fmt.Errorf("Failed to calculate dependencies: %w", err) + } + slog.Debug("Calculated dependencies", "deps", deps) + + m.layer = &Layer{ + deps: deps, + profile: m.profile, + back: m.overlay.Back, + } + + contentPath, err := m.layer.RequestOverlay(m) + if err != nil { + return err + } + m.overlay.LayerDir = contentPath + return nil +} diff --git a/go.mod b/go.mod index ac1810a..7089d9c 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.23.1 require ( github.com/BurntSushi/toml v1.4.0 github.com/DataDrake/cli-ng/v2 v2.0.2 + github.com/btcsuite/btcutil v1.0.2 github.com/cavaliergopher/grab/v3 v3.0.1 github.com/charlievieth/fastwalk v1.0.9 github.com/cheggaaa/pb/v3 v3.1.5 diff --git a/go.sum b/go.sum index 5a5ddd9..3b1a87e 100644 --- a/go.sum +++ b/go.sum @@ -11,10 +11,21 @@ github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXx github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow= github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4= github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4= github.com/charlievieth/fastwalk v1.0.9 h1:Odb92AfoReO3oFBfDGT5J+nwgzQPF/gWAw6E6/lkor0= @@ -27,6 +38,7 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -36,6 +48,7 @@ github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/getsolus/libeopkg v0.1.1-0.20240404173503-db4343f6b8f8 h1:I4mFys5UnxS36qT1qN9/5I9kfHZqHrk5fEPQDVh9BZc= github.com/getsolus/libeopkg v0.1.1-0.20240404173503-db4343f6b8f8/go.mod h1:3bcRCLrRzgeb1bgshVyS5e3Z1uNX7Gi10eqkiioqXgs= github.com/getsolus/libosdev v0.0.0-20181023041421-9ab0f4b463fd h1:QZoSqUIKIFeqhImxNk1cdY7M4n8JVZxTzuhP+Y0DaK8= @@ -55,12 +68,17 @@ github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -77,6 +95,9 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= @@ -114,14 +135,23 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= gitlab.com/slxh/go/powerline v0.1.0 h1:/3lwpGRD5yW9HFS/hammtCI4kvtjKw8E1dcpHS9Udx8= gitlab.com/slxh/go/powerline v0.1.0/go.mod h1:vBTN83xoDyGejdTeZkMGs8l/qZvOjpUkRMYrthNhqJE= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -135,6 +165,7 @@ golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= @@ -143,10 +174,13 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 804e83e08fe1dc57f28c5ec97e390ed16d72d8f9 Mon Sep 17 00:00:00 2001 From: Gavin Zhao Date: Tue, 25 Jun 2024 20:54:34 -0400 Subject: [PATCH 11/11] fix: report error if failed to remove layer Signed-off-by: Gavin Zhao --- builder/layer.go | 6 ++++-- builder/manager.go | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/builder/layer.go b/builder/layer.go index dab26e6..051433c 100644 --- a/builder/layer.go +++ b/builder/layer.go @@ -71,10 +71,12 @@ func (l *Layer) RequestOverlay(notif PidNotifier) (contentPath string, err error } } -func (l *Layer) RemoveIfNotCreated() { +func (l *Layer) RemoveIfNotCreated() error { if !l.created { slog.Info("Removing incomplete layer", "path", l.BasePath()) - os.RemoveAll(l.BasePath()) + return os.RemoveAll(l.BasePath()) + } else { + return nil } } diff --git a/builder/manager.go b/builder/manager.go index ee8ed17..111796f 100644 --- a/builder/manager.go +++ b/builder/manager.go @@ -321,7 +321,9 @@ func (m *Manager) Cleanup() { // Remove the layer if it's unfinished if m.layer != nil { - m.layer.RemoveIfNotCreated() + if err := m.layer.RemoveIfNotCreated(); err != nil { + slog.Error("Failure in cleaning incomplete layer", "err", err) + } } // Finally clean out the lock files