Пример #1
0
func (vfs FuseVfs) openQueryEntryDir(tx *storage.Tx, path []string) ([]fuse.DirEntry, fuse.Status) {
	log.Infof(2, "BEGIN openQueryEntryDir(%v)", path)
	defer log.Infof(2, "END openQueryEntryDir(%v)", path)

	queryText := path[0]

	expression, err := query.Parse(queryText)
	if err != nil {
		log.Fatalf("could not parse query: %v", err)
	}

	tagNames, err := query.TagNames(expression)
	if err != nil {
		log.Fatalf("could not identify tag names: %v", err)
	}

	tags, err := vfs.store.TagsByNames(tx, tagNames)
	for _, tagName := range tagNames {
		if !containsTag(tags, tagName) {
			return nil, fuse.ENOENT
		}
	}

	files, err := vfs.store.FilesForQuery(tx, expression, "", false, false, "name")
	if err != nil {
		log.Fatalf("could not query files: %v", err)
	}

	entries := make([]fuse.DirEntry, 0, len(files))
	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
func (vfs FuseVfs) getQueryEntryAttr(path []string) (*fuse.Attr, fuse.Status) {
	log.Infof(2, "BEGIN getQueryEntryAttr(%v)", path)
	defer log.Infof(2, "END getQueryEntryAttr(%v)", path)

	if len(path) == 1 && path[0] == helpFilename {
		now := time.Now()
		return &fuse.Attr{Mode: fuse.S_IFREG | 0444, Nlink: 1, Size: uint64(len(queryDirHelp)), Mtime: uint64(now.Unix()), Mtimensec: uint32(now.Nanosecond())}, fuse.OK
	}

	name := path[len(path)-1]

	if len(path) > 1 {
		fileId := vfs.parseFileId(name)
		if fileId != 0 {
			return vfs.getFileEntryAttr(fileId)
		}

		return nil, fuse.ENOENT
	}

	queryText := path[0]

	if queryText[len(queryText)-1] == ' ' {
		// prevent multiple entries for same query when typing path in a GUI
		return nil, fuse.ENOENT
	}

	expression, err := query.Parse(queryText)
	if err != nil {
		return nil, fuse.ENOENT
	}

	tx, err := vfs.store.Begin()
	if err != nil {
		log.Fatalf("could not begin transaction: %v", err)
	}
	defer tx.Commit()

	tagNames, err := query.TagNames(expression)
	if err != nil {
		log.Fatalf("could not identify tag names: %v", err)
	}

	tags, err := vfs.store.TagsByNames(tx, tagNames)
	for _, tagName := range tagNames {
		if !containsTag(tags, tagName) {
			return nil, fuse.ENOENT
		}
	}

	q, err := vfs.store.Query(tx, queryText)
	if err != nil {
		log.Fatalf("could not retrieve query '%v': %v", queryText, err)
	}
	if q == nil {
		_, err = vfs.store.AddQuery(tx, queryText)
		if err != nil {
			log.Fatalf("could not add query '%v': %v", queryText, err)
		}
	}

	now := time.Now()
	return &fuse.Attr{Mode: fuse.S_IFDIR | 0755, Nlink: 2, Size: uint64(0), Mtime: uint64(now.Unix()), Mtimensec: uint32(now.Nanosecond())}, fuse.OK
}
Пример #3
0
func listFilesForQuery(store *storage.Storage, tx *storage.Tx, queryText, path string, dirOnly, fileOnly, print0, showCount, explicitOnly, ignoreCase bool, sort string) (error, warnings) {
	log.Info(2, "parsing query")

	expression, err := query.Parse(queryText)
	if err != nil {
		return fmt.Errorf("could not parse query: %v", err), nil
	}

	log.Info(2, "checking tag names")

	warnings := make(warnings, 0, 10)

	tagNames, err := query.TagNames(expression)
	if err != nil {
		return fmt.Errorf("could not identify tag names: %v", err), nil
	}

	tags, err := store.TagsByCasedNames(tx, tagNames, ignoreCase)
	for _, tagName := range tagNames {
		if err := entities.ValidateTagName(tagName); err != nil {
			warnings = append(warnings, err.Error())
			continue
		}

		if !tags.ContainsCasedName(tagName, ignoreCase) {
			warnings = append(warnings, fmt.Sprintf("no such tag '%v'", tagName))
			continue
		}
	}

	valueNames, err := query.ExactValueNames(expression)
	if err != nil {
		return fmt.Errorf("could not identify value names: %v", err), nil
	}

	values, err := store.ValuesByCasedNames(tx, valueNames, ignoreCase)
	for _, valueName := range valueNames {
		if err := entities.ValidateValueName(valueName); err != nil {
			warnings = append(warnings, err.Error())
			continue
		}

		if !values.ContainsCasedName(valueName, ignoreCase) {
			warnings = append(warnings, fmt.Sprintf("no such value '%v'", valueName))
			continue
		}
	}

	log.Info(2, "querying database")

	files, err := store.FilesForQuery(tx, expression, path, explicitOnly, ignoreCase, sort)
	if err != nil {
		if strings.Index(err.Error(), "parser stack overflow") > -1 {
			return fmt.Errorf("the query is too complex (see the troubleshooting wiki for how to increase the stack size)"), warnings
		} else {
			return fmt.Errorf("could not query files: %v", err), warnings
		}
	}

	if err = listFiles(tx, files, dirOnly, fileOnly, print0, showCount); err != nil {
		return err, warnings
	}

	return nil, warnings
}