Some betterment of things

This commit is contained in:
Olivier 2016-12-14 09:55:09 -05:00
parent a54632176b
commit c5811d75b7
No known key found for this signature in database
GPG key ID: 1A9FE7C1DFF65CB0
10 changed files with 115 additions and 50 deletions

View file

@ -28,7 +28,7 @@ var ErrCcmdJiraProjectRequired = errors.New("Jira project needs to be set")
func (ccmd *CreateCmd) Create() error { func (ccmd *CreateCmd) Create() error {
var b = bytes.NewBufferString(CREATE_TEMPLATE) var b = bytes.NewBufferString(CREATE_TEMPLATE)
var iss *jkl.Issue var iss *jkl.JiraIssue
var err error var err error
if ccmd.file != "" { if ccmd.file != "" {
iss, err = GetIssueFromFile(ccmd.file, b) iss, err = GetIssueFromFile(ccmd.file, b)

View file

@ -40,7 +40,7 @@ func copyInitial(dst io.WriteSeeker, initial io.Reader) {
dst.Seek(0, 0) dst.Seek(0, 0)
} }
func GetIssueFromTmpFile(initial io.Reader) (*jkl.Issue, error) { func GetIssueFromTmpFile(initial io.Reader) (*jkl.JiraIssue, error) {
f, err := ioutil.TempFile(os.TempDir(), "jkl") f, err := ioutil.TempFile(os.TempDir(), "jkl")
if err != nil { if err != nil {
return nil, err return nil, err
@ -87,7 +87,7 @@ func GetTextFromFile(file *os.File) (io.Reader, error) {
return file, err return file, err
} }
func GetIssueFromFile(filename string, initial io.Reader) (*jkl.Issue, error) { func GetIssueFromFile(filename string, initial io.Reader) (*jkl.JiraIssue, error) {
f, err := os.Open(filename) f, err := os.Open(filename)
if err != nil { if err != nil {
return nil, err return nil, err
@ -104,8 +104,8 @@ func GetIssueFromFile(filename string, initial io.Reader) (*jkl.Issue, error) {
var spacex = regexp.MustCompile(`\s`) var spacex = regexp.MustCompile(`\s`)
func IssueFromFile(f io.Reader) *jkl.Issue { func IssueFromFile(f io.Reader) *jkl.JiraIssue {
iss := &jkl.Issue{Fields: &jkl.Fields{}} iss := &jkl.JiraIssue{Fields: &jkl.Fields{}}
riss := reflect.ValueOf(iss).Elem() riss := reflect.ValueOf(iss).Elem()
fieldsField := riss.FieldByName("Fields").Elem() fieldsField := riss.FieldByName("Fields").Elem()
currentField := reflect.Value{} currentField := reflect.Value{}
@ -143,6 +143,6 @@ func IssueFromFile(f io.Reader) *jkl.Issue {
return iss return iss
} }
func IssueFromList(list []string) *jkl.Issue { func IssueFromList(list []string) *jkl.JiraIssue {
return IssueFromFile(bytes.NewBufferString(strings.Join(list, "\n"))) return IssueFromFile(bytes.NewBufferString(strings.Join(list, "\n")))
} }

View file

@ -5,14 +5,11 @@ import (
"fmt" "fmt"
"log" "log"
"os" "otremblay.com/jkl"
"github.com/joho/godotenv"
"strings"
) )
func main() { func main() {
findRCFile() jkl.FindRCFile()
flag.Parse() flag.Parse()
if len(flag.Args()) == 0 { if len(flag.Args()) == 0 {
fmt.Print(usage) fmt.Print(usage)
@ -23,22 +20,6 @@ func main() {
} }
} }
func findRCFile() {
dir, err := os.Getwd()
if err != nil {
log.Fatalln(err)
}
path := strings.Split(dir, "/")
for i := len(path) - 1; i > 0; i-- {
err := godotenv.Load(strings.Join(path[0:i], "/") + "/.jklrc")
if err == nil {
return
}
}
log.Fatalln("No .jklrc found")
}
func runcmd(args []string) error { func runcmd(args []string) error {
switch args[0] { switch args[0] {
case "list": case "list":

5
cmd/jkl/jkl_test.go Normal file
View file

@ -0,0 +1,5 @@
package main

View file

@ -8,14 +8,16 @@ import (
"text/template" "text/template"
"fmt" "fmt"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
"otremblay.com/jkl" "otremblay.com/jkl"
) )
type listissue jkl.Issue type listissue jkl.JiraIssue
func (l *listissue) URL() string { func (l *listissue) URL() string {
i := jkl.Issue(*l) i := jkl.JiraIssue(*l)
return (&i).URL() return (&i).URL()
} }
func (l *listissue) Color() string { func (l *listissue) Color() string {

View file

@ -32,7 +32,7 @@ func (f *jklfile) String() string {
func (f *jklfile) Write(data []byte, off int64) (uint32, fuse.Status) { func (f *jklfile) Write(data []byte, off int64) (uint32, fuse.Status) {
n, err := f.File.WriteAt(data, off) n, err := f.File.WriteAt(data, off)
if err != nil { if err != nil {
return fuse.EACCES return uint32(0),fuse.EACCES
} }
return uint32(n), fuse.OK return uint32(n), fuse.OK
} }

View file

@ -16,7 +16,7 @@ import (
type jklfs struct { type jklfs struct {
pathfs.FileSystem pathfs.FileSystem
issuePerDirs map[string]*jkl.Issue issuePerDirs map[string]*jkl.JiraIssue
} }
func (j *jklfs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) { func (j *jklfs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
@ -90,7 +90,7 @@ func main() {
if len(flag.Args()) < 1 { if len(flag.Args()) < 1 {
log.Fatal("Usage:\n jklfs MOUNTPOINT") log.Fatal("Usage:\n jklfs MOUNTPOINT")
} }
nfs := pathfs.NewPathNodeFs(&jklfs{pathfs.NewDefaultFileSystem(), map[string]*jkl.Issue{}}, nil) nfs := pathfs.NewPathNodeFs(&jklfs{pathfs.NewDefaultFileSystem(), map[string]*jkl.JiraIssue{}}, nil)
server, _, err := nodefs.MountRoot(flag.Arg(0), nfs.Root(), nil) server, _, err := nodefs.MountRoot(flag.Arg(0), nfs.Root(), nil)
if err != nil { if err != nil {
log.Fatalf("Mount fail: %v\n", err) log.Fatalf("Mount fail: %v\n", err)

View file

@ -4,19 +4,30 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"log" "log"
"os"
"text/template" "text/template"
"os"
) )
type Search struct { type Search struct {
Issues []*Issue `json:"issues"` Issues []*JiraIssue `json:"issues"`
} }
type IssueType struct { type IssueType struct {
Name string `json:"name"` Name string `json:"name"`
Fields map[string]FieldSpec
} }
type FieldSpec struct {
Name string
Required bool
Schema struct {
Type string
}
}
type Project struct { type Project struct {
Key string `json:"key,omitempty"` Key string `json:"key,omitempty"`
IssueTypes []IssueType
} }
type Author struct { type Author struct {
@ -25,6 +36,7 @@ type Author struct {
} }
type Comment struct { type Comment struct {
Id string
Author *Author Author *Author
Body string Body string
} }
@ -49,7 +61,7 @@ type Fields struct {
Summary string `json:"summary,omitempty"` Summary string `json:"summary,omitempty"`
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
Comment *CommentColl `json:"comment,omitempty"` Comment *CommentColl `json:"comment,omitempty"`
Parent *Issue `json:",omitempty"` Parent *JiraIssue `json:",omitempty"`
Status *Status `json:",omitempty"` Status *Status `json:",omitempty"`
TimeTracking *TimeTracking `json:"timetracking,omitempty"` TimeTracking *TimeTracking `json:"timetracking,omitempty"`
} }
@ -72,16 +84,16 @@ func PrettySeconds(seconds int) string {
return fmt.Sprintf("%dd %2dh %2dm %2ds", days, hours, minutes, seconds) return fmt.Sprintf("%dd %2dh %2dm %2ds", days, hours, minutes, seconds)
} }
type Issue struct { type JiraIssue struct {
Key string `json:"key,omitempty"` Key string `json:"key,omitempty"`
Fields *Fields `json:"fields"` Fields *Fields `json:"fields"`
} }
func (i *Issue) URL() string { func (i *JiraIssue) URL() string {
return os.Getenv("JIRA_ROOT") + "browse/"+ i.Key return os.Getenv("JIRA_ROOT") + "browse/" + i.Key
} }
func (i *Issue) String() string { func (i *JiraIssue) String() string {
var b = bytes.NewBuffer(nil) var b = bytes.NewBuffer(nil)
err := issueTmpl.Execute(b, i) err := issueTmpl.Execute(b, i)
if err != nil { if err != nil {
@ -91,7 +103,7 @@ func (i *Issue) String() string {
return b.String() return b.String()
} }
var commentTemplate = `{{if .Fields.Comment }}{{range .Fields.Comment.Comments}}{{.Author.DisplayName}}: var commentTemplate = `{{if .Fields.Comment }}{{$k := .Key}}{{range .Fields.Comment.Comments}}{{.Author.DisplayName}} ({{$k}}#{{.Id}}):
----------------- -----------------
{{.Body}} {{.Body}}
----------------- -----------------

36
jkl.go
View file

@ -6,11 +6,15 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"net/url" "net/url"
"os" "os"
"strings"
"github.com/joho/godotenv"
) )
var defaultIssue = &Issue{} var defaultIssue = &JiraIssue{}
func bootHttpClient() { func bootHttpClient() {
if httpClient == nil { if httpClient == nil {
@ -18,7 +22,7 @@ func bootHttpClient() {
} }
} }
func Create(issue *Issue) error { func Create(issue *JiraIssue) error {
bootHttpClient() bootHttpClient()
payload, err := formatPayload(issue) payload, err := formatPayload(issue)
if err != nil { if err != nil {
@ -36,7 +40,7 @@ func Create(issue *Issue) error {
return nil return nil
} }
func Edit(issue *Issue) error { func Edit(issue *JiraIssue) error {
bootHttpClient() bootHttpClient()
payload, err := formatPayload(issue) payload, err := formatPayload(issue)
if err != nil { if err != nil {
@ -53,7 +57,7 @@ func Edit(issue *Issue) error {
return nil return nil
} }
func List(jql string) ([]*Issue, error) { func List(jql string) ([]*JiraIssue, error) {
bootHttpClient() bootHttpClient()
path := "api/2/search?fields=*all&maxResults=1000" path := "api/2/search?fields=*all&maxResults=1000"
if jql != "" { if jql != "" {
@ -75,7 +79,7 @@ func List(jql string) ([]*Issue, error) {
return issues.Issues, nil return issues.Issues, nil
} }
func GetIssue(taskKey string) (*Issue, error) { func GetIssue(taskKey string) (*JiraIssue, error) {
bootHttpClient() bootHttpClient()
path := "api/2/issue/" + taskKey path := "api/2/issue/" + taskKey
resp, err := httpClient.Get(path) resp, err := httpClient.Get(path)
@ -84,7 +88,7 @@ func GetIssue(taskKey string) (*Issue, error) {
return nil, err return nil, err
} }
dec := json.NewDecoder(resp.Body) dec := json.NewDecoder(resp.Body)
var issue = &Issue{} var issue = &JiraIssue{}
err = dec.Decode(issue) err = dec.Decode(issue)
if err != nil { if err != nil {
b, _ := ioutil.ReadAll(resp.Body) b, _ := ioutil.ReadAll(resp.Body)
@ -111,7 +115,7 @@ func AddComment(taskKey string, comment string) error {
return nil return nil
} }
func formatPayload(issue *Issue) (io.Reader, error) { func formatPayload(issue *JiraIssue) (io.Reader, error) {
if issue.Fields != nil && if issue.Fields != nil &&
issue.Fields.Project != nil && issue.Fields.Project != nil &&
issue.Fields.Project.Key == "" { issue.Fields.Project.Key == "" {
@ -128,3 +132,21 @@ func formatPayload(issue *Issue) (io.Reader, error) {
} }
return payload, nil return payload, nil
} }
func FindRCFile() string {
dir, err := os.Getwd()
if err != nil {
log.Fatalln(err)
}
path := strings.Split(dir, "/")
for i := len(path); i > 0; i-- {
dotenvpath := strings.Join(path[0:i], "/") + "/.jklrc"
err := godotenv.Load(dotenvpath)
if err == nil {
return dotenvpath
}
}
log.Fatalln("No .jklrc found")
return ""
}

43
jkl_test.go Normal file
View file

@ -0,0 +1,43 @@
package jkl
import (
"encoding/json"
"fmt"
"os"
"testing"
"text/template"
)
func TestUnmarshalProjects(t *testing.T) {
f, err := os.Open("projects.json")
if err != nil {
t.Error(err)
}
dec := json.NewDecoder(f)
x := struct{ Projects []Project }{}
err = dec.Decode(&x)
if err != nil {
t.Error(err)
}
for _, p := range x.Projects {
for _, it := range p.IssueTypes {
for sn, f := range it.Fields {
fmt.Println(it.Name, sn, f.Name, f.Required, f.Schema.Type)
}
}
}
}
type TestType struct {
Field string
}
func (t *TestType) String() string {
return t.Field
}
func TestStringerInTemplate(t *testing.T) {
x := template.Must(template.New("stuff").Parse("{{.}}"))
x.Execute(os.Stdout, &TestType{"This works"})
}