func (vfs FuseVfs) openTaggedEntryDir(path []string) ([]fuse.DirEntry, fuse.Status) { log.Infof("BEGIN openTaggedEntryDir(%v)", path) defer log.Infof("END openTaggedEntryDir(%v)", path) tagIds, err := vfs.tagNamesToIds(path) if err != nil { log.Fatalf("Could not lookup tag IDs: %v.", err) } if tagIds == nil { return nil, fuse.ENOENT } furtherTagIds, err := vfs.store.TagsForTags(tagIds) if err != nil { log.Fatalf("Could not retrieve tags for tags: %v", err) } files, err := vfs.store.FilesWithTags(tagIds, []uint{}) if err != nil { log.Fatalf("Could not retrieve tagged files: %v", err) } entries := make([]fuse.DirEntry, 0, len(files)+len(furtherTagIds)) for _, tag := range furtherTagIds { entries = append(entries, fuse.DirEntry{Name: tag.Name, Mode: fuse.S_IFDIR | 0755}) } for _, file := range files { linkName := vfs.getLinkName(file) entries = append(entries, fuse.DirEntry{Name: linkName, Mode: fuse.S_IFLNK}) } return entries, fuse.OK }
func (vfs FuseVfs) getTaggedEntryAttr(path []string) (*fuse.Attr, fuse.Status) { log.Infof("BEGIN getTaggedEntryAttr(%v)", path) defer log.Infof("END getTaggedEntryAttr(%v)", path) pathLength := len(path) name := path[pathLength-1] fileId, err := vfs.parseFileId(name) if err != nil { return nil, fuse.ENOENT } if fileId == 0 { // tag directory tagIds, err := vfs.tagNamesToIds(path) if err != nil { log.Fatalf("Could not lookup tag IDs: %v.", err) } if tagIds == nil { return nil, fuse.ENOENT } //TODO slow // fileCount, err := vfs.store.FileCountWithTags(tagIds) // if err != nil { // log.Fatalf("Could not retrieve count of files with tags: %v. (%v)", path, err) // } fileCount := 0 now := time.Now() return &fuse.Attr{Mode: fuse.S_IFDIR | 0755, Nlink: 2, Size: uint64(fileCount), Mtime: uint64(now.Unix()), Mtimensec: uint32(now.Nanosecond())}, fuse.OK } file, err := vfs.store.File(fileId) if err != nil { log.Fatalf("Could not retrieve file #%v: %v", fileId, err) } if file == nil { return &fuse.Attr{Mode: fuse.S_IFREG}, fuse.ENOENT } fileInfo, err := os.Stat(file.Path()) var size int64 var modTime time.Time if err == nil { size = fileInfo.Size() modTime = fileInfo.ModTime() } else { size = 0 modTime = time.Time{} } return &fuse.Attr{Mode: fuse.S_IFLNK | 0755, Size: uint64(size), Mtime: uint64(modTime.Unix()), Mtimensec: uint32(modTime.Nanosecond())}, fuse.OK }
func (vfs FuseVfs) Unlink(name string, context *fuse.Context) fuse.Status { log.Infof("BEGIN Unlink(%v)", name) defer log.Infof("END Unlink(%v)", name) fileId, err := vfs.parseFileId(name) if err != nil { log.Fatal("Could not unlink: ", err) } if fileId == 0 { // cannot unlink tag directories return fuse.EPERM } path := vfs.splitPath(name) tagNames := path[1 : len(path)-1] for _, tagName := range tagNames { tag, err := vfs.store.Db.TagByName(tagName) if err != nil { log.Fatal(err) } if tag == nil { log.Fatalf("Could not retrieve tag '%v'.", tagName) } err = vfs.store.RemoveFileTag(fileId, tag.Id) if err != nil { log.Fatal(err) } } return fuse.OK }
func (vfs FuseVfs) readTaggedEntryLink(path []string) (string, fuse.Status) { log.Infof("BEGIN readTaggedEntryLink(%v)", path) defer log.Infof("END readTaggedEntryLink(%v)", path) name := path[len(path)-1] fileId, err := vfs.parseFileId(name) if err != nil { log.Fatalf("Could not parse file identifier: %v", err) } if fileId == 0 { return "", fuse.ENOENT } file, err := vfs.store.File(fileId) if err != nil { log.Fatalf("Could not find file %v in database.", fileId) } return file.Path(), fuse.OK }
func (vfs FuseVfs) getTagsAttr() (*fuse.Attr, fuse.Status) { log.Infof("BEGIN getTagsAttr") defer log.Infof("END getTagsAttr") tagCount, err := vfs.store.Db.TagCount() if err != nil { log.Fatalf("Could not get tag count: %v", err) } now := time.Now() return &fuse.Attr{Mode: fuse.S_IFDIR | 0755, Nlink: 2, Size: uint64(tagCount), Mtime: uint64(now.Unix()), Mtimensec: uint32(now.Nanosecond())}, fuse.OK }
func (command FilesCommand) listFilesForTags(args []string) error { if len(args) == 0 { return fmt.Errorf("at least one tag must be specified. Use --all to show all files.") } store, err := storage.Open() if err != nil { return fmt.Errorf("could not open storage: %v", err) } defer store.Close() includeTagIds := make([]uint, 0) excludeTagIds := make([]uint, 0) for _, arg := range args { var tagName string var include bool if arg[0] == '-' { tagName = arg[1:] include = false } else { tagName = arg include = true } tag, err := store.TagByName(tagName) if err != nil { return fmt.Errorf("could not retrieve tag '%v': %v", tagName, err) } if tag == nil { log.Fatalf("no such tag '%v'.", tagName) } if include { includeTagIds = append(includeTagIds, tag.Id) } else { excludeTagIds = append(excludeTagIds, tag.Id) } } if command.verbose { log.Info("retrieving set of tagged files from the database.") } files, err := store.FilesWithTags(includeTagIds, excludeTagIds) if err != nil { return fmt.Errorf("could not retrieve files with tags %v and without tags %v: %v", includeTagIds, excludeTagIds, err) } return command.listFiles(files) }
func main() { helpCommand := &commands.HelpCommand{} commands := map[cli.CommandName]cli.Command{ "copy": commands.CopyCommand{}, "delete": commands.DeleteCommand{}, "dupes": commands.DupesCommand{}, "files": commands.FilesCommand{}, "help": helpCommand, "imply": commands.ImplyCommand{}, "merge": commands.MergeCommand{}, "mount": commands.MountCommand{}, "rename": commands.RenameCommand{}, "repair": commands.RepairCommand{}, "stats": commands.StatsCommand{}, "status": commands.StatusCommand{}, "tag": commands.TagCommand{}, "tags": commands.TagsCommand{}, "unmount": commands.UnmountCommand{}, "untag": commands.UntagCommand{}, "version": commands.VersionCommand{}, "vfs": commands.VfsCommand{}, } helpCommand.Commands = commands globalOptions := cli.Options{cli.Option{"--verbose", "-v", "show verbose messages", false, ""}, cli.Option{"--help", "-h", "show help and exit", false, ""}, cli.Option{"--version", "-V", "show version information and exit", false, ""}} parser := cli.NewParser(globalOptions, commands) commandName, options, arguments, err := parser.Parse(os.Args[1:]) if err != nil { log.Fatal(err) } if commandName == "" { commandName = "help" } command := commands[commandName] if command == nil { log.Fatalf("Invalid command '%v'.", commandName) } err = command.Exec(options, arguments) if err != nil { log.Fatal(err.Error()) } }
func (vfs FuseVfs) tagDirectories() ([]fuse.DirEntry, fuse.Status) { log.Infof("BEGIN tagDirectories") defer log.Infof("END tagDirectories") tags, err := vfs.store.Db.Tags() if err != nil { log.Fatalf("Could not retrieve tags: %v", err) } entries := make([]fuse.DirEntry, len(tags)) for index, tag := range tags { entries[index] = fuse.DirEntry{Name: tag.Name, Mode: fuse.S_IFDIR} } return entries, fuse.OK }