feat: rewrite install procedure

rewrites the installation of packages from scratch to solve several issues with
the existing implementation:

- does not need to choose between lockfile and jsonnetfile anymore. The
jsonnetfile what to be installed, while the lockfile also has versions and
checksums of all packages, even nested ones.
- the lockfile is regenerated on every run, preserving the locked values
- downloaded packages are hashed using sha256 to make sure we receive what we
expect. If files on the local disk are modified, they are downloaded again.
This commit is contained in:
sh0rez 2019-10-16 16:34:53 +02:00
parent 71938456ae
commit 36311f1601
No known key found for this signature in database
GPG key ID: 87C71DF9F8181FF1
5 changed files with 129 additions and 155 deletions

View file

@ -15,12 +15,12 @@
package main
import (
"context"
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"github.com/pkg/errors"
kingpin "gopkg.in/alecthomas/kingpin.v2"
"github.com/jsonnet-bundler/jsonnet-bundler/pkg"
@ -28,92 +28,52 @@ import (
"github.com/jsonnet-bundler/jsonnet-bundler/spec"
)
func installCommand(dir, jsonnetHome string, uris ...string) int {
func installCommand(dir, jsonnetHome string, uris []string) int {
if dir == "" {
dir = "."
}
filename, isLock, err := jsonnetfile.Choose(dir)
if err != nil {
kingpin.Fatalf("failed to choose jsonnetfile: %v", err)
return 1
kingpin.FatalIfError(
os.MkdirAll(filepath.Join(dir, "vendor", ".tmp"), os.ModePerm),
"creating vendor/ folder")
jsonnetFile, err := jsonnetfile.Load(filepath.Join(dir, jsonnetfile.File))
kingpin.FatalIfError(err, "failed to load jsonnetfile")
for _, u := range uris {
d := parseDependency(dir, u)
jsonnetFile.Dependencies = append(jsonnetFile.Dependencies, *d)
}
jsonnetFile, err := jsonnetfile.Load(filename)
if err != nil {
kingpin.Fatalf("failed to load jsonnetfile: %v", err)
return 1
lockFile, err := jsonnetfile.Load(filepath.Join(dir, jsonnetfile.LockFile))
if !os.IsNotExist(err) {
kingpin.FatalIfError(err, "failed to load lockfile")
}
if len(uris) > 0 {
for _, uri := range uris {
newDep := parseDependency(dir, uri)
if newDep == nil {
kingpin.Errorf("ignoring unrecognized uri: %s", uri)
continue
}
oldDeps := jsonnetFile.Dependencies
newDeps := []spec.Dependency{}
oldDepReplaced := false
for _, d := range oldDeps {
if d.Name == newDep.Name {
newDeps = append(newDeps, *newDep)
oldDepReplaced = true
} else {
newDeps = append(newDeps, d)
}
}
if !oldDepReplaced {
newDeps = append(newDeps, *newDep)
}
jsonnetFile.Dependencies = newDeps
}
locks := make(map[string]spec.Dependency)
for _, d := range lockFile.Dependencies {
locks[d.Name] = d
}
srcPath := filepath.Join(jsonnetHome)
err = os.MkdirAll(srcPath, os.ModePerm)
if err != nil {
kingpin.Fatalf("failed to create jsonnet home path: %v", err)
return 3
}
locked, err := pkg.Ensure(jsonnetFile, jsonnetHome, locks)
kingpin.FatalIfError(err, "failed to install packages")
lock, err := pkg.Install(context.TODO(), isLock, filename, jsonnetFile, jsonnetHome)
if err != nil {
kingpin.Fatalf("failed to install: %v", err)
return 3
}
// If installing from lock file there is no need to write any files back.
if !isLock {
b, err := json.MarshalIndent(jsonnetFile, "", " ")
if err != nil {
kingpin.Fatalf("failed to encode jsonnet file: %v", err)
return 3
}
b = append(b, []byte("\n")...)
err = ioutil.WriteFile(filepath.Join(dir, jsonnetfile.File), b, 0644)
if err != nil {
kingpin.Fatalf("failed to write jsonnet file: %v", err)
return 3
}
b, err = json.MarshalIndent(lock, "", " ")
if err != nil {
kingpin.Fatalf("failed to encode jsonnet file: %v", err)
return 3
}
b = append(b, []byte("\n")...)
err = ioutil.WriteFile(filepath.Join(dir, jsonnetfile.LockFile), b, 0644)
if err != nil {
kingpin.Fatalf("failed to write lock file: %v", err)
return 3
}
}
kingpin.FatalIfError(
writeJSONFile(filepath.Join(dir, jsonnetfile.File), jsonnetFile),
"updating jsonnetfile.json")
kingpin.FatalIfError(
writeJSONFile(filepath.Join(dir, jsonnetfile.LockFile), spec.JsonnetFile{Dependencies: locked}),
"updating jsonnetfile.lock.json")
return 0
}
func writeJSONFile(name string, d interface{}) error {
b, err := json.MarshalIndent(d, "", " ")
if err != nil {
return errors.Wrap(err, "encoding json")
}
b = append(b, []byte("\n")...)
return ioutil.WriteFile(name, b, 0644)
}