From df2c065241f9630a8d353e50487a9115ee84e36c Mon Sep 17 00:00:00 2001 From: Paul Ruane Date: Wed, 17 Dec 2014 10:45:20 +0000 Subject: [PATCH] Issue #6: read subcommands from standard input --- src/tmsu/cli/cli.go | 100 ++++++++++++++++++++++----- src/tmsu/cli/commands.go | 25 ++++--- src/tmsu/cli/commands_windows.go | 6 +- src/tmsu/cli/copy.go | 13 +--- src/tmsu/cli/copy_test.go | 4 +- src/tmsu/cli/delete.go | 13 +--- src/tmsu/cli/delete_test.go | 6 +- src/tmsu/cli/dupes.go | 16 ++--- src/tmsu/cli/dupes_test.go | 12 ++-- src/tmsu/cli/files.go | 12 +--- src/tmsu/cli/files_test.go | 50 +++++++------- src/tmsu/cli/help.go | 3 +- src/tmsu/cli/imply.go | 13 +--- src/tmsu/cli/merge.go | 13 +--- src/tmsu/cli/merge_test.go | 10 +-- src/tmsu/cli/mount.go | 7 +- src/tmsu/cli/option.go | 4 +- src/tmsu/cli/rename.go | 13 +--- src/tmsu/cli/rename_test.go | 8 +-- src/tmsu/cli/repair.go | 32 ++------- src/tmsu/cli/repair_test.go | 12 ++-- src/tmsu/cli/stats.go | 8 +-- src/tmsu/cli/status.go | 22 ++---- src/tmsu/cli/status_test.go | 8 +-- src/tmsu/cli/tag.go | 49 +++---------- src/tmsu/cli/tag_test.go | 6 +- src/tmsu/cli/tags.go | 16 ++--- src/tmsu/cli/tags_test.go | 8 +-- src/tmsu/cli/unmount.go | 5 +- src/tmsu/cli/untag.go | 34 ++------- src/tmsu/cli/untag_test.go | 8 +-- src/tmsu/cli/untagged.go | 8 +-- src/tmsu/cli/values.go | 16 ++--- src/tmsu/cli/values_test.go | 6 +- src/tmsu/cli/version.go | 3 +- src/tmsu/cli/vfs.go | 14 ++-- src/tmsu/common/terminal/terminal.go | 2 + src/tmsu/vfs/fusevfs.go | 7 +- 38 files changed, 246 insertions(+), 346 deletions(-) diff --git a/src/tmsu/cli/cli.go b/src/tmsu/cli/cli.go index d1a5cb00..6ed65eb1 100644 --- a/src/tmsu/cli/cli.go +++ b/src/tmsu/cli/cli.go @@ -18,23 +18,20 @@ along with this program. If not, see . package cli import ( + "bufio" + "io" "os" + "strings" "tmsu/common/log" + "tmsu/storage" "tmsu/storage/database" ) -var globalOptions = Options{Option{"--verbose", "-v", "show verbose messages", false, ""}, - Option{"--help", "-h", "show help and exit", false, ""}, - Option{"--version", "-V", "show version information and exit", false, ""}, - Option{"--database", "-D", "use the specified database", true, ""}, - Option{"--color", "", "colorize the output (auto/always/never)", true, ""}, -} - func Run() { helpCommands = commands parser := NewOptionParser(globalOptions, commands) - commandName, options, arguments, err := parser.Parse(os.Args[1:]) + commandName, options, arguments, err := parser.Parse(os.Args[1:]...) if err != nil { log.Fatal(err) } @@ -52,22 +49,91 @@ func Run() { database.Path = dbOption.Argument } + store, err := storage.Open() + if err != nil { + log.Fatalf("could not open storage: %v", err) + } + + if err := store.Begin(); err != nil { + log.Fatalf("could not begin transaction: %v", err) + } + + if commandName == "-" { + err = readCommandsFromStdin(store) + } else { + err = processCommand(store, commandName, options, arguments) + } + + store.Commit() + store.Close() + + if err != nil { + if err != errBlank { + log.Warn(err.Error()) + } + + os.Exit(1) + } +} + +// unexported + +var globalOptions = Options{Option{"--verbose", "-v", "show verbose messages", false, ""}, + Option{"--help", "-h", "show help and exit", false, ""}, + Option{"--version", "-V", "show version information and exit", false, ""}, + Option{"--database", "-D", "use the specified database", true, ""}, + Option{"--color", "", "colorize the output (auto/always/never)", true, ""}, +} + +func readCommandsFromStdin(store *storage.Storage) error { + reader := bufio.NewReader(os.Stdin) + + wereErrors := false + for { + line, _, err := reader.ReadLine() + if err != nil { + if err == io.EOF { + if wereErrors { + return errBlank + } else { + return nil + } + } + + log.Fatal(err) + } + + parser := NewOptionParser(globalOptions, commands) + words := strings.SplitN(string(line), " ", -1) + commandName, options, arguments, err := parser.Parse(words...) + if err != nil { + log.Fatal(err) + } + + if err := processCommand(store, commandName, options, arguments); err != nil { + if err != nil { + if err == errBlank { + wereErrors = true + } else { + return err + } + } + } + } +} + +func processCommand(store *storage.Storage, commandName string, options Options, arguments []string) error { command := findCommand(commands, commandName) if command == nil { log.Fatalf("invalid command '%v'.", commandName) } - err = command.Exec(options, arguments) - if err != nil { - if err != errBlank { - log.Warn(err.Error()) - } - - os.Exit(1) + if err := command.Exec(store, options, arguments); err != nil { + return err } -} -// unexported + return nil +} func findCommand(commands map[string]*Command, commandName string) *Command { command := commands[commandName] diff --git a/src/tmsu/cli/commands.go b/src/tmsu/cli/commands.go index c4e14ae5..c1784356 100644 --- a/src/tmsu/cli/commands.go +++ b/src/tmsu/cli/commands.go @@ -17,6 +17,10 @@ along with this program. If not, see . package cli +import ( + "tmsu/storage" +) + type Command struct { Name string Aliases []string @@ -25,25 +29,28 @@ type Command struct { Description string Examples []string Options Options - Exec func(options Options, args []string) error + Exec func(*storage.Storage, Options, []string) error Hidden bool } var commands = map[string]*Command{ - "copy": &CopyCommand, - "delete": &DeleteCommand, - "dupes": &DupesCommand, - "files": &FilesCommand, - "help": &HelpCommand, - "imply": &ImplyCommand, - "merge": &MergeCommand, + "copy": &CopyCommand, + "delete": &DeleteCommand, + "dupes": &DupesCommand, + "files": &FilesCommand, + "help": &HelpCommand, + "imply": &ImplyCommand, + "merge": &MergeCommand, + "mount": &MountCommand, "rename": &RenameCommand, "repair": &RepairCommand, "stats": &StatsCommand, "status": &StatusCommand, "tag": &TagCommand, "tags": &TagsCommand, + "unmount": &UnmountCommand, "untag": &UntagCommand, "untagged": &UntaggedCommand, "values": &ValuesCommand, - "version": &VersionCommand} + "version": &VersionCommand, + "vfs": &VfsCommand} diff --git a/src/tmsu/cli/commands_windows.go b/src/tmsu/cli/commands_windows.go index 34115357..1ad96432 100644 --- a/src/tmsu/cli/commands_windows.go +++ b/src/tmsu/cli/commands_windows.go @@ -18,7 +18,7 @@ along with this program. If not, see . package cli func init() { - commands["mount"] = &MountCommand - commands["unmount"] = &UnmountCommand - commands["vfs"] = &VfsCommand + delete(commands, "mount") + delete(commands, "unmount") + delete(commands, "vfs") } diff --git a/src/tmsu/cli/copy.go b/src/tmsu/cli/copy.go index bfbbfb89..a651da9a 100644 --- a/src/tmsu/cli/copy.go +++ b/src/tmsu/cli/copy.go @@ -35,18 +35,7 @@ var CopyCommand = Command{ Exec: copyExec, } -func copyExec(options Options, args []string) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - +func copyExec(store *storage.Storage, options Options, args []string) error { sourceTagName := args[0] destTagNames := args[1:] diff --git a/src/tmsu/cli/copy_test.go b/src/tmsu/cli/copy_test.go index 99a8f5f3..3708e291 100644 --- a/src/tmsu/cli/copy_test.go +++ b/src/tmsu/cli/copy_test.go @@ -62,7 +62,7 @@ func TestCopySuccessful(test *testing.T) { // test - if err := CopyCommand.Exec(Options{}, []string{"source", "dest"}); err != nil { + if err := CopyCommand.Exec(store, Options{}, []string{"source", "dest"}); err != nil { test.Fatal(err) } @@ -88,7 +88,7 @@ func TestCopyNonExistentSourceTag(test *testing.T) { // test - err := CopyCommand.Exec(Options{}, []string{"source", "dest"}) + err := CopyCommand.Exec(store, Options{}, []string{"source", "dest"}) // validate diff --git a/src/tmsu/cli/delete.go b/src/tmsu/cli/delete.go index 855a5fd0..70f017ce 100644 --- a/src/tmsu/cli/delete.go +++ b/src/tmsu/cli/delete.go @@ -35,22 +35,11 @@ var DeleteCommand = Command{ Exec: deleteExec, } -func deleteExec(options Options, args []string) error { +func deleteExec(store *storage.Storage, options Options, args []string) error { if len(args) == 0 { return fmt.Errorf("no tags to delete specified") } - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - wereErrors := false for _, tagName := range args { tag, err := store.TagByName(tagName) diff --git a/src/tmsu/cli/delete_test.go b/src/tmsu/cli/delete_test.go index 9c2d3351..d2c10b7c 100644 --- a/src/tmsu/cli/delete_test.go +++ b/src/tmsu/cli/delete_test.go @@ -44,7 +44,7 @@ func TestDeleteUnappliedTag(test *testing.T) { // test - if err := DeleteCommand.Exec(Options{}, []string{"beetroot"}); err != nil { + if err := DeleteCommand.Exec(store, Options{}, []string{"beetroot"}); err != nil { test.Fatal(err) } @@ -113,7 +113,7 @@ func TestDeleteAppliedTag(test *testing.T) { // test - if err := DeleteCommand.Exec(Options{}, []string{"deathrow"}); err != nil { + if err := DeleteCommand.Exec(store, Options{}, []string{"deathrow"}); err != nil { test.Fatal(err) } @@ -166,7 +166,7 @@ func TestDeleteNonExistentTag(test *testing.T) { // test - err := DeleteCommand.Exec(Options{}, []string{"deleteme"}) + err := DeleteCommand.Exec(store, Options{}, []string{"deleteme"}) // validate diff --git a/src/tmsu/cli/dupes.go b/src/tmsu/cli/dupes.go index 5c6bf2ba..6b49b4f7 100644 --- a/src/tmsu/cli/dupes.go +++ b/src/tmsu/cli/dupes.go @@ -40,26 +40,20 @@ var DupesCommand = Command{ Exec: dupesExec, } -func dupesExec(options Options, args []string) error { +func dupesExec(store *storage.Storage, options Options, args []string) error { recursive := options.HasOption("--recursive") switch len(args) { case 0: - findDuplicatesInDb() + findDuplicatesInDb(store) default: - return findDuplicatesOf(args, recursive) + return findDuplicatesOf(store, args, recursive) } return nil } -func findDuplicatesInDb() error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - +func findDuplicatesInDb(store *storage.Storage) error { log.Info(2, "identifying duplicate files.") fileSets, err := store.DuplicateFiles() @@ -85,7 +79,7 @@ func findDuplicatesInDb() error { return nil } -func findDuplicatesOf(paths []string, recursive bool) error { +func findDuplicatesOf(store *storage.Storage, paths []string, recursive bool) error { store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) diff --git a/src/tmsu/cli/dupes_test.go b/src/tmsu/cli/dupes_test.go index 55a404d8..dbba9a97 100644 --- a/src/tmsu/cli/dupes_test.go +++ b/src/tmsu/cli/dupes_test.go @@ -57,7 +57,7 @@ func TestDupesSingle(test *testing.T) { // test - if err := DupesCommand.Exec(Options{}, []string{}); err != nil { + if err := DupesCommand.Exec(store, Options{}, []string{}); err != nil { test.Fatal(err) } @@ -110,7 +110,7 @@ func TestDupesMultiple(test *testing.T) { // test - if err := DupesCommand.Exec(Options{}, []string{}); err != nil { + if err := DupesCommand.Exec(store, Options{}, []string{}); err != nil { test.Fatal(err) } @@ -162,7 +162,7 @@ func TestDupesNone(test *testing.T) { // test - if err := DupesCommand.Exec(Options{}, []string{}); err != nil { + if err := DupesCommand.Exec(store, Options{}, []string{}); err != nil { test.Fatal(err) } @@ -221,7 +221,7 @@ func TestDupesSingleUntaggedFile(test *testing.T) { // test - if err := DupesCommand.Exec(Options{}, []string{path}); err != nil { + if err := DupesCommand.Exec(store, Options{}, []string{path}); err != nil { test.Fatal(err) } @@ -280,7 +280,7 @@ func TestDupesMultipleUntaggedFile(test *testing.T) { // test - if err := DupesCommand.Exec(Options{}, []string{path}); err != nil { + if err := DupesCommand.Exec(store, Options{}, []string{path}); err != nil { test.Fatal(err) } @@ -339,7 +339,7 @@ func TestDupesNoneUntaggedFile(test *testing.T) { // test - if err := DupesCommand.Exec(Options{}, []string{path}); err != nil { + if err := DupesCommand.Exec(store, Options{}, []string{path}); err != nil { test.Fatal(err) } diff --git a/src/tmsu/cli/files.go b/src/tmsu/cli/files.go index 91d2c3d1..644733f2 100644 --- a/src/tmsu/cli/files.go +++ b/src/tmsu/cli/files.go @@ -62,7 +62,7 @@ Note: Your shell may use some punctuation (e.g. < and >) for its own purposes. E Exec: filesExec, } -func filesExec(options Options, args []string) error { +func filesExec(store *storage.Storage, options Options, args []string) error { dirOnly := options.HasOption("--directory") fileOnly := options.HasOption("--file") topOnly := options.HasOption("--top") @@ -84,18 +84,12 @@ func filesExec(options Options, args []string) error { } queryText := strings.Join(args, " ") - return listFilesForQuery(queryText, absPath, dirOnly, fileOnly, topOnly, leafOnly, print0, showCount, explicitOnly) + return listFilesForQuery(store, queryText, absPath, dirOnly, fileOnly, topOnly, leafOnly, print0, showCount, explicitOnly) } // unexported -func listFilesForQuery(queryText, path string, dirOnly, fileOnly, topOnly, leafOnly, print0, showCount, explicitOnly bool) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - +func listFilesForQuery(store *storage.Storage, queryText, path string, dirOnly, fileOnly, topOnly, leafOnly, print0, showCount, explicitOnly bool) error { log.Info(2, "parsing query") expression, err := query.Parse(queryText) diff --git a/src/tmsu/cli/files_test.go b/src/tmsu/cli/files_test.go index dbb9551f..68691ab7 100644 --- a/src/tmsu/cli/files_test.go +++ b/src/tmsu/cli/files_test.go @@ -59,7 +59,7 @@ func TestFilesAll(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{}); err != nil { test.Fatal(err) } @@ -123,7 +123,7 @@ func TestFilesSingleTag(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"b"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"b"}); err != nil { test.Fatal(err) } @@ -186,7 +186,7 @@ func TestFilesNotSingleTag(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"not", "b"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"not", "b"}); err != nil { test.Fatal(err) } @@ -257,7 +257,7 @@ func TestFilesImplicitAnd(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"b", "c"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"b", "c"}); err != nil { test.Fatal(err) } @@ -328,7 +328,7 @@ func TestFilesAnd(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"b", "and", "c"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"b", "and", "c"}); err != nil { test.Fatal(err) } @@ -399,7 +399,7 @@ func TestFilesImplicitAndNot(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"b", "not", "c"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"b", "not", "c"}); err != nil { test.Fatal(err) } @@ -470,7 +470,7 @@ func TestFilesAndNot(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"b", "and", "not", "c"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"b", "and", "not", "c"}); err != nil { test.Fatal(err) } @@ -541,7 +541,7 @@ func TestFilesOr(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"b", "or", "c"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"b", "or", "c"}); err != nil { test.Fatal(err) } @@ -603,10 +603,10 @@ func TestFilesTagEqualsValue(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"size", "=", "100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size", "=", "100"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size = 100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size = 100"}); err != nil { test.Fatal(err) } @@ -668,13 +668,13 @@ func TestFilesTagNotEqualsValue(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"not", "size", "=", "100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"not", "size", "=", "100"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"not size = 100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"not size = 100"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"not size eq 100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"not size eq 100"}); err != nil { test.Fatal(err) } @@ -736,13 +736,13 @@ func TestFilesTagLessThanValue(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"size", "<", "100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size", "<", "100"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size < 100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size < 100"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size lt 100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size lt 100"}); err != nil { test.Fatal(err) } @@ -804,13 +804,13 @@ func TestFilesTagGreaterThanValue(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"size", ">", "99"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size", ">", "99"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size > 99"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size > 99"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size gt 99"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size gt 99"}); err != nil { test.Fatal(err) } @@ -872,13 +872,13 @@ func TestFilesTagLessThanOrEqualToValue(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"size", "<=", "100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size", "<=", "100"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size <= 100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size <= 100"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size le 100"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size le 100"}); err != nil { test.Fatal(err) } @@ -940,13 +940,13 @@ func TestFilesTagGreaterThanOrEqualToValue(test *testing.T) { // test - if err := FilesCommand.Exec(Options{}, []string{"size", ">=", "99"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size", ">=", "99"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size >= 99"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size >= 99"}); err != nil { test.Fatal(err) } - if err := FilesCommand.Exec(Options{}, []string{"size ge 99"}); err != nil { + if err := FilesCommand.Exec(store, Options{}, []string{"size ge 99"}); err != nil { test.Fatal(err) } diff --git a/src/tmsu/cli/help.go b/src/tmsu/cli/help.go index d9b47da8..9f5fc791 100644 --- a/src/tmsu/cli/help.go +++ b/src/tmsu/cli/help.go @@ -25,6 +25,7 @@ import ( "tmsu/common/log" "tmsu/common/terminal" "tmsu/common/terminal/ansi" + "tmsu/storage" ) var HelpCommand = Command{ @@ -38,7 +39,7 @@ var HelpCommand = Command{ var helpCommands map[string]*Command -func helpExec(options Options, args []string) error { +func helpExec(store *storage.Storage, options Options, args []string) error { var colour bool if options.HasOption("--color") { when := options.Get("--color").Argument diff --git a/src/tmsu/cli/imply.go b/src/tmsu/cli/imply.go index 61666b54..e89dc4ee 100644 --- a/src/tmsu/cli/imply.go +++ b/src/tmsu/cli/imply.go @@ -41,18 +41,7 @@ The 'tags' subcommand can be used to identify which tags applied to a file are i Exec: implyExec, } -func implyExec(options Options, args []string) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - +func implyExec(store *storage.Storage, options Options, args []string) error { switch { case options.HasOption("--list"): return listImplications(store) diff --git a/src/tmsu/cli/merge.go b/src/tmsu/cli/merge.go index e7a40e27..2ef5eb80 100644 --- a/src/tmsu/cli/merge.go +++ b/src/tmsu/cli/merge.go @@ -34,22 +34,11 @@ var MergeCommand = Command{ Exec: mergeExec, } -func mergeExec(options Options, args []string) error { +func mergeExec(store *storage.Storage, options Options, args []string) error { if len(args) < 2 { return fmt.Errorf("too few arguments") } - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - destTagName := args[len(args)-1] destTag, err := store.TagByName(destTagName) if err != nil { diff --git a/src/tmsu/cli/merge_test.go b/src/tmsu/cli/merge_test.go index 68cc3756..876255ad 100644 --- a/src/tmsu/cli/merge_test.go +++ b/src/tmsu/cli/merge_test.go @@ -85,7 +85,7 @@ func TestMergeSingleTag(test *testing.T) { // test - if err := MergeCommand.Exec(Options{}, []string{"a", "b"}); err != nil { + if err := MergeCommand.Exec(store, Options{}, []string{"a", "b"}); err != nil { test.Fatal(err) } @@ -196,7 +196,7 @@ func TestMergeMultipleTags(test *testing.T) { // test - if err := MergeCommand.Exec(Options{}, []string{"a", "b", "c"}); err != nil { + if err := MergeCommand.Exec(store, Options{}, []string{"a", "b", "c"}); err != nil { test.Fatal(err) } @@ -253,7 +253,7 @@ func TestMergeNonExistentSourceTag(test *testing.T) { // test - if err := MergeCommand.Exec(Options{}, []string{"a", "b"}); err == nil { + if err := MergeCommand.Exec(store, Options{}, []string{"a", "b"}); err == nil { test.Fatal("Expected non-existent source tag to be identified.") } } @@ -277,7 +277,7 @@ func TestMergeNonExistentDestinationTag(test *testing.T) { // test - if err := MergeCommand.Exec(Options{}, []string{"a", "b"}); err == nil { + if err := MergeCommand.Exec(store, Options{}, []string{"a", "b"}); err == nil { test.Fatal("Expected non-existent destination tag to be identified.") } } @@ -301,7 +301,7 @@ func TestMergeSourceAndDestinationTheSame(test *testing.T) { // test - if err := MergeCommand.Exec(Options{}, []string{"a", "a"}); err == nil { + if err := MergeCommand.Exec(store, Options{}, []string{"a", "a"}); err == nil { test.Fatal("Expected source and destination the same tag to be identified.") } } diff --git a/src/tmsu/cli/mount.go b/src/tmsu/cli/mount.go index d7c3662c..13876602 100644 --- a/src/tmsu/cli/mount.go +++ b/src/tmsu/cli/mount.go @@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +// +build !windows + package cli import ( @@ -25,6 +27,7 @@ import ( "syscall" "time" "tmsu/common/log" + "tmsu/storage" "tmsu/storage/database" "tmsu/vfs" ) @@ -50,7 +53,7 @@ To allow other users access to the mounted filesystem, pass the 'allow_other' FU Exec: mountExec, } -func mountExec(options Options, args []string) error { +func mountExec(store *storage.Storage, options Options, args []string) error { var mountOptions string if options.HasOption("--options") { mountOptions = options.Get("--options").Argument @@ -139,7 +142,7 @@ func mountExplicit(databasePath string, mountPath string, mountOptions string) e log.Infof(2, "spawning daemon to mount VFS for database '%v' at '%v'", databasePath, mountPath) - args := []string{"vfs", databasePath, mountPath, "--options=" + mountOptions} + args := []string{"vfs", "--database=" + databasePath, mountPath, "--options=" + mountOptions} daemon := exec.Command(os.Args[0], args...) errorPipe, err := daemon.StderrPipe() diff --git a/src/tmsu/cli/option.go b/src/tmsu/cli/option.go index cc9267bf..2374c012 100644 --- a/src/tmsu/cli/option.go +++ b/src/tmsu/cli/option.go @@ -74,7 +74,7 @@ func NewOptionParser(globalOptions Options, commandByName map[string]*Command) * return &parser } -func (parser *OptionParser) Parse(args []string) (commandName string, options Options, arguments []string, err error) { +func (parser *OptionParser) Parse(args... string) (commandName string, options Options, arguments []string, err error) { commandName = "" options = make(Options, 0) arguments = make([]string, 0) @@ -93,7 +93,7 @@ func (parser *OptionParser) Parse(args []string) (commandName string, options Op case "--": parseOptions = false default: - if parseOptions && arg[0] == '-' { + if parseOptions && len(arg) > 1 && arg[0] == '-' { parts := strings.SplitN(arg, "=", 2) optionName := parts[0] diff --git a/src/tmsu/cli/rename.go b/src/tmsu/cli/rename.go index 40f27e2d..e87b8a67 100644 --- a/src/tmsu/cli/rename.go +++ b/src/tmsu/cli/rename.go @@ -36,18 +36,7 @@ Attempting to rename a tag with a new name for which a tag already exists will r Exec: renameExec, } -func renameExec(options Options, args []string) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - +func renameExec(store *storage.Storage, options Options, args []string) error { if len(args) < 2 { return fmt.Errorf("tag to rename and new name must both be specified") } diff --git a/src/tmsu/cli/rename_test.go b/src/tmsu/cli/rename_test.go index 7fcb1028..52721359 100644 --- a/src/tmsu/cli/rename_test.go +++ b/src/tmsu/cli/rename_test.go @@ -62,7 +62,7 @@ func TestRenameSuccessful(test *testing.T) { // test - if err := RenameCommand.Exec(Options{}, []string{"source", "dest"}); err != nil { + if err := RenameCommand.Exec(store, Options{}, []string{"source", "dest"}); err != nil { test.Fatal(err) } @@ -99,7 +99,7 @@ func TestRenameNonExistentSourceTag(test *testing.T) { // test - err := RenameCommand.Exec(Options{}, []string{"source", "dest"}) + err := RenameCommand.Exec(store, Options{}, []string{"source", "dest"}) // validate @@ -116,7 +116,7 @@ func TestRenameInvalidDestTag(test *testing.T) { // test - err := RenameCommand.Exec(Options{}, []string{"source", "slash/invalid"}) + err := RenameCommand.Exec(store, Options{}, []string{"source", "slash/invalid"}) // validate @@ -149,7 +149,7 @@ func TestRenameDestTagAlreadyExists(test *testing.T) { // test - err = RenameCommand.Exec(Options{}, []string{"source", "dest"}) + err = RenameCommand.Exec(store, Options{}, []string{"source", "dest"}) // validate diff --git a/src/tmsu/cli/repair.go b/src/tmsu/cli/repair.go index b0472c37..b13a6b79 100644 --- a/src/tmsu/cli/repair.go +++ b/src/tmsu/cli/repair.go @@ -60,14 +60,14 @@ When run with the --manual option, any paths that begin with OLD are updated to // unexported -func repairExec(options Options, args []string) error { +func repairExec(store *storage.Storage, options Options, args []string) error { pretend := options.HasOption("--pretend") if options.HasOption("--manual") { fromPath := args[0] toPath := args[1] - if err := manualRepair(fromPath, toPath, pretend); err != nil { + if err := manualRepair(store, fromPath, toPath, pretend); err != nil { return err } } else { @@ -81,7 +81,7 @@ func repairExec(options Options, args []string) error { limitPath = options.Get("--path").Argument } - if err := fullRepair(searchPaths, limitPath, removeMissing, recalcUnmodified, rationalize, pretend); err != nil { + if err := fullRepair(store, searchPaths, limitPath, removeMissing, recalcUnmodified, rationalize, pretend); err != nil { return err } } @@ -89,7 +89,7 @@ func repairExec(options Options, args []string) error { return nil } -func manualRepair(fromPath, toPath string, pretend bool) error { +func manualRepair(store *storage.Storage, fromPath, toPath string, pretend bool) error { absFromPath, err := filepath.Abs(fromPath) if err != nil { return fmt.Errorf("%v: could not determine absolute path", err) @@ -100,17 +100,6 @@ func manualRepair(fromPath, toPath string, pretend bool) error { return fmt.Errorf("%v: could not determine absolute path", err) } - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - log.Infof(2, "retrieving files under '%v' from the database", fromPath) dbFile, err := store.FileByPath(absFromPath) @@ -181,23 +170,12 @@ func manualRepairFile(store *storage.Storage, file *entities.File, toPath string return err } -func fullRepair(searchPaths []string, limitPath string, removeMissing, recalcUnmodified, rationalize, pretend bool) error { +func fullRepair(store *storage.Storage, searchPaths []string, limitPath string, removeMissing, recalcUnmodified, rationalize, pretend bool) error { absLimitPath, err := filepath.Abs(limitPath) if err != nil { return fmt.Errorf("%v: could not determine absolute path", err) } - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - fingerprintAlgorithm, err := store.SettingAsString("fingerprintAlgorithm") if err != nil { return err diff --git a/src/tmsu/cli/repair_test.go b/src/tmsu/cli/repair_test.go index d0f7f77d..67a3b0db 100644 --- a/src/tmsu/cli/repair_test.go +++ b/src/tmsu/cli/repair_test.go @@ -41,7 +41,7 @@ func TestRepairMovedFile(test *testing.T) { } defer os.Remove("/tmp/tmsu/a") - if err := TagCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "a"}); err != nil { + if err := TagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "a"}); err != nil { test.Fatal(err) } @@ -51,7 +51,7 @@ func TestRepairMovedFile(test *testing.T) { // test - if err := RepairCommand.Exec(Options{}, []string{"/tmp/tmsu"}); err != nil { + if err := RepairCommand.Exec(store, Options{}, []string{"/tmp/tmsu"}); err != nil { test.Fatal(err) } @@ -88,7 +88,7 @@ func TestRepairModifiedFile(test *testing.T) { } defer os.Remove("/tmp/tmsu/a") - if err := TagCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "a"}); err != nil { + if err := TagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "a"}); err != nil { test.Fatal(err) } @@ -98,7 +98,7 @@ func TestRepairModifiedFile(test *testing.T) { // test - if err := RepairCommand.Exec(Options{}, []string{"/tmp/tmsu"}); err != nil { + if err := RepairCommand.Exec(store, Options{}, []string{"/tmp/tmsu"}); err != nil { test.Fatal(err) } @@ -140,7 +140,7 @@ func TestReportsMissingFiles(test *testing.T) { test.Fatal(err) } - if err := TagCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "a"}); err != nil { + if err := TagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "a"}); err != nil { test.Fatal(err) } @@ -150,7 +150,7 @@ func TestReportsMissingFiles(test *testing.T) { // test - if err := RepairCommand.Exec(Options{}, []string{}); err != nil { + if err := RepairCommand.Exec(store, Options{}, []string{}); err != nil { test.Fatal(err) } diff --git a/src/tmsu/cli/stats.go b/src/tmsu/cli/stats.go index 818f496f..39936d42 100644 --- a/src/tmsu/cli/stats.go +++ b/src/tmsu/cli/stats.go @@ -32,15 +32,9 @@ var StatsCommand = Command{ Exec: statsExec, } -func statsExec(options Options, args []string) error { +func statsExec(store *storage.Storage, options Options, args []string) error { usage := options.HasOption("--usage") - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - tagCount, err := store.TagCount() if err != nil { return fmt.Errorf("could not retrieve tag count: %v", err) diff --git a/src/tmsu/cli/status.go b/src/tmsu/cli/status.go index 69bcb7cd..b727cbba 100644 --- a/src/tmsu/cli/status.go +++ b/src/tmsu/cli/status.go @@ -87,19 +87,19 @@ func NewReport() *StatusReport { return &StatusReport{make([]Row, 0, 10)} } -func statusExec(options Options, args []string) error { +func statusExec(store *storage.Storage, options Options, args []string) error { dirOnly := options.HasOption("--directory") var report *StatusReport var err error if len(args) == 0 { - report, err = statusDatabase(dirOnly) + report, err = statusDatabase(store, dirOnly) if err != nil { return err } } else { - report, err = statusPaths(args, dirOnly) + report, err = statusPaths(store, args, dirOnly) if err != nil { return err } @@ -110,15 +110,9 @@ func statusExec(options Options, args []string) error { return nil } -func statusDatabase(dirOnly bool) (*StatusReport, error) { +func statusDatabase(store *storage.Storage, dirOnly bool) (*StatusReport, error) { report := NewReport() - store, err := storage.Open() - if err != nil { - return nil, fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - log.Info(2, "retrieving all files from database.") files, err := store.Files() @@ -150,15 +144,9 @@ func statusDatabase(dirOnly bool) (*StatusReport, error) { return report, nil } -func statusPaths(paths []string, dirOnly bool) (*StatusReport, error) { +func statusPaths(store *storage.Storage, paths []string, dirOnly bool) (*StatusReport, error) { report := NewReport() - store, err := storage.Open() - if err != nil { - return nil, fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - for _, path := range paths { absPath, err := filepath.Abs(path) if err != nil { diff --git a/src/tmsu/cli/status_test.go b/src/tmsu/cli/status_test.go index 167050a3..0aa96b2e 100644 --- a/src/tmsu/cli/status_test.go +++ b/src/tmsu/cli/status_test.go @@ -55,15 +55,15 @@ func TestStatusReport(test *testing.T) { } defer os.Remove("/tmp/tmsu/d") - if err := TagCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "a"}); err != nil { + if err := TagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "a"}); err != nil { test.Fatal(err) } - if err := TagCommand.Exec(Options{}, []string{"/tmp/tmsu/b", "b"}); err != nil { + if err := TagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/b", "b"}); err != nil { test.Fatal(err) } - if err := TagCommand.Exec(Options{}, []string{"/tmp/tmsu/d", "d"}); err != nil { + if err := TagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/d", "d"}); err != nil { test.Fatal(err) } @@ -80,7 +80,7 @@ func TestStatusReport(test *testing.T) { // test - if err := StatusCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b", "/tmp/tmsu/c", "/tmp/tmsu/d"}); err != nil { + if err := StatusCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b", "/tmp/tmsu/c", "/tmp/tmsu/d"}); err != nil { test.Fatal(err) } diff --git a/src/tmsu/cli/tag.go b/src/tmsu/cli/tag.go index ac9769bf..07250fea 100644 --- a/src/tmsu/cli/tag.go +++ b/src/tmsu/cli/tag.go @@ -53,7 +53,7 @@ Optionally tags applied to files may be attributed with a VALUE using the TAG=VA Exec: tagExec, } -func tagExec(options Options, args []string) error { +func tagExec(store *storage.Storage, options Options, args []string) error { recursive := options.HasOption("--recursive") explicit := options.HasOption("--explicit") @@ -63,7 +63,7 @@ func tagExec(options Options, args []string) error { return fmt.Errorf("set of tags to create must be specified") } - if err := createTags(args); err != nil { + if err := createTags(store, args); err != nil { return err } case options.HasOption("--tags"): @@ -81,7 +81,7 @@ func tagExec(options Options, args []string) error { return fmt.Errorf("at least one file to tag must be specified") } - if err := tagPaths(tagArgs, paths, explicit, recursive); err != nil { + if err := tagPaths(store, tagArgs, paths, explicit, recursive); err != nil { return err } case options.HasOption("--from"): @@ -96,7 +96,7 @@ func tagExec(options Options, args []string) error { paths := args - if err := tagFrom(fromPath, paths, explicit, recursive); err != nil { + if err := tagFrom(store, fromPath, paths, explicit, recursive); err != nil { return err } default: @@ -107,7 +107,7 @@ func tagExec(options Options, args []string) error { paths := args[0:1] tagArgs := args[1:] - if err := tagPaths(tagArgs, paths, explicit, recursive); err != nil { + if err := tagPaths(store, tagArgs, paths, explicit, recursive); err != nil { return err } } @@ -115,18 +115,7 @@ func tagExec(options Options, args []string) error { return nil } -func createTags(tagNames []string) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - +func createTags(store *storage.Storage, tagNames []string) error { wereErrors := false for _, tagName := range tagNames { tag, err := store.TagByName(tagName) @@ -154,18 +143,7 @@ func createTags(tagNames []string) error { return nil } -func tagPaths(tagArgs, paths []string, explicit, recursive bool) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - +func tagPaths(store *storage.Storage, tagArgs, paths []string, explicit, recursive bool) error { fingerprintAlgorithm, err := store.SettingAsString("fingerprintAlgorithm") if err != nil { return err @@ -254,18 +232,7 @@ func tagPaths(tagArgs, paths []string, explicit, recursive bool) error { return nil } -func tagFrom(fromPath string, paths []string, explicit, recursive bool) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - +func tagFrom(store *storage.Storage, fromPath string, paths []string, explicit, recursive bool) error { fingerprintAlgorithmSetting, err := store.Setting("fingerprintAlgorithm") if err != nil { return fmt.Errorf("could not retrieve fingerprint algorithm: %v", err) diff --git a/src/tmsu/cli/tag_test.go b/src/tmsu/cli/tag_test.go index 0e9672c5..e2d181bd 100644 --- a/src/tmsu/cli/tag_test.go +++ b/src/tmsu/cli/tag_test.go @@ -42,7 +42,7 @@ func TestSingleTag(test *testing.T) { // test - if err := TagCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "apple"}); err != nil { + if err := TagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "apple"}); err != nil { test.Fatal(err) } @@ -104,7 +104,7 @@ func TestMultipleTags(test *testing.T) { // test - if err := TagCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "apple", "banana", "clementine"}); err != nil { + if err := TagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "apple", "banana", "clementine"}); err != nil { test.Fatal(err) } @@ -189,7 +189,7 @@ func TestTagMultipleFiles(test *testing.T) { // test - if err := TagCommand.Exec(Options{Option{"--tags", "-t", "", true, "apple banana"}}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b"}); err != nil { + if err := TagCommand.Exec(store, Options{Option{"--tags", "-t", "", true, "apple banana"}}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b"}); err != nil { test.Fatal(err) } diff --git a/src/tmsu/cli/tags.go b/src/tmsu/cli/tags.go index fcf97178..b56401d0 100644 --- a/src/tmsu/cli/tags.go +++ b/src/tmsu/cli/tags.go @@ -52,7 +52,7 @@ See the 'imply' subcommand for more information on implied tags.`, Exec: tagsExec, } -func tagsExec(options Options, args []string) error { +func tagsExec(store *storage.Storage, options Options, args []string) error { showCount := options.HasOption("--count") onePerLine := options.HasOption("-1") explicitOnly := options.HasOption("--explicit") @@ -76,19 +76,13 @@ func tagsExec(options Options, args []string) error { } if len(args) == 0 { - return listAllTags(showCount, onePerLine, colour) + return listAllTags(store, showCount, onePerLine, colour) } - return listTagsForPaths(args, showCount, onePerLine, explicitOnly, colour) + return listTagsForPaths(store, args, showCount, onePerLine, explicitOnly, colour) } -func listAllTags(showCount, onePerLine, colour bool) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - +func listAllTags(store *storage.Storage, showCount, onePerLine, colour bool) error { log.Info(2, "retrieving all tags.") if showCount { @@ -121,7 +115,7 @@ func listAllTags(showCount, onePerLine, colour bool) error { return nil } -func listTagsForPaths(paths []string, showCount, onePerLine, explicitOnly, colour bool) error { +func listTagsForPaths(store *storage.Storage, paths []string, showCount, onePerLine, explicitOnly, colour bool) error { store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) diff --git a/src/tmsu/cli/tags_test.go b/src/tmsu/cli/tags_test.go index b00e5144..7c54dd19 100644 --- a/src/tmsu/cli/tags_test.go +++ b/src/tmsu/cli/tags_test.go @@ -71,7 +71,7 @@ func TestTagsForSingleFile(test *testing.T) { // test - if err := TagsCommand.Exec(Options{}, []string{"/tmp/tmsu/a"}); err != nil { + if err := TagsCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a"}); err != nil { test.Fatal(err) } @@ -138,7 +138,7 @@ func TestTagsForMultipleFiles(test *testing.T) { // test - if err := TagsCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b"}); err != nil { + if err := TagsCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b"}); err != nil { test.Fatal(err) } @@ -180,7 +180,7 @@ func TestAllTags(test *testing.T) { // test - if err := TagsCommand.Exec(Options{}, []string{}); err != nil { + if err := TagsCommand.Exec(store, Options{}, []string{}); err != nil { test.Fatal(err) } @@ -245,7 +245,7 @@ func TestImpliedTags(test *testing.T) { // test - if err := TagsCommand.Exec(Options{}, []string{"/tmp/tmsu/a"}); err != nil { + if err := TagsCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a"}); err != nil { test.Fatal(err) } diff --git a/src/tmsu/cli/unmount.go b/src/tmsu/cli/unmount.go index 35cc0d71..20a0019b 100644 --- a/src/tmsu/cli/unmount.go +++ b/src/tmsu/cli/unmount.go @@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +// +build !windows + package cli import ( @@ -22,6 +24,7 @@ import ( "os" "os/exec" "tmsu/common/log" + "tmsu/storage" "tmsu/vfs" ) @@ -36,7 +39,7 @@ var UnmountCommand = Command{ Exec: unmountExec, } -func unmountExec(options Options, args []string) error { +func unmountExec(store *storage.Storage, options Options, args []string) error { if options.HasOption("--all") { return unmountAll() } diff --git a/src/tmsu/cli/untag.go b/src/tmsu/cli/untag.go index cbfbd973..97469e25 100644 --- a/src/tmsu/cli/untag.go +++ b/src/tmsu/cli/untag.go @@ -42,7 +42,7 @@ var UntagCommand = Command{ Exec: untagExec, } -func untagExec(options Options, args []string) error { +func untagExec(store *storage.Storage, options Options, args []string) error { if len(args) < 1 { return fmt.Errorf("no arguments specified") } @@ -56,7 +56,7 @@ func untagExec(options Options, args []string) error { paths := args - if err := untagPathsAll(paths, recursive); err != nil { + if err := untagPathsAll(store, paths, recursive); err != nil { return err } } else if options.HasOption("--tags") { @@ -70,7 +70,7 @@ func untagExec(options Options, args []string) error { return fmt.Errorf("at least one file to untag must be specified") } - if err := untagPaths(paths, tagArgs, recursive); err != nil { + if err := untagPaths(store, paths, tagArgs, recursive); err != nil { return err } } else { @@ -81,7 +81,7 @@ func untagExec(options Options, args []string) error { paths := args[0:1] tagArgs := args[1:] - if err := untagPaths(paths, tagArgs, recursive); err != nil { + if err := untagPaths(store, paths, tagArgs, recursive); err != nil { return err } } @@ -89,18 +89,7 @@ func untagExec(options Options, args []string) error { return nil } -func untagPathsAll(paths []string, recursive bool) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - +func untagPathsAll(store *storage.Storage, paths []string, recursive bool) error { wereErrors := false for _, path := range paths { absPath, err := filepath.Abs(path) @@ -145,18 +134,7 @@ func untagPathsAll(paths []string, recursive bool) error { return nil } -func untagPaths(paths, tagArgs []string, recursive bool) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - - if err := store.Begin(); err != nil { - return fmt.Errorf("could not begin transaction: %v", err) - } - defer store.Commit() - +func untagPaths(store *storage.Storage, paths, tagArgs []string, recursive bool) error { wereErrors := false files := make(entities.Files, 0, len(paths)) diff --git a/src/tmsu/cli/untag_test.go b/src/tmsu/cli/untag_test.go index 2606b58b..f166c0eb 100644 --- a/src/tmsu/cli/untag_test.go +++ b/src/tmsu/cli/untag_test.go @@ -64,7 +64,7 @@ func TestSingleUntag(test *testing.T) { // test - if err := UntagCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "apple"}); err != nil { + if err := UntagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "apple"}); err != nil { test.Fatal(err) } @@ -121,7 +121,7 @@ func TestMultipleUntag(test *testing.T) { // test - if err := UntagCommand.Exec(Options{}, []string{"/tmp/tmsu/a", "apple", "banana"}); err != nil { + if err := UntagCommand.Exec(store, Options{}, []string{"/tmp/tmsu/a", "apple", "banana"}); err != nil { test.Fatal(err) } @@ -183,7 +183,7 @@ func TestUntagMultipleFiles(test *testing.T) { // test - if err := UntagCommand.Exec(Options{Option{"--tags", "-t", "", true, "apple"}}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b"}); err != nil { + if err := UntagCommand.Exec(store, Options{Option{"--tags", "-t", "", true, "apple"}}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b"}); err != nil { test.Fatal(err) } @@ -245,7 +245,7 @@ func TestUntagAll(test *testing.T) { // test - if err := UntagCommand.Exec(Options{Option{"--all", "-a", "", false, ""}}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b"}); err != nil { + if err := UntagCommand.Exec(store, Options{Option{"--all", "-a", "", false, ""}}, []string{"/tmp/tmsu/a", "/tmp/tmsu/b"}); err != nil { test.Fatal(err) } diff --git a/src/tmsu/cli/untagged.go b/src/tmsu/cli/untagged.go index 91d63392..06761fdb 100644 --- a/src/tmsu/cli/untagged.go +++ b/src/tmsu/cli/untagged.go @@ -39,7 +39,7 @@ Where PATHs are not specified, untagged items under the current working director Exec: untaggedExec, } -func untaggedExec(options Options, args []string) error { +func untaggedExec(store *storage.Storage, options Options, args []string) error { recursive := !options.HasOption("--directory") paths := args @@ -51,12 +51,6 @@ func untaggedExec(options Options, args []string) error { } } - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - if err := findUntagged(store, paths, recursive); err != nil { return err } diff --git a/src/tmsu/cli/values.go b/src/tmsu/cli/values.go index a79e230e..9eaffb03 100644 --- a/src/tmsu/cli/values.go +++ b/src/tmsu/cli/values.go @@ -38,24 +38,18 @@ var ValuesCommand = Command{ Exec: valuesExec, } -func valuesExec(options Options, args []string) error { +func valuesExec(store *storage.Storage, options Options, args []string) error { showCount := options.HasOption("--count") onePerLine := options.HasOption("-1") if len(args) == 0 { - return listAllValues(showCount, onePerLine) + return listAllValues(store, showCount, onePerLine) } - return listValues(args, showCount, onePerLine) + return listValues(store, args, showCount, onePerLine) } -func listAllValues(showCount, onePerLine bool) error { - store, err := storage.Open() - if err != nil { - return fmt.Errorf("could not open storage: %v", err) - } - defer store.Close() - +func listAllValues(store *storage.Storage, showCount, onePerLine bool) error { log.Info(2, "retrieving all values.") if showCount { @@ -88,7 +82,7 @@ func listAllValues(showCount, onePerLine bool) error { return nil } -func listValues(tagNames []string, showCount, onePerLine bool) error { +func listValues(store *storage.Storage, tagNames []string, showCount, onePerLine bool) error { store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) diff --git a/src/tmsu/cli/values_test.go b/src/tmsu/cli/values_test.go index 78d357a7..aafe57a0 100644 --- a/src/tmsu/cli/values_test.go +++ b/src/tmsu/cli/values_test.go @@ -76,7 +76,7 @@ func TestValuesForSingleTag(test *testing.T) { // test - if err := ValuesCommand.Exec(Options{}, []string{"material"}); err != nil { + if err := ValuesCommand.Exec(store, Options{}, []string{"material"}); err != nil { test.Fatal(err) } @@ -153,7 +153,7 @@ func TestValuesForMulitpleTags(test *testing.T) { // test - if err := ValuesCommand.Exec(Options{}, []string{"material", "shape"}); err != nil { + if err := ValuesCommand.Exec(store, Options{}, []string{"material", "shape"}); err != nil { test.Fatal(err) } @@ -200,7 +200,7 @@ func TestAllValues(test *testing.T) { // test - if err := ValuesCommand.Exec(Options{}, []string{}); err != nil { + if err := ValuesCommand.Exec(store, Options{}, []string{}); err != nil { test.Fatal(err) } diff --git a/src/tmsu/cli/version.go b/src/tmsu/cli/version.go index e5468c2a..2dcb2fe3 100644 --- a/src/tmsu/cli/version.go +++ b/src/tmsu/cli/version.go @@ -20,6 +20,7 @@ package cli import ( "fmt" "tmsu/common/terminal" + "tmsu/storage" "tmsu/version" ) @@ -33,7 +34,7 @@ var VersionCommand = Command{ Hidden: true, } -func versionExec(options Options, args []string) error { +func versionExec(store *storage.Storage, options Options, args []string) error { fmt.Println("TMSU", version.Version) fmt.Println() terminal.PrintWrapped(`Copyright © 2011-2014 Paul Ruane. diff --git a/src/tmsu/cli/vfs.go b/src/tmsu/cli/vfs.go index 5b43c119..78d3290c 100644 --- a/src/tmsu/cli/vfs.go +++ b/src/tmsu/cli/vfs.go @@ -15,18 +15,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +// +build !windows + package cli import ( "fmt" "strings" + "tmsu/storage" "tmsu/vfs" ) var VfsCommand = Command{ Name: "vfs", Synopsis: "Hosts the virtual filesystem", - Usages: []string{"tmsu vfs [OPTION]... FILE MOUNTPOINT"}, + Usages: []string{"tmsu vfs [OPTION]... MOUNTPOINT"}, Description: `This subcommand is the foreground process which hosts the virtual filesystem. It is run automatically when a virtual filesystem is mounted using the 'mount' subcommand and terminated when the virtual filesystem is unmounted. It is not normally necessary to issue this subcommand manually unless debugging the virtual filesystem. For debug output use the --verbose option.`, @@ -35,7 +38,7 @@ It is not normally necessary to issue this subcommand manually unless debugging Hidden: true, } -func vfsExec(options Options, args []string) error { +func vfsExec(store *storage.Storage, options Options, args []string) error { if len(args) == 0 { fmt.Errorf("mountpoint not specified") } @@ -45,12 +48,11 @@ func vfsExec(options Options, args []string) error { mountOptions = strings.Split(options.Get("--options").Argument, ",") } - databasePath := args[0] - mountPath := args[1] + mountPath := args[0] - vfs, err := vfs.MountVfs(databasePath, mountPath, mountOptions) + vfs, err := vfs.MountVfs(store, mountPath, mountOptions) if err != nil { - return fmt.Errorf("could not mount virtual filesystem for database '%v' at '%v': %v", databasePath, mountPath, err) + return fmt.Errorf("could not mount virtual filesystem at '%v': %v", mountPath, err) } defer vfs.Unmount() diff --git a/src/tmsu/common/terminal/terminal.go b/src/tmsu/common/terminal/terminal.go index b8788aff..a0593376 100644 --- a/src/tmsu/common/terminal/terminal.go +++ b/src/tmsu/common/terminal/terminal.go @@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +// +build !windows + package terminal import ( diff --git a/src/tmsu/vfs/fusevfs.go b/src/tmsu/vfs/fusevfs.go index 140d9761..49df7a9a 100644 --- a/src/tmsu/vfs/fusevfs.go +++ b/src/tmsu/vfs/fusevfs.go @@ -66,7 +66,7 @@ type FuseVfs struct { server *fuse.Server } -func MountVfs(databasePath string, mountPath string, options []string) (*FuseVfs, error) { +func MountVfs(store *storage.Storage, mountPath string, options []string) (*FuseVfs, error) { fuseVfs := FuseVfs{} pathFs := pathfs.NewPathNodeFs(&fuseVfs, nil) conn := nodefs.NewFileSystemConnector(pathFs.Root(), nil) @@ -77,11 +77,6 @@ func MountVfs(databasePath string, mountPath string, options []string) (*FuseVfs return nil, fmt.Errorf("could not mount virtual filesystem at '%v': %v", mountPath, err) } - store, err := storage.OpenAt(databasePath) - if err != nil { - return nil, fmt.Errorf("could not open database at '%v': %v", databasePath, err) - } - fuseVfs.store = store fuseVfs.mountPath = mountPath fuseVfs.server = server