package pr import ( "crypto/tls" "encoding/json" "fmt" "io/ioutil" "net/http" "net/url" "os" "path" "sort" "strconv" "strings" "text/tabwriter" "git.sr.ht/~avanier/gitea-resource/util" ) // List returns a slice of PRs func List(stdinPayload util.STDINPayload) { var ( err error stdoutVersions []stdoutVersion ) if stdinPayload.Source.SkipSSLVerification { http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} } client := &http.Client{} req, err := http.NewRequest("GET", composeAllPrURL(stdinPayload.Source), nil) if !stdinPayload.Source.Insecure && len(stdinPayload.Source.AccessToken) > 0 { req.Header.Add("Authorization", stdinPayload.Source.AccessToken) } response, err := client.Do(req) util.CheckResponse(response) /* CAVEAT EMPTOR This does not page. So, for some reason if you have more than 50 PRs addeed since you last checked, or you run this for the first time, and you set version to `every`, this will only show the 50 first. You can either change Gitea's number of API items returned, or create a PR a pager here. https://docs.gitea.io/en-us/api-usage/ */ if err != nil { util.HandleError(err) } data, _ := ioutil.ReadAll(response.Body) prs := []pr{} // Slice of PRs err = json.Unmarshal(data, &prs) if err != nil { util.HandleError(err) } fmt.Fprintf(os.Stderr, "prs returned: %d\n", len(prs)) fmt.Fprintf(os.Stderr, "minimum version: %s\n", stdinPayload.Version.Number) prs = filterPRs(prs, stdinPayload.Version.Number) prs = sortPRs(prs) table := tabwriter.NewWriter(os.Stderr, 0, 0, 1, ' ', tabwriter.TabIndent) header := []string{ "Number", "Url", "Title", "Creator", "Date Created", "Base Ref", "Head Ref", } if len(prs) > 0 { fmt.Fprintln(table, strings.Join(header, "\t")) } else { fmt.Fprintln(os.Stderr, "no prs detected beyond the last known version") } for ind, onePr := range prs { stdoutVersions = append(stdoutVersions, stdoutVersion{Ref: strconv.Itoa(int(onePr.Number))}) if ind == 0 { fmt.Printf("\n") } lineElems := []string{ fmt.Sprint(onePr.Number), onePr.URL, onePr.Title, extractUser(onePr), onePr.Created, onePr.Base.Ref, onePr.Head.Ref, } fmt.Fprintln(table, strings.Join(lineElems, "\t")) } err = table.Flush() if err != nil { util.HandleError(err) } stdoutData, err := json.MarshalIndent(stdoutVersions, "", " ") if err != nil { util.HandleError(err) } fmt.Fprintln(os.Stdout, string(stdoutData)) } func composeAllPrURL(sourceConfig util.SourceConfig) string { urlString := &url.URL{} if sourceConfig.Insecure { urlString.Scheme = "http" } else { urlString.Scheme = "https" } urlString.Host = strings.Join([]string{ sourceConfig.Hostname, sourceConfig.Port}, ":", ) urlPath := path.Join( "api", "v1", "repos", sourceConfig.Owner, sourceConfig.Repo, "pulls", ) urlString.Path = urlPath queryString := url.Values{} queryString.Set("state", "open") queryString.Set("sort", "oldest") urlString.RawQuery = queryString.Encode() return urlString.String() } func composeSinglePrURL(source util.STDINPayload) string { urlString := &url.URL{} if source.Source.Insecure { urlString.Scheme = "http" } else { urlString.Scheme = "https" } urlString.Host = strings.Join([]string{ source.Source.Hostname, source.Source.Port}, ":", ) urlPath := path.Join( "api", "v1", "repos", source.Source.Owner, source.Source.Repo, "pulls", source.Version.Number, ) urlString.Path = urlPath return urlString.String() } func extractUser(onePr pr) string { var user string if onePr.User.FullName != "" { user = onePr.User.FullName } else { user = onePr.User.Username } return user } func sortPRs(prs []pr) []pr { sort.SliceStable(prs, func(leftInd, rightInd int) bool { return prs[leftInd].Number < prs[rightInd].Number }) return prs } func filterPRs(prs []pr, minVersStr string) []pr { filteredPRs := []pr{} minVer, err := strconv.ParseInt(minVersStr, 10, 64) if err != nil { util.HandleError(err) } for _, onePR := range prs { if int64(onePR.Number) > minVer { filteredPRs = append(filteredPRs, onePR) } } return filteredPRs } // Get fetches the raw json of the PR object from the API and outputs it to a file func Get(stdinPayload util.STDINPayload, dest string) { var ( err error thisPR pr ) if stdinPayload.Source.SkipSSLVerification { http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} } client := &http.Client{} req, err := http.NewRequest("GET", composeSinglePrURL(stdinPayload), nil) if err != nil { util.HandleError(err) } if !stdinPayload.Source.Insecure && len(stdinPayload.Source.AccessToken) > 0 { req.Header.Add("Authorization", stdinPayload.Source.AccessToken) } response, err := client.Do(req) util.CheckResponse(response) data, _ := ioutil.ReadAll(response.Body) err = json.Unmarshal(data, &thisPR) if err != nil { util.HandleError(err) } metadataPayload := metadata{ Number: strconv.Itoa(int(thisPR.Number)), Title: thisPR.Title, Base: thisPR.Base.Ref, Head: thisPR.Head.Ref, CreatedAt: thisPR.Created, CreatedBy: extractUser(thisPR), } stdoutPayload := getStdout{ Version: stdoutVersion{ Ref: strconv.Itoa(int(thisPR.Number)), }, Metadata: metadataPayload, } stdoutData, err := json.MarshalIndent(stdoutPayload, "", " ") fmt.Fprintln(os.Stdout, string(stdoutData)) rawDestFile := path.Join( dest, "pr.json", ) metaDestFile := path.Join( dest, "metadata.json", ) err = ioutil.WriteFile(rawDestFile, data, 0644) if err != nil { util.HandleError(err) } fmt.Fprintf(os.Stderr, "raw data written to %s\n", rawDestFile) err = ioutil.WriteFile(metaDestFile, stdoutData, 0644) if err != nil { util.HandleError(err) } fmt.Fprintf(os.Stderr, "resource metadata written to %s\n", metaDestFile) }