arianagiroux 2 тижнів тому
батько
коміт
220e2907d0
5 змінених файлів з 160 додано та 4 видалено
  1. 3 2
      Readme.md
  2. 1 1
      cmd/issues.go
  3. 62 1
      io.go
  4. 92 0
      io_test.go
  5. 2 0
      tui.go

+ 3 - 2
Readme.md

@@ -14,12 +14,13 @@ go install cmd/issues.go
 
 ## TODO
 
-- `cmd/issues.go:// TODO implement create/edit/delete funcs`
+- `cmd/issues.go:// TODO implement edit/delete funcs`
 - `cmd/issues.go:// TODO implement attempt to auto load issues folder if no arg specified`
-- `io.go:func WriteIssue(issue Issue) (success bool, err error) { return false, nil } // TODO: implement`
 - `io.go:func DeleteIssue(issue Issue) (success bool, err error) { return false, nil } // TODO: implement`
 - `tui.go:// TODO enable collection recursing (i.e, embeded collections)`
 - `tui.go:// TODO enable scroll/viewport logic on issues!!!`
+- `tui.go:// TODO connect WriteIssue to createIssue widget`
+- `tui.go:	case IssueCollection: // TODO handle updates to IssueCollection widgets in its own update func`
 
 ## See also
 

+ 1 - 1
cmd/issues.go

@@ -1,4 +1,4 @@
-// TODO implement create/edit/delete funcs
+// TODO implement edit/delete funcs
 //
 // TODO implement attempt to auto load issues folder if no arg specified
 package main

+ 62 - 1
io.go

@@ -25,9 +25,12 @@
 package issues
 
 import (
+	"errors"
 	"os"
+	"path/filepath"
 )
 
+// converts file from []string to string, reports errors
 func readPath(path string) (output string, err error) {
 	content, err := os.ReadFile(path)
 
@@ -89,7 +92,65 @@ func IsIssueCollection(path string) bool {
 }
 
 // Writes a issue to disk
-func WriteIssue(issue Issue) (success bool, err error) { return false, nil } // TODO: implement
+func WriteIssue(issue Issue, ignoreExisting bool) (success bool, err error) {
+	if IsIssue(issue.Path) && !ignoreExisting {
+		return false, errors.New("path exists")
+	}
+
+	// make base directory (effectively, the title)
+	err = os.Mkdir(issue.Path, 0755)
+	if err != nil {
+		return false, err
+	}
+
+	// Write Fields
+	f := []Field{issue.Description, issue.Status}
+	for _, field := range f {
+		if len(field.Path) > 0 { // skip empty paths
+			path := filepath.Join(issue.Path, field.Path)
+			err = os.WriteFile(path, []byte(field.Data), 0755)
+			if err != nil {
+				return false, err // test by overwrite path
+			}
+		}
+	}
+
+	// Write Tags
+	if len(issue.Tags.Path) > 0 { // skip tags with no path init
+		err = os.Mkdir(filepath.Join(issue.Path, issue.Tags.Path), 0755)
+		if err != nil {
+			return false, err // test by overwrite path
+		}
+		for _, field := range issue.Tags.Fields {
+			if len(field.Path) > 0 { // skip empty paths
+				path := filepath.Join(issue.Path, issue.Tags.Path, field.Path)
+				err = os.WriteFile(path, []byte(field.Data), 0755)
+				if err != nil {
+					return false, err // test by overwrite path
+				}
+			}
+		}
+	}
+
+	// Write Blockedby
+	if len(issue.Tags.Path) > 0 { // skip blockedby with no path init
+		err = os.Mkdir(filepath.Join(issue.Path, issue.Blockedby.Path), 0755)
+		if err != nil {
+			return false, err // test by overwrite path
+		}
+		for _, field := range issue.Blockedby.Fields {
+			if len(field.Path) > 0 { // skip empty paths
+				path := filepath.Join(issue.Path, issue.Blockedby.Path, field.Path)
+				err = os.WriteFile(path, []byte(field.Data), 0755)
+				if err != nil {
+					return false, err // test by overwrite path
+				}
+			}
+		}
+	}
+
+	return true, nil
+}
 
 // Removes a issue from disk
 func DeleteIssue(issue Issue) (success bool, err error) { return false, nil } // TODO: implement

+ 92 - 0
io_test.go

@@ -1,6 +1,7 @@
 package issues
 
 import (
+	"os"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -51,3 +52,94 @@ func Test_IsIssueCollection_returns_false_on_error(t *testing.T) {
 	val := IsIssueCollection("willneverexist")
 	assert.False(t, val)
 }
+
+func Test_WriteIssue_fails_on_existing(t *testing.T) {
+	testIssue := Issue{
+		Title: "",
+		Path:  "tests/bugs/test-1",
+	}
+
+	_, err := WriteIssue(testIssue, false)
+	assert.Error(t, err)
+}
+
+func Test_WriteIssue_fails_on_bad_path(t *testing.T) {
+	testIssue := Issue{
+		Title: "",
+		Path:  "tests/cantexist/test",
+	}
+
+	_, err := WriteIssue(testIssue, true)
+	assert.Error(t, err)
+}
+
+func Test_WriteIssue_creates_base_path(t *testing.T) {
+	testIssue := Issue{Path: "tests/bugs/test-write1"}
+
+	// clean up path
+	err := os.RemoveAll(testIssue.Path)
+	assert.Nil(t, err)
+
+	// run test
+	result, err := WriteIssue(testIssue, false)
+	assert.Nil(t, err)
+	assert.True(t, result)
+
+	// clean up path
+	err = os.RemoveAll(testIssue.Path)
+	assert.Nil(t, err)
+}
+
+func Test_WriteIssue_creates_fields(t *testing.T) {
+	testIssue := Issue{
+		Path:        "tests/bugs/test-write2",
+		Status:      Field{Path: "/status", Data: "test"},
+		Description: Field{Path: "/description", Data: "test"},
+	}
+
+	// clean up path
+	err := os.RemoveAll(testIssue.Path)
+	assert.Nil(t, err)
+
+	// run test
+	result, err := WriteIssue(testIssue, false)
+	assert.Nil(t, err)
+	assert.True(t, result)
+
+	// clean up path
+	err = os.RemoveAll(testIssue.Path)
+	assert.Nil(t, err)
+}
+
+func Test_WriteIssue_creates_variadic_fields(t *testing.T) {
+	testIssue := Issue{
+		Path: "tests/bugs/test-write3",
+		Tags: VariadicField{
+			Path: "/tags",
+			Fields: []Field{
+				{Path: "test1"},
+				{Path: "test2"},
+			},
+		},
+		Blockedby: VariadicField{
+			Path: "/blockedby",
+			Fields: []Field{
+				{Path: "test1"},
+				{Path: "test2"},
+			},
+		},
+	}
+
+	// clean up path
+	err := os.RemoveAll(testIssue.Path)
+	assert.Nil(t, err)
+
+	// run test
+	result, err := WriteIssue(testIssue, false)
+	assert.Nil(t, err)
+	assert.True(t, result)
+
+	// clean up path
+	err = os.RemoveAll(testIssue.Path)
+	assert.Nil(t, err)
+}

+ 2 - 0
tui.go

@@ -3,6 +3,8 @@
 // TODO enable collection recursing (i.e, embeded collections)
 //
 // TODO enable scroll/viewport logic on issues!!!
+
+// TODO connect WriteIssue to createIssue widget
 //
 // While the package remains in v0.0.X releases, this TUI may be undocumented.
 package issues