272 lines
4.8 KiB
Go
272 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"archive/zip"
|
|
"encoding/json"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"git.trj.tw/golang/utils"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var version string
|
|
var workdir string
|
|
var downloadDir = os.TempDir()
|
|
var fileName = "koatmpl.zip"
|
|
|
|
func init() {
|
|
flag.StringVar(&version, "version", "", "template version")
|
|
flag.StringVar(&workdir, "wd", "", "working directory")
|
|
flag.Parse()
|
|
}
|
|
|
|
const apiHost = "https://git.trj.tw"
|
|
const apiPath = "/api/v1/repos/nodejs/koa-template/releases"
|
|
|
|
type Commit struct {
|
|
URL string `json:"url"`
|
|
SHA string `json:"sha"`
|
|
}
|
|
type Tag struct {
|
|
Name string `json:"name"`
|
|
ID string `json:"id"`
|
|
Commit Commit `json:"commit"`
|
|
ZipballURL string `json:"zipball_url"`
|
|
TarballURL string `json:"tarball_url"`
|
|
}
|
|
|
|
type Asset struct {
|
|
ID int `json:"id"`
|
|
Name string `json:"name"`
|
|
Size int64 `json:"size"`
|
|
DownloadCount int `json:"download_count"`
|
|
CreatedAt string `json:"created_at"`
|
|
UUID string `json:"uuid"`
|
|
BrowserDownloadURL string `json:"browser_download_url"`
|
|
}
|
|
type Release struct {
|
|
ID int `json:"id"`
|
|
TagName string `json:"tag_name"`
|
|
TargetCommitish string `json:"target_commitish"`
|
|
Name string `json:"name"`
|
|
Body string `json:"body"`
|
|
URL string `json:"url"`
|
|
TarballURL string `json:"tarball_url"`
|
|
ZipballURL string `json:"zipball_url"`
|
|
Draft bool `json:"draft"`
|
|
Prerelease bool `json:"prerelease"`
|
|
CreatedAt string `json:"created_at"`
|
|
PublishedAt string `json:"published_at"`
|
|
Assets []Asset `json:"assets"`
|
|
}
|
|
|
|
func main() {
|
|
args := flag.Args()
|
|
|
|
if len(workdir) > 0 {
|
|
workdir = utils.ParsePath(workdir)
|
|
if !utils.IsDir(workdir) {
|
|
log.Fatalf("target directory not exists")
|
|
}
|
|
}
|
|
|
|
if len(args) == 0 {
|
|
// download
|
|
err := downloadZipball()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
err = Unzip()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Println("Success")
|
|
return
|
|
}
|
|
|
|
switch strings.ToLower(args[0]) {
|
|
case "list":
|
|
list, err := getTagList()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Println("Release:")
|
|
for _, v := range list {
|
|
fmt.Println(v)
|
|
}
|
|
break
|
|
default:
|
|
log.Fatalf("argv not match")
|
|
}
|
|
|
|
}
|
|
|
|
func Unzip() (err error) {
|
|
wd, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(workdir) > 0 {
|
|
wd = workdir
|
|
}
|
|
|
|
r, err := zip.OpenReader(path.Join(downloadDir, fileName))
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer r.Close()
|
|
|
|
for _, f := range r.File {
|
|
fpath := filepath.Join(wd, f.Name)
|
|
|
|
if !strings.HasPrefix(fpath, filepath.Clean(wd)+string(os.PathSeparator)) {
|
|
return fmt.Errorf("%s: illegal file path", fpath)
|
|
}
|
|
|
|
if f.FileInfo().IsDir() {
|
|
if err := os.MkdirAll(fpath, 0775); err != nil {
|
|
return err
|
|
}
|
|
continue
|
|
}
|
|
|
|
if err := os.MkdirAll(filepath.Dir(fpath), 0775); err != nil && err != os.ErrExist {
|
|
return err
|
|
}
|
|
|
|
outFile, err := os.Create(fpath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer outFile.Close()
|
|
|
|
rc, err := f.Open()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer rc.Close()
|
|
|
|
_, err = io.Copy(outFile, rc)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func downloadZipball() (err error) {
|
|
latest := true
|
|
if len(version) > 0 {
|
|
latest = false
|
|
}
|
|
|
|
tags, err := getList()
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(tags) == 0 {
|
|
return errors.New("no release tag")
|
|
}
|
|
|
|
link := ""
|
|
if latest == false {
|
|
for _, v := range tags {
|
|
if v.TagName == version {
|
|
for _, it := range v.Assets {
|
|
if it.Name == "release.zip" {
|
|
link = it.BrowserDownloadURL
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
for _, v := range tags[0].Assets {
|
|
if v.Name == "release.zip" {
|
|
link = v.BrowserDownloadURL
|
|
}
|
|
}
|
|
}
|
|
if len(link) == 0 {
|
|
return errors.New("get download link fail")
|
|
}
|
|
|
|
resp, err := http.DefaultClient.Get(link)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
f, err := os.Create(path.Join(downloadDir, fileName))
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
_, err = io.Copy(f, resp.Body)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func getList() (tags []Release, err error) {
|
|
u, err := url.Parse(apiHost)
|
|
if err != nil {
|
|
return
|
|
}
|
|
u, err = u.Parse(apiPath)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
req, err := http.NewRequest("GET", u.String(), nil)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
logrus.Debugf("Try send request to api: %s\n", u.String())
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body := make([]Release, 0)
|
|
|
|
b, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = json.Unmarshal(b, &body)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return body, nil
|
|
}
|
|
|
|
func getTagList() (tags []string, err error) {
|
|
body, err := getList()
|
|
|
|
tags = make([]string, 0, len(body))
|
|
for _, v := range body {
|
|
tags = append(tags, v.TagName)
|
|
}
|
|
|
|
return
|
|
}
|