コード例 #1
0
ファイル: fusevfs.go プロジェクト: kelvinhammond/tmsu
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
}
コード例 #2
0
ファイル: fusevfs.go プロジェクト: kelvinhammond/tmsu
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
}
コード例 #3
0
ファイル: fusevfs.go プロジェクト: kelvinhammond/tmsu
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
}
コード例 #4
0
ファイル: fusevfs.go プロジェクト: kelvinhammond/tmsu
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
}
コード例 #5
0
ファイル: fusevfs.go プロジェクト: kelvinhammond/tmsu
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
}
コード例 #6
0
ファイル: files.go プロジェクト: kelvinhammond/tmsu
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)
}
コード例 #7
0
ファイル: main.go プロジェクト: kelvinhammond/tmsu
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())
	}
}
コード例 #8
0
ファイル: fusevfs.go プロジェクト: kelvinhammond/tmsu
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
}