koa-init/main.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
}