mirror of
https://github.com/dnote/dnote
synced 2026-03-14 22:45:50 +01:00
Improve output and edit command (#52)
* Refine output * Show note content while editing * v0.2.0-alpha.2
This commit is contained in:
parent
db1d668006
commit
d31b22aed0
16 changed files with 260 additions and 85 deletions
2
Gopkg.lock
generated
2
Gopkg.lock
generated
|
|
@ -52,6 +52,6 @@
|
|||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "dc231aa7e3a8f7286e2b20dac68d566c430b0c7a3a0de97c3a3534280a6f85b4"
|
||||
inputs-digest = "a6df84725e42f485baf9261b9d48ad577c4687d5d7f5b90353d1e40606f40e26"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package add
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
@ -69,7 +69,7 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
return errors.Wrap(err, "Failed to write note")
|
||||
}
|
||||
|
||||
fmt.Printf("[+] Added to %s\n", bookName)
|
||||
log.Infof("added to %s\n", bookName)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
@ -37,13 +38,12 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
|
||||
for _, book := range books {
|
||||
if book == currentBook {
|
||||
fmt.Printf("* %v\n", book)
|
||||
fmt.Printf(" %s\033[%dm%s\033[0m\n", "* ", log.ColorBlue, book)
|
||||
} else {
|
||||
fmt.Printf(" %v\n", book)
|
||||
fmt.Printf(" %s%s\n", " ", book)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,28 @@
|
|||
package edit
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/dnote-io/cli/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var newContent string
|
||||
|
||||
var example = `
|
||||
* Edit the note by index in the current book
|
||||
dnote edit 3 "new content"
|
||||
dnote edit 3
|
||||
|
||||
* Edit the note by index in a certain book
|
||||
dnote edit JS 3 "new content"`
|
||||
dnote edit js 3
|
||||
|
||||
* Skip the prompt by providing new content directly
|
||||
dntoe eidt js 3 -c "new content"`
|
||||
|
||||
func NewCmd(ctx infra.DnoteCtx) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
|
|
@ -28,11 +34,14 @@ func NewCmd(ctx infra.DnoteCtx) *cobra.Command {
|
|||
RunE: newRun(ctx),
|
||||
}
|
||||
|
||||
f := cmd.Flags()
|
||||
f.StringVarP(&newContent, "content", "c", "", "The new content for the note")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func preRun(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 2 {
|
||||
if len(args) < 1 {
|
||||
return errors.New("Missing argument")
|
||||
}
|
||||
|
||||
|
|
@ -47,54 +56,63 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
}
|
||||
|
||||
var targetBookName string
|
||||
var index int
|
||||
var content string
|
||||
var targetIdx int
|
||||
|
||||
if len(args) == 2 {
|
||||
if len(args) == 1 {
|
||||
targetBookName, err = core.GetCurrentBook(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
index, err = strconv.Atoi(args[0])
|
||||
targetIdx, err = strconv.Atoi(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content = args[1]
|
||||
} else if len(args) == 3 {
|
||||
} else if len(args) == 2 {
|
||||
targetBookName = args[0]
|
||||
index, err = strconv.Atoi(args[1])
|
||||
targetIdx, err = strconv.Atoi(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
content = args[2]
|
||||
}
|
||||
|
||||
targetBook, exists := dnote[targetBookName]
|
||||
if !exists {
|
||||
return errors.Errorf("Book with the name '%s' does not exist", targetBookName)
|
||||
return errors.Errorf("Book %s does not exist", targetBookName)
|
||||
}
|
||||
if targetIdx > len(targetBook.Notes)-1 {
|
||||
return errors.Errorf("Book %s does not have note with index %d", targetBookName, targetIdx)
|
||||
}
|
||||
targetNote := targetBook.Notes[targetIdx]
|
||||
|
||||
if newContent == "" {
|
||||
log.Printf("content: %s\n", targetNote.Content)
|
||||
log.Printf("new content: ")
|
||||
|
||||
newContent, err = utils.GetInput()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to get new content")
|
||||
}
|
||||
}
|
||||
|
||||
ts := time.Now().Unix()
|
||||
|
||||
for i, note := range dnote[targetBookName].Notes {
|
||||
if i == index {
|
||||
note.Content = content
|
||||
note.EditedOn = ts
|
||||
dnote[targetBookName].Notes[i] = note
|
||||
targetNote.Content = utils.SanitizeContent(newContent)
|
||||
targetNote.EditedOn = ts
|
||||
targetBook.Notes[targetIdx] = targetNote
|
||||
dnote[targetBookName] = targetBook
|
||||
|
||||
err := core.LogActionEditNote(ctx, note.UUID, targetBook.Name, note.Content, ts)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to log action")
|
||||
}
|
||||
|
||||
err = core.WriteDnote(ctx, dnote)
|
||||
fmt.Printf("Edited Note : %d \n", index)
|
||||
return err
|
||||
}
|
||||
err = core.LogActionEditNote(ctx, targetNote.UUID, targetBook.Name, targetNote.Content, ts)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to log action")
|
||||
}
|
||||
|
||||
// If loop finishes without returning, note did not exist
|
||||
fmt.Println("Error : The note with that index is not found.")
|
||||
err = core.WriteDnote(ctx, dnote)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to write dnote")
|
||||
}
|
||||
|
||||
log.Info("edited the note")
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
@ -24,7 +25,9 @@ func NewCmd(ctx infra.DnoteCtx) *cobra.Command {
|
|||
|
||||
func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
fmt.Print("Please enter your APIKey: ")
|
||||
log.Printf("welcome to the dnote cloud :)\n")
|
||||
log.Printf("you can get the api key from https://dnote.io\n")
|
||||
log.Infof("api key: ")
|
||||
|
||||
var apiKey string
|
||||
fmt.Scanln(&apiKey)
|
||||
|
|
@ -40,6 +43,8 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Infof("credential configured\n")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ package ls
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
}
|
||||
}
|
||||
|
||||
fmt.Printf("On note %s\n", bookName)
|
||||
log.Infof("on book %s\n", bookName)
|
||||
|
||||
dnote, err := core.GetDnote(ctx)
|
||||
if err != nil {
|
||||
|
|
@ -53,7 +53,7 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
for k, v := range dnote {
|
||||
if k == bookName {
|
||||
for i, note := range v.Notes {
|
||||
fmt.Printf("* [%d] - %s\n", i, note.Content)
|
||||
fmt.Printf(" \033[%dm(%d)\033[0m %s\n", log.ColorYellow, i, note.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/dnote-io/cli/utils"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -38,7 +39,10 @@ func NewCmd(ctx infra.DnoteCtx) *cobra.Command {
|
|||
func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
||||
return func(cmd *cobra.Command, args []string) error {
|
||||
if targetBookName != "" {
|
||||
book(ctx, targetBookName)
|
||||
err := book(ctx, targetBookName)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to delete the book")
|
||||
}
|
||||
} else {
|
||||
if len(args) < 2 {
|
||||
return errors.New("Missing argument")
|
||||
|
|
@ -79,13 +83,14 @@ func note(ctx infra.DnoteCtx, index int, bookName string) error {
|
|||
}
|
||||
|
||||
content := notes[index].Content
|
||||
fmt.Printf("Deleting note: %s\n", content)
|
||||
log.Printf("content: \"%s\"\n", content)
|
||||
|
||||
ok, err := utils.AskConfirmation("Are you sure?")
|
||||
ok, err := utils.AskConfirmation("remove this note?")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to get confirmation")
|
||||
}
|
||||
if !ok {
|
||||
log.Warnf("aborted by user\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -102,17 +107,18 @@ func note(ctx infra.DnoteCtx, index int, bookName string) error {
|
|||
return errors.Wrap(err, "Failed to write dnote")
|
||||
}
|
||||
|
||||
fmt.Printf("Deleted!\n")
|
||||
log.Infof("removed from %s\n", bookName)
|
||||
return nil
|
||||
}
|
||||
|
||||
// book deletes a book with the given name
|
||||
func book(ctx infra.DnoteCtx, bookName string) error {
|
||||
ok, err := utils.AskConfirmation("Are you sure?")
|
||||
ok, err := utils.AskConfirmation(fmt.Sprintf("delete book '%s' and all its notes?", bookName))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
log.Warnf("aborted by user\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -134,11 +140,10 @@ func book(ctx infra.DnoteCtx, bookName string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("[-] Deleted book : %s \n", bookName)
|
||||
log.Info("removed book\n")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("Error : The book with that name is not found.")
|
||||
return nil
|
||||
return errors.Errorf("Book '%s' was not found", bookName)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ import (
|
|||
)
|
||||
|
||||
var root = &cobra.Command{
|
||||
Use: "dnote",
|
||||
Short: "Dnote - Instantly capture what you learn while coding",
|
||||
Use: "dnote",
|
||||
Short: "Dnote - Instantly capture what you learn while coding",
|
||||
SilenceErrors: true,
|
||||
SilenceUsage: true,
|
||||
}
|
||||
|
||||
// Register adds a new command
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
|
@ -48,23 +49,27 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to read the timestamp")
|
||||
}
|
||||
actions, err := core.ReadActionLog(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to read the action log")
|
||||
}
|
||||
|
||||
if config.APIKey == "" {
|
||||
fmt.Println("Login required. Please run `dnote login`")
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println("Compressing dnote...")
|
||||
payload, err := getPayload(ctx, timestamp)
|
||||
payload, err := getPayload(actions, timestamp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to get dnote payload")
|
||||
}
|
||||
|
||||
fmt.Println("Syncing with the server...")
|
||||
log.Infof("writing changes (total %d).", len(actions))
|
||||
resp, err := postActions(ctx, config.APIKey, payload)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to post to the server ")
|
||||
}
|
||||
fmt.Println(" done.")
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
|
|
@ -84,10 +89,12 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
return errors.Wrap(err, "Failed to unmarshal payload")
|
||||
}
|
||||
|
||||
log.Infof("resolving delta (total %d).", len(respData.Actions))
|
||||
err = core.ReduceAll(ctx, respData.Actions)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to reduce returned actions")
|
||||
}
|
||||
fmt.Println(" done.")
|
||||
|
||||
// Update bookmark
|
||||
ts, err := core.ReadTimestamp(ctx)
|
||||
|
|
@ -98,7 +105,7 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
return errors.Wrap(err, "Failed to update bookmark")
|
||||
}
|
||||
|
||||
fmt.Println("Successfully synced all notes")
|
||||
log.Infof("synced\n")
|
||||
if err := core.ClearActionLog(ctx); err != nil {
|
||||
return errors.Wrap(err, "Failed to clear the action log")
|
||||
}
|
||||
|
|
@ -107,15 +114,15 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func getPayload(ctx infra.DnoteCtx, timestamp infra.Timestamp) (*bytes.Buffer, error) {
|
||||
actions, err := compressActions(ctx)
|
||||
func getPayload(actions []core.Action, timestamp infra.Timestamp) (*bytes.Buffer, error) {
|
||||
compressedActions, err := compressActions(actions)
|
||||
if err != nil {
|
||||
return &bytes.Buffer{}, errors.Wrap(err, "Failed to compress actions")
|
||||
}
|
||||
|
||||
payload := syncPayload{
|
||||
Bookmark: timestamp.Bookmark,
|
||||
Actions: actions,
|
||||
Actions: compressedActions,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(payload)
|
||||
|
|
@ -127,10 +134,10 @@ func getPayload(ctx infra.DnoteCtx, timestamp infra.Timestamp) (*bytes.Buffer, e
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func compressActions(ctx infra.DnoteCtx) ([]byte, error) {
|
||||
b, err := core.ReadActionLogContent(ctx)
|
||||
func compressActions(actions []core.Action) ([]byte, error) {
|
||||
b, err := json.Marshal(&actions)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to read the action log content")
|
||||
return nil, errors.Wrap(err, "failed to marshal actions into JSON")
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
package use
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
|
@ -32,8 +31,7 @@ func newRun(ctx infra.DnoteCtx) core.RunEFunc {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Now using %s\n", targetBookName)
|
||||
log.Infof("now on book '%s'\n", targetBookName)
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import (
|
|||
|
||||
const (
|
||||
// Version is the current version of dnote
|
||||
Version = "0.2.0-alpha"
|
||||
Version = "0.2.0-alpha.2"
|
||||
|
||||
// TimestampFilename is the name of the file containing upgrade info
|
||||
TimestampFilename = "timestamps"
|
||||
|
|
|
|||
39
log/log.go
Normal file
39
log/log.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
ColorRed = 31
|
||||
ColorGreen = 32
|
||||
ColorYellow = 33
|
||||
ColorBlue = 34
|
||||
ColorGray = 37
|
||||
)
|
||||
|
||||
var indent = " "
|
||||
|
||||
func Info(msg string) {
|
||||
fmt.Printf("%s\033[%dm%s\033[0m %s\n", indent, ColorBlue, "•", msg)
|
||||
}
|
||||
|
||||
func Infof(msg string, v ...interface{}) {
|
||||
fmt.Printf("%s\033[%dm%s\033[0m %s", indent, ColorBlue, "•", fmt.Sprintf(msg, v...))
|
||||
}
|
||||
|
||||
func Warnf(msg string, v ...interface{}) {
|
||||
fmt.Printf("%s\033[%dm%s\033[0m %s", indent, ColorRed, "•", fmt.Sprintf(msg, v...))
|
||||
}
|
||||
|
||||
func Error(msg string) {
|
||||
fmt.Printf("%s\033[%dm%s\033[0m %s\n", indent, ColorRed, "⨯", msg)
|
||||
}
|
||||
|
||||
func Printf(msg string, v ...interface{}) {
|
||||
fmt.Printf("%s\033[%dm%s\033[0m %s", indent, ColorGray, "•", fmt.Sprintf(msg, v...))
|
||||
}
|
||||
|
||||
func WithPrefixf(prefixColor int, prefix, msg string, v ...interface{}) {
|
||||
fmt.Printf(" \033[%dm%s\033[0m %s\n", prefixColor, prefix, fmt.Sprintf(msg, v...))
|
||||
}
|
||||
2
main.go
2
main.go
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/dnote-io/cli/cmd/root"
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
// commands
|
||||
|
|
@ -49,6 +50,7 @@ func main() {
|
|||
root.Register(upgrade.NewCmd(ctx))
|
||||
|
||||
if err := root.Execute(); err != nil {
|
||||
log.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
80
main_test.go
80
main_test.go
|
|
@ -191,7 +191,77 @@ func TestEdit(t *testing.T) {
|
|||
testutils.WriteFile(ctx, "./testutils/fixtures/dnote2.json", "dnote")
|
||||
|
||||
// Execute
|
||||
runDnoteCmd(ctx, "edit", "js", "1", "foo bar")
|
||||
cmd, stderr, err := newDnoteCmd(ctx, "edit", "js", "1")
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Failed to get command"))
|
||||
}
|
||||
stdin, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Failed to get stdin %s"))
|
||||
}
|
||||
defer stdin.Close()
|
||||
|
||||
// Start the program
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Failed to start command"))
|
||||
}
|
||||
|
||||
// enter content
|
||||
_, err = io.WriteString(stdin, "foo bar\n")
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Failed to write to stdin"))
|
||||
}
|
||||
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
panic(errors.Wrapf(err, "Failed to run command %s", stderr.String()))
|
||||
}
|
||||
|
||||
// Test
|
||||
dnote, err := core.GetDnote(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(errors.Wrap(err, "Failed to get dnote"))
|
||||
}
|
||||
actions, err := core.ReadActionLog(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(errors.Wrap(err, "Failed to read actions"))
|
||||
}
|
||||
|
||||
book := dnote["js"]
|
||||
action := actions[0]
|
||||
|
||||
var actionData core.EditNoteData
|
||||
err = json.Unmarshal(action.Data, &actionData)
|
||||
if err != nil {
|
||||
log.Fatalln("Failed to unmarshal the action data: %s", err)
|
||||
}
|
||||
|
||||
testutils.AssertEqual(t, len(actions), 1, "There should be 1 action")
|
||||
testutils.AssertEqual(t, action.Type, core.ActionEditNote, "action type mismatch")
|
||||
testutils.AssertEqual(t, actionData.Content, "foo bar", "action data name mismatch")
|
||||
testutils.AssertEqual(t, actionData.BookName, "js", "action data book_name mismatch")
|
||||
testutils.AssertEqual(t, actionData.NoteUUID, "f0d0fbb7-31ff-45ae-9f0f-4e429c0c797f", "action data note_uuis mismatch")
|
||||
testutils.AssertNotEqual(t, action.Timestamp, 0, "action timestamp mismatch")
|
||||
testutils.AssertEqual(t, len(book.Notes), 2, "Book should have one note")
|
||||
testutils.AssertEqual(t, book.Notes[0].UUID, "43827b9a-c2b0-4c06-a290-97991c896653", "Note should have UUID")
|
||||
testutils.AssertEqual(t, book.Notes[0].Content, "Booleans have toString()", "Note content mismatch")
|
||||
testutils.AssertEqual(t, book.Notes[1].UUID, "f0d0fbb7-31ff-45ae-9f0f-4e429c0c797f", "Note should have UUID")
|
||||
testutils.AssertEqual(t, book.Notes[1].Content, "foo bar", "Note content mismatch")
|
||||
testutils.AssertNotEqual(t, book.Notes[1].EditedOn, int64(0), "Note edited_on mismatch")
|
||||
}
|
||||
func TestEdit_ContentFlag(t *testing.T) {
|
||||
// Setup
|
||||
ctx := testutils.InitCtx("./tmp")
|
||||
testutils.SetupTmp(ctx)
|
||||
defer testutils.ClearTmp(ctx)
|
||||
|
||||
// init files by running root command
|
||||
runDnoteCmd(ctx)
|
||||
testutils.WriteFile(ctx, "./testutils/fixtures/dnote2.json", "dnote")
|
||||
|
||||
// Execute
|
||||
runDnoteCmd(ctx, "edit", "js", "1", "-c", "foo bar")
|
||||
|
||||
// Test
|
||||
dnote, err := core.GetDnote(ctx)
|
||||
|
|
@ -253,8 +323,8 @@ func TestRemoveNote(t *testing.T) {
|
|||
panic(errors.Wrap(err, "Failed to start command"))
|
||||
}
|
||||
|
||||
// Hit return to confirm
|
||||
_, err = io.WriteString(stdin, "\n")
|
||||
// confirm
|
||||
_, err = io.WriteString(stdin, "y\n")
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Failed to write to stdin"))
|
||||
}
|
||||
|
|
@ -326,8 +396,8 @@ func TestRemoveBook(t *testing.T) {
|
|||
panic(errors.Wrap(err, "Failed to start command"))
|
||||
}
|
||||
|
||||
// Hit return to confirm
|
||||
_, err = io.WriteString(stdin, "\n")
|
||||
// confirm
|
||||
_, err = io.WriteString(stdin, "y\n")
|
||||
if err != nil {
|
||||
panic(errors.Wrap(err, "Failed to write to stdin"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"github.com/dnote-io/cli/core"
|
||||
"github.com/dnote-io/cli/infra"
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/dnote-io/cli/utils"
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/pkg/errors"
|
||||
|
|
@ -69,7 +70,7 @@ func AutoUpgrade(ctx infra.DnoteCtx) error {
|
|||
}
|
||||
|
||||
if shouldCheck {
|
||||
willCheck, err := utils.AskConfirmation("Would you like to check for an update?")
|
||||
willCheck, err := utils.AskConfirmation("check for upgrade?")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -86,6 +87,8 @@ func AutoUpgrade(ctx infra.DnoteCtx) error {
|
|||
}
|
||||
|
||||
func Upgrade(ctx infra.DnoteCtx) error {
|
||||
log.Infof("current version is %s\n", core.Version)
|
||||
|
||||
// Fetch the latest version
|
||||
gh := github.NewClient(nil)
|
||||
releases, _, err := gh.Repositories.ListReleases(context.Background(), "dnote-io", "cli", nil)
|
||||
|
|
@ -101,22 +104,31 @@ func Upgrade(ctx infra.DnoteCtx) error {
|
|||
return err
|
||||
}
|
||||
|
||||
log.Infof("latest version is %s\n", latestVersion)
|
||||
|
||||
// Check if up to date
|
||||
if latestVersion == core.Version {
|
||||
fmt.Printf("Up-to-date: %s\n", core.Version)
|
||||
core.InitTimestampFile(ctx)
|
||||
log.Info("you are up-to-date")
|
||||
err = touchLastUpgrade(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to update the upgrade timestamp")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
asset := getAsset(latest)
|
||||
if asset == nil {
|
||||
core.InitTimestampFile(ctx)
|
||||
fmt.Printf("Could not find the release for %s %s", runtime.GOOS, runtime.GOARCH)
|
||||
return nil
|
||||
err = touchLastUpgrade(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Failed to update the upgrade timestamp")
|
||||
}
|
||||
|
||||
return errors.Errorf("Could not find the release for %s %s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
|
||||
// Download temporary file
|
||||
fmt.Printf("Downloading: %s\n", latestVersion)
|
||||
log.Infof("Downloading: %s\n", latestVersion)
|
||||
tmpPath := path.Join(os.TempDir(), "dnote_update")
|
||||
|
||||
out, err := os.Create(tmpPath)
|
||||
|
|
@ -158,7 +170,7 @@ func Upgrade(ctx infra.DnoteCtx) error {
|
|||
return errors.Wrap(err, "Upgrade is done, but failed to update the last_upgrade timestamp.")
|
||||
}
|
||||
|
||||
fmt.Printf("Updated: v%s -> v%s\n", core.Version, latestVersion)
|
||||
fmt.Println("Changelog: https://github.com/dnote-io/cli/releases")
|
||||
log.Infof("Updated: v%s -> v%s\n", core.Version, latestVersion)
|
||||
log.Infof("Changelog: https://github.com/dnote-io/cli/releases")
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@ package utils
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dnote-io/cli/log"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
|
@ -27,18 +28,25 @@ func GenerateUID() string {
|
|||
return uuid.NewV4().String()
|
||||
}
|
||||
|
||||
func AskConfirmation(question string) (bool, error) {
|
||||
fmt.Printf("%s [Y/n]: ", question)
|
||||
|
||||
func GetInput() (string, error) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
res, err := reader.ReadString('\n')
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return false, err
|
||||
return "", errors.Wrap(err, "Failed to read stdin")
|
||||
}
|
||||
|
||||
ok := res == "y\n" || res == "Y\n" || res == "\n"
|
||||
return input, nil
|
||||
}
|
||||
|
||||
return ok, nil
|
||||
func AskConfirmation(question string) (bool, error) {
|
||||
log.Printf("%s (y/N): ", question)
|
||||
|
||||
res, err := GetInput()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "Failed to get user input")
|
||||
}
|
||||
|
||||
return res == "y\n", nil
|
||||
}
|
||||
|
||||
// FileExists checks if the file exists at the given path
|
||||
|
|
@ -144,3 +152,12 @@ func CopyDir(src, dest string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SanitizeContent(s string) string {
|
||||
var ret string
|
||||
|
||||
ret = strings.Replace(s, "\n", "", -1)
|
||||
ret = strings.Replace(ret, "\r\n", "", -1)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue