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 }