Lots of small stuff
This commit is contained in:
commit
b5c1189de8
14 changed files with 911 additions and 0 deletions
52
cmd/jkl/comment.go
Normal file
52
cmd/jkl/comment.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"io"
|
||||
|
||||
"otremblay.com/jkl"
|
||||
)
|
||||
|
||||
type CommentCmd struct {
|
||||
args []string
|
||||
file string
|
||||
issueKey string
|
||||
}
|
||||
|
||||
func NewCommentCmd(args []string) (*CommentCmd, error) {
|
||||
ccmd := &CommentCmd{}
|
||||
f := flag.NewFlagSet("comments", flag.ExitOnError)
|
||||
f.StringVar(&ccmd.file, "f", "", "File to get issue comment from")
|
||||
f.Parse(args)
|
||||
if len(f.Args()) < 1 {
|
||||
return nil, ErrNotEnoughArgs
|
||||
}
|
||||
ccmd.issueKey = f.Arg(0)
|
||||
return ccmd, nil
|
||||
}
|
||||
|
||||
var ErrNotEnoughArgs = errors.New("Not enough arguments")
|
||||
|
||||
func (ccmd *CommentCmd) Comment() error {
|
||||
var b = bytes.NewBufferString("")
|
||||
var comment io.Reader
|
||||
var err error
|
||||
if ccmd.file != "" {
|
||||
comment, err = GetTextFromSpecifiedFile(ccmd.file, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
comment, err = GetTextFromTmpFile(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
io.Copy(b, comment)
|
||||
|
||||
return jkl.AddComment(ccmd.issueKey, b.String())
|
||||
}
|
||||
54
cmd/jkl/create.go
Normal file
54
cmd/jkl/create.go
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
"otremblay.com/jkl"
|
||||
)
|
||||
|
||||
type CreateCmd struct {
|
||||
args []string
|
||||
project string
|
||||
file string
|
||||
}
|
||||
|
||||
func NewCreateCmd(args []string) (*CreateCmd, error) {
|
||||
ccmd := &CreateCmd{project: os.Getenv("JIRA_PROJECT")}
|
||||
f := flag.NewFlagSet("x", flag.ExitOnError)
|
||||
f.StringVar(&ccmd.project, "p", "", "Jira project key")
|
||||
f.StringVar(&ccmd.file, "f", "", "File to get issue description from")
|
||||
f.Parse(args)
|
||||
return ccmd, nil
|
||||
}
|
||||
|
||||
var ErrCcmdJiraProjectRequired = errors.New("Jira project needs to be set")
|
||||
|
||||
func (ccmd *CreateCmd) Create() error {
|
||||
var b = bytes.NewBufferString(CREATE_TEMPLATE)
|
||||
var iss *jkl.Issue
|
||||
var err error
|
||||
if ccmd.file != "" {
|
||||
iss, err = GetIssueFromFile(ccmd.file, b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
iss, err = GetIssueFromTmpFile(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
if iss.Fields != nil &&
|
||||
(iss.Fields.Project == nil || iss.Fields.Project.Key == "") {
|
||||
iss.Fields.Project = &jkl.Project{Key: ccmd.project}
|
||||
}
|
||||
return jkl.Create(iss)
|
||||
}
|
||||
|
||||
const CREATE_TEMPLATE = `Issue Type:
|
||||
Summary:
|
||||
Description:`
|
||||
59
cmd/jkl/edit.go
Normal file
59
cmd/jkl/edit.go
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
"text/template"
|
||||
|
||||
"otremblay.com/jkl"
|
||||
)
|
||||
|
||||
type EditCmd struct {
|
||||
args []string
|
||||
project string
|
||||
file string
|
||||
}
|
||||
|
||||
func NewEditCmd(args []string) (*CreateCmd, error) {
|
||||
ccmd := &CreateCmd{project: os.Getenv("JIRA_PROJECT")}
|
||||
f := flag.NewFlagSet("x", flag.ExitOnError)
|
||||
f.StringVar(&ccmd.project, "p", "", "Jira project key")
|
||||
f.StringVar(&ccmd.file, "f", "filename", "File to get issue description from")
|
||||
f.Parse(args)
|
||||
return ccmd, nil
|
||||
}
|
||||
|
||||
func (ecmd *EditCmd) Edit(taskKey string) error {
|
||||
b := bytes.NewBuffer(nil)
|
||||
iss, err := jkl.GetIssue(taskKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = editTmpl.Execute(b, iss)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ecmd.file != "" {
|
||||
iss, err = GetIssueFromFile(ecmd.file, b)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
iss, err = GetIssueFromTmpFile(b)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
iss.Key = taskKey
|
||||
return jkl.Edit(iss)
|
||||
}
|
||||
|
||||
const EDIT_TEMPLATE = `Summary: {{.Fields.Summary}}
|
||||
Description: {{.Fields.Description}}`
|
||||
|
||||
var editTmpl = template.Must(template.New("editTmpl").Parse(EDIT_TEMPLATE))
|
||||
148
cmd/jkl/editor.go
Normal file
148
cmd/jkl/editor.go
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"reflect"
|
||||
|
||||
"bufio"
|
||||
|
||||
"otremblay.com/jkl"
|
||||
)
|
||||
|
||||
// def get_editor do
|
||||
// [System.get_env("EDITOR"), "nano", "vim", "vi"]
|
||||
// |> Enum.find(nil, fn (ed) -> System.find_executable(ed) != nil end)
|
||||
// end
|
||||
var editors = []string{os.Getenv("EDITOR"), "nano", "vim", "vi"}
|
||||
|
||||
// GetEditor returns the path to an editor, taking $EDITOR in account
|
||||
func GetEditor() string {
|
||||
for _, ed := range editors {
|
||||
if p, err := exec.LookPath(ed); err == nil {
|
||||
return p
|
||||
}
|
||||
}
|
||||
log.Fatal("No editor available; use flags.")
|
||||
return ""
|
||||
}
|
||||
|
||||
func copyInitial(dst io.WriteSeeker, initial io.Reader) {
|
||||
io.Copy(dst, initial)
|
||||
dst.Seek(0, 0)
|
||||
}
|
||||
|
||||
func GetIssueFromTmpFile(initial io.Reader) (*jkl.Issue, error) {
|
||||
f, err := ioutil.TempFile(os.TempDir(), "jkl")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copyInitial(f, initial)
|
||||
f2, err := GetTextFromFile(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return IssueFromFile(f2), nil
|
||||
}
|
||||
|
||||
func GetTextFromTmpFile(initial io.Reader) (io.Reader, error) {
|
||||
f, err := ioutil.TempFile(os.TempDir(), "jkl")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copyInitial(f, initial)
|
||||
return GetTextFromFile(f)
|
||||
}
|
||||
|
||||
func GetTextFromSpecifiedFile(filename string, initial io.Reader) (io.Reader, error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fi, err := f.Stat(); err == nil && fi.Size() == 0 {
|
||||
copyInitial(f, initial)
|
||||
}
|
||||
return GetTextFromFile(f)
|
||||
}
|
||||
|
||||
func GetTextFromFile(file *os.File) (io.Reader, error) {
|
||||
cmd := exec.Command(GetEditor(), file.Name())
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
_, err = file.Seek(0, 0)
|
||||
return file, err
|
||||
}
|
||||
|
||||
func GetIssueFromFile(filename string, initial io.Reader) (*jkl.Issue, error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if fi, err := f.Stat(); err == nil && fi.Size() == 0 {
|
||||
copyInitial(f, initial)
|
||||
}
|
||||
f2, err := GetTextFromFile(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return IssueFromFile(f2), nil
|
||||
}
|
||||
|
||||
var spacex = regexp.MustCompile(`\s`)
|
||||
|
||||
func IssueFromFile(f io.Reader) *jkl.Issue {
|
||||
iss := &jkl.Issue{Fields: &jkl.Fields{}}
|
||||
riss := reflect.ValueOf(iss).Elem()
|
||||
fieldsField := riss.FieldByName("Fields").Elem()
|
||||
currentField := reflect.Value{}
|
||||
brd := bufio.NewReader(f)
|
||||
for {
|
||||
b, _, err := brd.ReadLine()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
parts := strings.Split(string(b), ":")
|
||||
potentialField := spacex.ReplaceAllString(parts[0], "")
|
||||
|
||||
if newfield := fieldsField.FieldByName(potentialField); newfield.IsValid() {
|
||||
parts = parts[1:len(parts)]
|
||||
if potentialField == "IssueType" {
|
||||
iss.Fields.IssueType = &jkl.IssueType{}
|
||||
currentField = reflect.Value{}
|
||||
f2 := newfield.Elem()
|
||||
f3 := f2.FieldByName("Name")
|
||||
f3.SetString(strings.TrimSpace(strings.Join(parts, ":")))
|
||||
} else if potentialField == "Project" {
|
||||
iss.Fields.Project = &jkl.Project{}
|
||||
currentField = reflect.Value{}
|
||||
f2 := newfield.Elem()
|
||||
f3 := f2.FieldByName("Key")
|
||||
f3.SetString(strings.TrimSpace(strings.Join(parts, ":")))
|
||||
} else {
|
||||
currentField = newfield
|
||||
}
|
||||
}
|
||||
if currentField.IsValid() {
|
||||
currentField.SetString(strings.TrimSpace(currentField.String() + "\n" + strings.Join(parts, ":")))
|
||||
}
|
||||
}
|
||||
return iss
|
||||
}
|
||||
|
||||
func IssueFromList(list []string) *jkl.Issue {
|
||||
return IssueFromFile(bytes.NewBufferString(strings.Join(list, "\n")))
|
||||
}
|
||||
36
cmd/jkl/editor_test.go
Normal file
36
cmd/jkl/editor_test.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIssueFromList(t *testing.T) {
|
||||
iss := IssueFromList(strings.Split(`Description: Cowboys
|
||||
from
|
||||
hell
|
||||
Issue Type: Sometype
|
||||
this is ignored
|
||||
Summary: Dookienator
|
||||
also ignored`, "\n"))
|
||||
AssertEqual(t, `Cowboys
|
||||
from
|
||||
hell`, iss.Fields.Description)
|
||||
AssertEqual(t, "Sometype", iss.Fields.IssueType.Name)
|
||||
}
|
||||
|
||||
func TestSpacex(t *testing.T) {
|
||||
AssertEqual(t, "Something", spacex.ReplaceAllString("Some thing", ""))
|
||||
}
|
||||
|
||||
func AssertEqual(t *testing.T, expected interface{}, actual interface{}) {
|
||||
if expected != actual {
|
||||
t.Errorf(`Assertation failed!
|
||||
Asserted: %v
|
||||
Actual: %v`, expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func Assert(t *testing.T, fn func() bool) {
|
||||
|
||||
}
|
||||
63
cmd/jkl/jkl.go
Normal file
63
cmd/jkl/jkl.go
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"os"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := godotenv.Load(".jklrc", fmt.Sprintf("%s/.jklrc", os.Getenv("HOME")))
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
flag.Parse()
|
||||
if len(flag.Args()) == 0 {
|
||||
fmt.Print(usage)
|
||||
return
|
||||
}
|
||||
if err := runcmd(flag.Args()); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func runcmd(args []string) error {
|
||||
switch args[0] {
|
||||
case "list":
|
||||
return List(flag.Args()[1:])
|
||||
case "create":
|
||||
ccmd, err := NewCreateCmd(flag.Args()[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ccmd.Create()
|
||||
case "task":
|
||||
tcmd := &TaskCmd{}
|
||||
return tcmd.Handle(flag.Args()[1:])
|
||||
case "edit":
|
||||
ecmd := &EditCmd{}
|
||||
return ecmd.Edit(flag.Arg(1))
|
||||
case "comment":
|
||||
ccmd, err := NewCommentCmd(flag.Args()[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ccmd.Comment()
|
||||
}
|
||||
fmt.Println(usage)
|
||||
return nil
|
||||
}
|
||||
|
||||
const usage = `Usage:
|
||||
jkl [options] <command> [args]
|
||||
|
||||
Available commands:
|
||||
|
||||
list
|
||||
create
|
||||
edit
|
||||
`
|
||||
30
cmd/jkl/list.go
Normal file
30
cmd/jkl/list.go
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"text/template"
|
||||
|
||||
"otremblay.com/jkl"
|
||||
)
|
||||
|
||||
var listTemplateStr string
|
||||
var listTemplate *template.Template
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&listTemplateStr, "listTemplate", "{{.Key}}\t({{.Fields.IssueType.Name}}{{if .Fields.Parent}} of {{.Fields.Parent.Key}}{{end}})\t{{.Fields.Summary}}\n", "Go template used in list command")
|
||||
listTemplate = template.Must(template.New("listTemplate").Parse(listTemplateStr))
|
||||
}
|
||||
|
||||
func List(args []string) error {
|
||||
if issues, err := jkl.List(strings.Join(args, " ")); err != nil {
|
||||
return err
|
||||
} else {
|
||||
for _, issue := range issues {
|
||||
listTemplate.Execute(os.Stdout, issue)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
28
cmd/jkl/task.go
Normal file
28
cmd/jkl/task.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"otremblay.com/jkl"
|
||||
)
|
||||
|
||||
type TaskCmd struct{}
|
||||
|
||||
func (t *TaskCmd) Handle(args []string) error {
|
||||
if len(args) == 1 {
|
||||
return t.Get(args[0])
|
||||
}
|
||||
return ErrTaskSubCommandNotFound
|
||||
}
|
||||
|
||||
var ErrTaskSubCommandNotFound = errors.New("Subcommand not found.")
|
||||
|
||||
func (t *TaskCmd) Get(taskKey string) error {
|
||||
issue, err := jkl.GetIssue(taskKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(issue)
|
||||
return nil
|
||||
}
|
||||
78
cmd/jklfs/jklfile.go
Normal file
78
cmd/jklfs/jklfile.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
import "github.com/hanwen/go-fuse/fuse"
|
||||
import "github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
import "io/ioutil"
|
||||
|
||||
func NewJklfsFile() (nodefs.File, error) {
|
||||
f, err := ioutil.TempFile("", "jklfile")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &jklfile{f}, nil
|
||||
}
|
||||
|
||||
type jklfile struct {
|
||||
*os.File
|
||||
}
|
||||
|
||||
func (f *jklfile) InnerFile() nodefs.File {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *jklfile) String() string {
|
||||
return fmt.Sprintf("jklfile(%s)", f.Name())
|
||||
}
|
||||
|
||||
func (f *jklfile) Write(data []byte, off int64) (uint32, fuse.Status) {
|
||||
n, err := f.File.WriteAt(data, off)
|
||||
if err != nil {
|
||||
return fuse.EACCES
|
||||
}
|
||||
return uint32(n), fuse.OK
|
||||
}
|
||||
|
||||
func (f *jklfile) Fsync(flag int) (code fuse.Status) {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (f *jklfile) Truncate(size uint64) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (f *jklfile) Chmod(mode uint32) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (f *jklfile) Chown(uid uint32, gid uint32) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (f *jklfile) Allocate(off uint64, sz uint64, mode uint32) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
|
||||
func (f *jklfile) Flush() fuse.Status {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (f *jklfile) GetAttr(out *fuse.Attr) fuse.Status {
|
||||
return fuse.OK
|
||||
}
|
||||
|
||||
func (f *jklfile) Read(dest []byte, off int64) (fuse.ReadResult, fuse.Status) {
|
||||
return nil, fuse.OK
|
||||
}
|
||||
func (f *jklfile) Release() {
|
||||
|
||||
}
|
||||
func (f *jklfile) SetInode(i *nodefs.Inode) {}
|
||||
|
||||
func (f *jklfile) Utimens(atime *time.Time, mtime *time.Time) fuse.Status {
|
||||
return fuse.EPERM
|
||||
}
|
||||
BIN
cmd/jklfs/jklfs
Executable file
BIN
cmd/jklfs/jklfs
Executable file
Binary file not shown.
99
cmd/jklfs/jklfs.go
Normal file
99
cmd/jklfs/jklfs.go
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"otremblay.com/jkl"
|
||||
|
||||
"github.com/hanwen/go-fuse/fuse"
|
||||
"github.com/hanwen/go-fuse/fuse/nodefs"
|
||||
"github.com/hanwen/go-fuse/fuse/pathfs"
|
||||
)
|
||||
|
||||
type jklfs struct {
|
||||
pathfs.FileSystem
|
||||
issuePerDirs map[string]*jkl.Issue
|
||||
}
|
||||
|
||||
func (j *jklfs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
|
||||
switch name {
|
||||
case "current_sprint":
|
||||
return &fuse.Attr{
|
||||
Mode: fuse.S_IFDIR | 0755,
|
||||
}, fuse.OK
|
||||
case "":
|
||||
return &fuse.Attr{
|
||||
Mode: fuse.S_IFDIR | 0755,
|
||||
}, fuse.OK
|
||||
}
|
||||
if _, ok := j.issuePerDirs[name]; ok {
|
||||
return &fuse.Attr{
|
||||
Mode: fuse.S_IFDIR | 0755,
|
||||
}, fuse.OK
|
||||
}
|
||||
pathPieces := strings.Split(name, "/")
|
||||
path := strings.Join(pathPieces[0:2], "/")
|
||||
if i, ok := j.issuePerDirs[path]; ok {
|
||||
if path+"/description" == name {
|
||||
return &fuse.Attr{
|
||||
Mode: fuse.S_IFREG | 0644, Size: uint64(len(i.Fields.Description)),
|
||||
}, fuse.OK
|
||||
}
|
||||
}
|
||||
return nil, fuse.ENOENT
|
||||
}
|
||||
|
||||
func (j *jklfs) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntry, code fuse.Status) {
|
||||
if name == "" {
|
||||
c = []fuse.DirEntry{{Name: "current_sprint", Mode: fuse.S_IFDIR}}
|
||||
return c, fuse.OK
|
||||
}
|
||||
if name == "current_sprint" {
|
||||
issues, err := jkl.List("sprint in openSprints() and project = 'DO'")
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
return nil, fuse.ENOENT
|
||||
}
|
||||
c = make([]fuse.DirEntry, len(issues))
|
||||
for i, issue := range issues {
|
||||
c[i] = fuse.DirEntry{Name: issue.Key, Mode: fuse.S_IFDIR}
|
||||
j.issuePerDirs["current_sprint/"+issue.Key] = issue
|
||||
}
|
||||
return c, fuse.OK
|
||||
}
|
||||
|
||||
if _, ok := j.issuePerDirs[name]; ok {
|
||||
c = []fuse.DirEntry{fuse.DirEntry{Name: "description", Mode: fuse.S_IFREG}}
|
||||
return c, fuse.OK
|
||||
}
|
||||
|
||||
return nil, fuse.ENOENT
|
||||
}
|
||||
|
||||
func (j *jklfs) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
|
||||
pathPieces := strings.Split(name, "/")
|
||||
path := strings.Join(pathPieces[0:2], "/")
|
||||
if i, ok := j.issuePerDirs[path]; ok {
|
||||
if path+"/description" == name {
|
||||
return nodefs.NewDataFile([]byte(i.Fields.Description)), fuse.OK
|
||||
}
|
||||
}
|
||||
return nil, fuse.ENOENT
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if len(flag.Args()) < 1 {
|
||||
log.Fatal("Usage:\n jklfs MOUNTPOINT")
|
||||
}
|
||||
nfs := pathfs.NewPathNodeFs(&jklfs{pathfs.NewDefaultFileSystem(), map[string]*jkl.Issue{}}, nil)
|
||||
server, _, err := nodefs.MountRoot(flag.Arg(0), nfs.Root(), nil)
|
||||
if err != nil {
|
||||
log.Fatalf("Mount fail: %v\n", err)
|
||||
}
|
||||
server.Serve()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue