aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorn-peugnet <n.peugnet@free.fr>2021-09-27 19:55:57 +0200
committern-peugnet <n.peugnet@free.fr>2021-09-27 19:55:57 +0200
commit53640f33362d8d6dc65db403e3b31a6776b49796 (patch)
treef18c69aafc8b614978e4c5d9e10a987240eff5a0
parentccb97e0bb5fb0e0c257411d442183d49dd734822 (diff)
downloaddna-backup-53640f33362d8d6dc65db403e3b31a6776b49796.tar.gz
dna-backup-53640f33362d8d6dc65db403e3b31a6776b49796.zip
add CLI with subcommands
-rw-r--r--TODO.md7
-rw-r--r--main.go78
-rw-r--r--repo.go7
3 files changed, 77 insertions, 15 deletions
diff --git a/TODO.md b/TODO.md
index 0353b41..daa8120 100644
--- a/TODO.md
+++ b/TODO.md
@@ -17,7 +17,7 @@ priority 1
- [x] remove errored files from `fileList`
- [ ] **TODO: Priority 3** add superblock logic.
- [ ] **TODO: Priority 2** add version blocks or journal logic.
-- [ ] command line with subcommands (like, hmm... git ? for instance).
+- [x] command line with subcommands (like, hmm... git ? for instance).
priority 2
----------
@@ -48,6 +48,7 @@ priority 2
listing could be another solution but with this approach we would have
to think about what other metadata we want to store
- [ ] use a symlink aware Walk function (easy enough)
+- [ ] add quick progress bar to CLI
reunion 7/09
------------
@@ -65,8 +66,8 @@ ideas
2. Implement the `fs` interface of Go? Not sure if this will be useful.
-3. If we don't need to reduce read amplification we could compress all chunks if
- it reduces the space used.
+3. If we don't need to reduce read amplification we could compress all chunks
+ together if it reduces the space used.
mystical bug 22/09
------------------
diff --git a/main.go b/main.go
index c0e55d8..cf208c9 100644
--- a/main.go
+++ b/main.go
@@ -8,32 +8,90 @@ import (
"github.com/n-peugnet/dna-backup/logger"
)
+type command struct {
+ Flag *flag.FlagSet
+ Usage string
+ Help string
+ Run func([]string) error
+}
+
const (
- usage = "usage: dna-backup [<options>] [--] <source> <dest>\n\noptions:\n"
+ name = "dna-backup"
+ baseUsage = "<command> [<options>] [--] <args>"
+ commitUsage = "[<options>] [--] <source> <dest>"
+ commitHelp = "Create a new version of folder <source> into repo <dest>"
+ restoreUsage = "[<options>] [--] <source> <dest>"
+ restoreHelp = "Restore the last version from repo <source> into folder <dest>"
)
var (
- logLevel int
+ logLevel int
+ commitCmd = flag.NewFlagSet("commit", flag.ExitOnError)
+ restoreCmd = flag.NewFlagSet("restore", flag.ExitOnError)
+ subcommands = map[string]command{
+ commitCmd.Name(): {commitCmd, commitUsage, commitHelp, commitMain},
+ restoreCmd.Name(): {restoreCmd, restoreUsage, restoreHelp, restoreMain},
+ }
)
func init() {
- flag.IntVar(&logLevel, "v", 3, "log verbosity level (0-4)")
+ // init default help message
+ flag.Usage = func() {
+ fmt.Fprintf(flag.CommandLine.Output(), "usage: %s %s\n\ncommands:\n", name, baseUsage)
+ for _, s := range subcommands {
+ fmt.Printf(" %s %s\n", s.Flag.Name(), s.Help)
+ }
+ os.Exit(1)
+ }
+ // setup subcommands
+ for _, s := range subcommands {
+ s.Flag.IntVar(&logLevel, "v", 3, "log verbosity level (0-4)")
+ }
}
func main() {
- flag.Usage = func() {
- fmt.Fprintf(flag.CommandLine.Output(), usage)
- flag.PrintDefaults()
- }
flag.Parse()
- logger.Init(logLevel)
- if len(flag.Args()) != 2 {
+
+ args := flag.Args()
+ if len(args) < 1 {
+ flag.Usage()
+ }
+ cmd, exists := subcommands[args[0]]
+ if !exists {
+ fmt.Fprintf(flag.CommandLine.Output(), "error: unknown command %s\n\n", args[0])
flag.Usage()
+ }
+ cmd.Flag.Usage = func() {
+ fmt.Fprintf(cmd.Flag.Output(), "usage: %s %s %s\n\noptions:\n", name, cmd.Flag.Name(), cmd.Usage)
+ cmd.Flag.PrintDefaults()
os.Exit(1)
}
- args := flag.Args()
+ cmd.Flag.Parse(args[1:])
+ logger.Init(logLevel)
+ if err := cmd.Run(cmd.Flag.Args()); err != nil {
+ fmt.Fprintf(cmd.Flag.Output(), "error: %s\n\n", err)
+ cmd.Flag.Usage()
+ }
+}
+
+func commitMain(args []string) error {
+ if len(args) != 2 {
+ return fmt.Errorf("wrong number of args")
+ }
source := args[0]
dest := args[1]
repo := NewRepo(dest)
repo.Commit(source)
+ return nil
+}
+
+func restoreMain(args []string) error {
+ if len(args) != 2 {
+ return fmt.Errorf("wrong number args")
+ }
+ source := args[0]
+ dest := args[1]
+ repo := NewRepo(source)
+ repo.Restore(dest)
+ return nil
}
diff --git a/repo.go b/repo.go
index 06524aa..d781b16 100644
--- a/repo.go
+++ b/repo.go
@@ -182,9 +182,12 @@ func (r *Repo) Commit(source string) {
func (r *Repo) Restore(destination string) {
versions := r.loadVersions()
+ logger.Info("loading previous file lists")
r.loadFileLists(versions)
+ logger.Info("loading previous recipies")
r.loadRecipes(versions)
reader, writer := io.Pipe()
+ logger.Info("restoring latest version")
go r.restoreStream(writer, r.recipe)
bufReader := bufio.NewReaderSize(reader, r.chunkSize*2)
for _, file := range r.files {
@@ -353,7 +356,7 @@ func fileList2slice(l []File) (ret slice.Slice) {
}
func slice2fileList(s slice.Slice) (ret []File) {
- ret = make([]File, len(s), len(s))
+ ret = make([]File, len(s))
for i := range s {
if f, ok := s[i].(File); ok {
ret[i] = f
@@ -721,7 +724,7 @@ func recipe2slice(r []Chunk) (ret slice.Slice) {
}
func slice2recipe(s slice.Slice) (ret []Chunk) {
- ret = make([]Chunk, len(s), len(s))
+ ret = make([]Chunk, len(s))
for i := range s {
if c, ok := s[i].(Chunk); ok {
ret[i] = c