Skip to content

Commit

Permalink
feat: from-json and to-json (#4)
Browse files Browse the repository at this point in the history
* fix: hide completion cmd

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>

* feat: from-json and to-json

Signed-off-by: Carlos Alexandro Becker <caarlos0@gmail.com>
  • Loading branch information
caarlos0 authored Feb 3, 2021
1 parent 64412c1 commit 10c761f
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 1 deletion.
1 change: 1 addition & 0 deletions internal/cmd/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Fish:
`,
SilenceUsage: true,
DisableFlagsInUseLine: true,
Hidden: true,
ValidArgs: []string{"bash", "zsh", "fish"},
Args: cobra.ExactValidArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down
61 changes: 61 additions & 0 deletions internal/cmd/fromjson.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cmd

import (
"encoding/json"
"fmt"
"io/ioutil"
"log"

"github.com/caarlos0/tasktimer/internal/model"
"github.com/caarlos0/tasktimer/internal/store"
"github.com/spf13/cobra"
)

type fromJSONCmd struct {
cmd *cobra.Command
}

func newFromJSONCmd() *fromJSONCmd {
var cmd = &cobra.Command{
Use: "from-json",
Short: "Imports a JSON into a project - WARNING: it will wipe the project first, use with care!",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
var project = cmd.Parent().Flag("project").Value.String()
db, f, err := setup(project)
if err != nil {
return err
}
defer db.Close()
defer f.Close()

input, err := ioutil.ReadFile(args[0])
if err != nil {
return fmt.Errorf("failed to read %s: %w", args[0], err)
}

var tasks []model.Task
if err := json.Unmarshal(input, &tasks); err != nil {
return fmt.Errorf("input json is not in the correct format: %w", err)
}

tmp, err := ioutil.TempFile("", "tasktimer-"+project)
if err != nil {
return fmt.Errorf("failed to create backup file: %w", err)
}
if _, err := db.Backup(tmp, 0); err != nil {
return fmt.Errorf("failed to backup to %s: %w", tmp.Name(), err)
}

log.Printf("backup made to %s\n", tmp.Name())

if err := db.DropAll(); err != nil {
return fmt.Errorf("failed to clear database: %w", err)
}

return store.LoadTasks(db, tasks)
},
}

return &fromJSONCmd{cmd: cmd}
}
2 changes: 1 addition & 1 deletion internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func newRootCmd(version string, exit func(int)) *rootCmd {

cmd.PersistentFlags().StringVarP(&root.project, "project", "p", "default", "Project name")

cmd.AddCommand(newRerportCmd().cmd, newCompletionCmd().cmd, newPathsCmd().cmd)
cmd.AddCommand(newRerportCmd().cmd, newCompletionCmd().cmd, newPathsCmd().cmd, newToJSONCmd().cmd, newFromJSONCmd().cmd)

root.cmd = cmd
return root
Expand Down
32 changes: 32 additions & 0 deletions internal/cmd/tojson.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"os"

"github.com/caarlos0/tasktimer/internal/ui"
"github.com/spf13/cobra"
)

type toJSONCmd struct {
cmd *cobra.Command
}

func newToJSONCmd() *toJSONCmd {
var cmd = &cobra.Command{
Use: "to-json",
Short: "Exports the database as JSON",
RunE: func(cmd *cobra.Command, args []string) error {
var project = cmd.Parent().Flag("project").Value.String()
db, f, err := setup(project)
if err != nil {
return err
}
defer db.Close()
defer f.Close()

return ui.WriteProjectJSON(db, project, os.Stdout)
},
}

return &toJSONCmd{cmd: cmd}
}
30 changes: 30 additions & 0 deletions internal/store/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package store

import (
"encoding/json"
"fmt"
"log"
"sort"
"strconv"
Expand Down Expand Up @@ -95,3 +96,32 @@ func CreateTask(db *badger.DB, t string) error {
}.Bytes())
})
}

func LoadTasks(db *badger.DB, tasks []model.Task) error {
return db.Update(func(txn *badger.Txn) error {
seq, err := db.GetSequence(sequenceID, 100)
if err != nil {
return err
}
defer seq.Release()

for _, t := range tasks {
s, err := seq.Next()
if err != nil {
return err
}
var id = string(prefix) + strconv.FormatUint(s, 10)
log.Println("creating task:", id, "->", t)
if err := txn.Set([]byte(id), model.Task{
ID: s,
Title: t.Title,
StartAt: t.StartAt,
EndAt: t.EndAt,
}.Bytes()); err != nil {
return fmt.Errorf("failed to create task: %w", err)
}
}

return nil
})
}
27 changes: 27 additions & 0 deletions internal/ui/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ui

import (
"encoding/json"
"io"

"github.com/caarlos0/tasktimer/internal/store"
"github.com/dgraph-io/badger/v3"
)

// WriteProjectJSON writes the project task list in JSON format to the given
// io.Writer.
func WriteProjectJSON(db *badger.DB, project string, w io.Writer) error {
tasks, err := store.GetTaskList(db)
if err != nil {
return err
}

bts, err := json.Marshal(tasks)
if err != nil {
return err
}

_, err = w.Write(bts)

return err
}

0 comments on commit 10c761f

Please sign in to comment.