diff --git a/cmd/config.go b/cmd/config.go index 73e437e..d636d4a 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -12,6 +12,7 @@ import ( type config struct { target string + target2 string root string tags []string search string @@ -19,6 +20,7 @@ type config struct { add string addSchedule string addTags string + dryRun bool } func getConfig() config { @@ -29,11 +31,13 @@ func getConfig() config { var config config flag.StringVar(&config.target, "f", defaultFilepath, "($PTTODO_FILE) path to yaml file or dir (starting with root then alphabetical for dir)") + flag.StringVar(&config.target2, "g", "", "path to yaml file to merge into root of -f") flag.StringVar(&config.root, "root", DUMP_TODO, "path to pretty print ("+fmt.Sprint([]string{DUMP_ALL, DUMP_TODO, DUMP_SCHEDULED, DUMP_DONE})+")") var tagss string flag.StringVar(&tagss, "tags", "", "csv of all tags to find, -x to invert") flag.StringVar(&config.search, "search", "", "fts case insensitive") flag.BoolVar(&config.edit, "e", false, "edit file") + flag.BoolVar(&config.dryRun, "dry-run", false, "dry run") flag.StringVar(&config.add, "add", "", "todo to add") flag.StringVar(&config.addSchedule, "add-schedule", "", "todo to add schedule") flag.StringVar(&config.addTags, "add-tags", "", "todo to add csv tags") diff --git a/cmd/main.go b/cmd/main.go index 46c1782..9d79be2 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -4,6 +4,7 @@ import ( "bytes" "io" "io/ioutil" + "log" "os" "gitea.inhome.blapointe.com/gogs/pttodo/pttodo" @@ -26,16 +27,93 @@ func main() { func _main() error { config := getConfig() - if err := add(&config); err != nil { - return err + + if config.target2 != "" { + return merge(&config) + } else { + if err := add(&config); err != nil { + return err + } + if err := edit(&config); err != nil { + return err + } + return dump(config) } - if err := edit(&config); err != nil { - return err - } - return dump(config) } -func merge(filepath string, mergeTargetFilePath string) error { +func merge(config *config) error { + if config.target2 == "" { + return nil + } + + baseReader, err := filePathReader(config.target) + if err != nil { + return err + } + baseB, err := ioutil.ReadAll(baseReader) + if err != nil { + return err + } + + mergingReader, err := filePathReader(config.target2) + if err != nil { + return err + } + mergingB, err := ioutil.ReadAll(mergingReader) + if err != nil { + return err + } + + var base, merging pttodo.Root + if err := yaml.Unmarshal(baseB, &base); err != nil { + return err + } + if err := yaml.Unmarshal(mergingB, &merging); err != nil { + return err + } + + slurp := func(dst, src *[]pttodo.Todo) { + _src := *src + for i := range _src { + found := false + for j := range *dst { + found = found || _src[i].Equals((*dst)[j]) + } + if !found { + *dst = append(*dst, _src[i]) + } + } + } + slurp(&base.Todo, &merging.Todo) + slurp(&base.Scheduled, &merging.Scheduled) + slurp(&base.Done, &merging.Done) + + if tmppath, err := marshalRootToTempFile(base); err != nil { + return err + } else if config.dryRun { + log.Println("===before===") + _dump(os.Stdout, []string{config.target}, config.tags, config.search, config.root) + log.Println("===after===") + _dump(os.Stdout, []string{tmppath}, config.tags, config.search, config.root) + } else if err := rename(tmppath, config.target); err != nil { + return err + } + + merging.Done = append(merging.Done, merging.Todo...) + merging.Todo = merging.Todo[:0] + merging.Scheduled = append(merging.Done, merging.Scheduled...) + merging.Scheduled = merging.Scheduled[:0] + if tmppath2, err := marshalRootToTempFile(merging); err != nil { + return err + } else if config.dryRun { + } else if err := rename(tmppath2, config.target2); err != nil { + return err + } + + return nil +} + +func _merge(filepath string, mergeTargetFilePath string) error { baseReader, err := filePathReader(filepath) if err != nil { return err