gf/g/os/gspath/gspath.go
2018-09-25 17:25:38 +08:00

115 lines
3.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
// 搜索目录管理.
// 可以添加搜索目录,按照添加的优先级进行文件检索,并在内部进行高效缓存处理。
package gspath
import (
"sync"
"errors"
"strings"
"gitee.com/johng/gf/g/os/gfile"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/os/gfsnotify"
"gitee.com/johng/gf/g/os/glog"
)
// 文件目录搜索管理对象
type SPath struct {
mu sync.RWMutex
paths []string // 搜索路径,按照优先级进行排序
cache *gmap.StringStringMap // 搜索结果缓存map
}
func New () *SPath {
return &SPath{
paths : make([]string, 0),
cache : gmap.NewStringStringMap(),
}
}
// 设置搜索路径,只保留当前设置项,其他搜索路径被清空
func (sp *SPath) Set(path string) error {
r := gfile.RealPath(path)
if r == "" {
r = sp.Search(path)
if r == "" {
r = gfile.RealPath(gfile.Pwd() + gfile.Separator + path)
}
}
if r != "" && gfile.IsDir(r) {
r = strings.TrimRight(r, gfile.Separator)
sp.mu.Lock()
sp.paths = []string{r}
sp.mu.Unlock()
sp.cache.Clear()
glog.Debug("gspath.SetPath: ", r)
return nil
}
glog.Debug("gspath.SetPath failed: ", path)
return errors.New("invalid path:" + path)
}
// 添加搜索路径
func (sp *SPath) Add(path string) error {
r := gfile.RealPath(path)
if r == "" {
r = sp.Search(path)
if r == "" {
r = gfile.RealPath(gfile.Pwd() + gfile.Separator + path)
}
}
if r != "" && gfile.IsDir(r) {
r = strings.TrimRight(r, gfile.Separator)
sp.mu.Lock()
sp.paths = append(sp.paths, r)
sp.mu.Unlock()
glog.Debug("gspath.Add: ", r)
return nil
}
glog.Debug("gspath.Add failed: ", path)
return errors.New("invalid path:" + path)
}
// 按照优先级搜索文件,返回搜索到的文件绝对路径,找不到该文件时,返回空字符串
// 给定的name只是相对文件路径或者只是一个文件名
func (sp *SPath) Search(name string) string {
path := sp.cache.Get(name)
if path == "" {
sp.mu.RLock()
for _, v := range sp.paths {
path = gfile.RealPath(v + gfile.Separator + name)
if path != "" && gfile.Exists(path) {
break
}
}
sp.mu.RUnlock()
if path != "" {
sp.cache.Set(name, path)
sp.addMonitor(name, path)
}
}
return path
}
// 当前的搜索路径数量
func (sp *SPath) Size() int {
sp.mu.RLock()
length := len(sp.paths)
sp.mu.RUnlock()
return length
}
// 添加文件监控,当文件删除时,同时也删除搜索结果缓存
func (sp *SPath) addMonitor(name, path string) {
gfsnotify.Add(path, func(event *gfsnotify.Event) {
glog.Debug("gspath.monitor:", event)
if event.IsRemove() {
sp.cache.Remove(name)
}
})
}