diff --git a/db/installed.go b/db/installed.go new file mode 100644 index 0000000..14f3a3a --- /dev/null +++ b/db/installed.go @@ -0,0 +1,70 @@ +package db + +import ( + "encoding/json" + "os" + "path/filepath" + + "github.com/pkg/errors" + "mcquay.me/fs" + "mcquay.me/pm" +) + +const in = "var/lib/pm/installed.json" + +// AddInstalled adds m to the installed package database. +func AddInstalled(root string, m pm.Meta) error { + db, err := loadi(root) + if err != nil { + return errors.Wrap(err, "loading installed db") + } + db[m.Name] = m + return savei(root, db) +} + +// IsInstalled checks if m is in the installed package database. +func IsInstalled(root string, m pm.Meta) (bool, error) { + db, err := loadi(root) + if err != nil { + return false, errors.Wrap(err, "loading installed db") + } + + _, r := db[m.Name] + return r, nil +} + +func loadi(root string) (pm.Installed, error) { + r := pm.Installed{} + dbn := filepath.Join(root, in) + + if !fs.Exists(dbn) { + return r, nil + } + + f, err := os.Open(dbn) + if err != nil { + return r, errors.Wrap(err, "open") + } + + if err := json.NewDecoder(f).Decode(&r); err != nil { + return r, errors.Wrap(err, "decoding db") + } + + return r, nil +} + +func savei(root string, db pm.Installed) error { + f, err := os.Create(filepath.Join(root, in)) + if err != nil { + return errors.Wrap(err, "create") + } + enc := json.NewEncoder(f) + enc.SetIndent("", "\t") + if err := enc.Encode(&db); err != nil { + return errors.Wrap(err, "decoding db") + } + if err := f.Close(); err != nil { + return errors.Wrap(err, "close db") + } + return nil +} diff --git a/installed.go b/installed.go new file mode 100644 index 0000000..50ebdbd --- /dev/null +++ b/installed.go @@ -0,0 +1,4 @@ +package pm + +// Installed tracks installed packages. +type Installed map[Name]Meta diff --git a/pkg/install.go b/pkg/install.go index c932832..f907342 100644 --- a/pkg/install.go +++ b/pkg/install.go @@ -60,6 +60,13 @@ func Install(root string, pkgs []string) error { } for _, m := range ms { + already, err := db.IsInstalled(root, m) + if err != nil { + return errors.Wrapf(err, "is installed %v", m.Name) + } + if already { + return errors.Errorf("%v already installed!", m.Name) + } if err := verifyManifestIntegrity(root, m); err != nil { return errors.Wrap(err, "verifying pkg integrity") } @@ -85,6 +92,10 @@ func Install(root string, pkgs []string) error { if err := os.Remove(filepath.Join(cacheDir, m.Pkg())); err != nil { return errors.Wrapf(err, "cleaning up pkg %v", m.Pkg()) } + + if err := db.AddInstalled(root, m); err != nil { + return errors.Wrapf(err, "adding ", m.Name) + } } return nil }