Files
gitea-release-resource/in_command.go
2015-10-27 15:01:02 -07:00

175 lines
3.6 KiB
Go

package resource
import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strconv"
"github.com/zachgersh/go-github/github"
)
type InCommand struct {
github GitHub
writer io.Writer
}
func NewInCommand(github GitHub, writer io.Writer) *InCommand {
return &InCommand{
github: github,
writer: writer,
}
}
func (c *InCommand) Run(destDir string, request InRequest) (InResponse, error) {
err := os.MkdirAll(destDir, 0755)
if err != nil {
return InResponse{}, err
}
var foundRelease *github.RepositoryRelease
if request.Version.Tag != "" {
foundRelease, err = c.github.GetReleaseByTag(request.Version.Tag)
} else {
id, _ := strconv.Atoi(request.Version.ID)
foundRelease, err = c.github.GetRelease(id)
}
if err != nil {
return InResponse{}, err
}
if foundRelease == nil {
return InResponse{}, errors.New("no releases")
}
if foundRelease.TagName != nil && *foundRelease.TagName != "" {
tagPath := filepath.Join(destDir, "tag")
err = ioutil.WriteFile(tagPath, []byte(*foundRelease.TagName), 0644)
if err != nil {
return InResponse{}, err
}
version := determineVersionFromTag(*foundRelease.TagName)
versionPath := filepath.Join(destDir, "version")
err = ioutil.WriteFile(versionPath, []byte(version), 0644)
if err != nil {
return InResponse{}, err
}
}
assets, err := c.github.ListReleaseAssets(*foundRelease)
if err != nil {
return InResponse{}, err
}
for _, asset := range assets {
path := filepath.Join(destDir, *asset.Name)
var matchFound bool
if len(request.Params.Globs) == 0 {
matchFound = true
} else {
for _, glob := range request.Params.Globs {
matches, err := filepath.Match(glob, *asset.Name)
if err != nil {
return InResponse{}, err
}
if matches {
matchFound = true
break
}
}
}
if !matchFound {
continue
}
fmt.Fprintf(c.writer, "downloading asset: %s\n", *asset.Name)
err := c.downloadAsset(asset, path)
if err != nil {
return InResponse{}, err
}
}
if request.Params.IncludeSourceTarball {
u, err := c.github.GetTarballLink(request.Version.Tag)
if err != nil {
return InResponse{}, err
}
fmt.Fprintln(c.writer, "downloading source tarball to source.tar.gz")
if err := c.downloadFile(u.String(), filepath.Join(destDir, "source.tar.gz")); err != nil {
return InResponse{}, err
}
}
if request.Params.IncludeSourceZip {
u, err := c.github.GetZipballLink(request.Version.Tag)
if err != nil {
return InResponse{}, err
}
fmt.Fprintln(c.writer, "downloading source zip to source.zip")
if err := c.downloadFile(u.String(), filepath.Join(destDir, "source.zip")); err != nil {
return InResponse{}, err
}
}
return InResponse{
Version: versionFromRelease(foundRelease),
Metadata: metadataFromRelease(foundRelease),
}, nil
}
func (c *InCommand) downloadAsset(asset github.ReleaseAsset, destPath string) error {
out, err := os.Create(destPath)
if err != nil {
return err
}
defer out.Close()
content, err := c.github.DownloadReleaseAsset(asset)
if err != nil {
return err
}
defer content.Close()
_, err = io.Copy(out, content)
if err != nil {
return err
}
return nil
}
func (c *InCommand) downloadFile(url, destPath string) error {
out, err := os.Create(destPath)
if err != nil {
return err
}
defer out.Close()
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to download file `%s`: HTTP status %d", filepath.Base(destPath), resp.StatusCode)
}
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}