jsonnet-bundler/pkg/http.go

107 lines
2.5 KiB
Go
Raw Normal View History

// Copyright 2018 jsonnet-bundler authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package pkg
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"github.com/jsonnet-bundler/jsonnet-bundler/spec/v1/deps"
"github.com/pkg/errors"
"io"
"io/ioutil"
"net/http"
"os"
"path"
"path/filepath"
"strings"
)
type HttpPackage struct {
Source *deps.Http
}
func NewHttpPackage(source *deps.Http) Interface {
return &HttpPackage{
Source: source,
}
}
func downloadFile(filepath string, url string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
if resp.StatusCode != 200 {
return fmt.Errorf("unexpected status code %d", resp.StatusCode)
}
defer resp.Body.Close()
// Create the file
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
// Write the body to file
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}
func (h *HttpPackage) Install(ctx context.Context, name, dir, version string) (string, error) {
destPath := path.Join(dir, name)
pkgh := sha256.Sum256([]byte(fmt.Sprintf("jsonnetpkg-%s-%s", strings.Replace(name, "/", "-", -1), strings.Replace(version, "/", "-", -1))))
// using 16 bytes should be a good middle ground between length and collision resistance
tmpDir, err := ioutil.TempDir(filepath.Join(dir, ".tmp"), hex.EncodeToString(pkgh[:16]))
if err != nil {
return "", errors.Wrap(err, "failed to create tmp dir")
}
defer os.RemoveAll(tmpDir)
err = os.Setenv("VERSION", version)
if err != nil {
return "", err
}
url := os.ExpandEnv(h.Source.Url)
filename := filepath.Base(url)
err = downloadFile(path.Join(tmpDir, filename), url)
if err != nil {
return "", errors.Wrap(err, "failed to download file")
}
var ar *os.File
ar, err = os.Open(path.Join(tmpDir, filename))
if err != nil {
return "", errors.Wrap(err, "failed to open downloaded archive")
}
defer ar.Close()
err = GzipUntar(destPath, ar, "")
if err != nil {
return "", errors.Wrap(err, "failed to unpack downloaded archive")
}
return version, nil
}