Files
mostlymatter/vendor/github.com/mattermost/rsc/cmd/issue/issue.go
Christopher Speller 38ee83e45b Moving to glide
2016-05-12 23:56:07 -04:00

186 строки
3.8 KiB
Go

package main
import (
"encoding/xml"
"flag"
"fmt"
"html"
"log"
"net/http"
"net/url"
"os"
"sort"
"strconv"
"strings"
"time"
)
func usage() {
fmt.Fprintf(os.Stderr, `usage: issue [-p project] query
If query is a single number, prints the full history for the issue.
Otherwise, prints a table of matching results.
The special query 'go1' is shorthand for 'Priority-Go1'.
`)
os.Exit(2)
}
type Feed struct {
Entry Entries `xml:"entry"`
}
type Entry struct {
ID string `xml:"id"`
Title string `xml:"title"`
Published time.Time `xml:"published"`
Content string `xml:"content"`
Updates []Update `xml:"updates"`
Author struct {
Name string `xml:"name"`
} `xml:"author"`
Owner string `xml:"owner"`
Status string `xml:"status"`
Label []string `xml:"label"`
}
type Update struct {
Summary string `xml:"summary"`
Owner string `xml:"ownerUpdate"`
Label string `xml:"label"`
Status string `xml:"status"`
}
type Entries []Entry
func (e Entries) Len() int { return len(e) }
func (e Entries) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
func (e Entries) Less(i, j int) bool { return e[i].Title < e[j].Title }
var project = flag.String("p", "go", "code.google.com project identifier")
var v = flag.Bool("v", false, "verbose")
func main() {
flag.Usage = usage
flag.Parse()
if flag.NArg() != 1 {
usage()
}
full := false
q := flag.Arg(0)
n, _ := strconv.Atoi(q)
if n != 0 {
q = "id:" + q
full = true
}
if q == "go1" {
q = "label:Priority-Go1"
}
log.SetFlags(0)
query := url.Values{
"q": {q},
"max-results": {"400"},
}
if !full {
query["can"] = []string{"open"}
}
u := "https://code.google.com/feeds/issues/p/" + *project + "/issues/full?" + query.Encode()
if *v {
log.Print(u)
}
r, err := http.Get(u)
if err != nil {
log.Fatal(err)
}
var feed Feed
if err := xml.NewDecoder(r.Body).Decode(&feed); err != nil {
log.Fatal(err)
}
r.Body.Close()
sort.Sort(feed.Entry)
for _, e := range feed.Entry {
id := e.ID
if i := strings.Index(id, "id="); i >= 0 {
id = id[:i+len("id=")]
}
fmt.Printf("%s\t%s\n", id, e.Title)
if full {
fmt.Printf("Reported by %s (%s)\n", e.Author.Name, e.Published.Format("2006-01-02 15:04:05"))
if e.Owner != "" {
fmt.Printf("\tOwner: %s\n", e.Owner)
}
if e.Status != "" {
fmt.Printf("\tStatus: %s\n", e.Status)
}
for _, l := range e.Label {
fmt.Printf("\tLabel: %s\n", l)
}
if e.Content != "" {
fmt.Printf("\n\t%s\n", wrap(html.UnescapeString(e.Content), "\t"))
}
u := "https://code.google.com/feeds/issues/p/" + *project + "/issues/" + id + "/comments/full"
if *v {
log.Print(u)
}
r, err := http.Get(u)
if err != nil {
log.Fatal(err)
}
var feed Feed
if err := xml.NewDecoder(r.Body).Decode(&feed); err != nil {
log.Fatal(err)
}
r.Body.Close()
for _, e := range feed.Entry {
fmt.Printf("\n%s (%s)\n", e.Title, e.Published.Format("2006-01-02 15:04:05"))
for _, up := range e.Updates {
if up.Summary != "" {
fmt.Printf("\tSummary: %s\n", up.Summary)
}
if up.Owner != "" {
fmt.Printf("\tOwner: %s\n", up.Owner)
}
if up.Status != "" {
fmt.Printf("\tStatus: %s\n", up.Status)
}
if up.Label != "" {
fmt.Printf("\tLabel: %s\n", up.Label)
}
}
if e.Content != "" {
fmt.Printf("\n\t%s\n", wrap(html.UnescapeString(e.Content), "\t"))
}
}
}
}
}
func wrap(t string, prefix string) string {
out := ""
t = strings.Replace(t, "\r\n", "\n", -1)
lines := strings.Split(t, "\n")
for i, line := range lines {
if i > 0 {
out += "\n" + prefix
}
s := line
for len(s) > 70 {
i := strings.LastIndex(s[:70], " ")
if i < 0 {
i = 69
}
i++
out += s[:i] + "\n" + prefix
s = s[i:]
}
out += s
}
return out
}