// vfs.go package models import ( "database/sql" "errors" "path" "time" _ "github.com/mattn/go-sqlite3" ) type Vfs struct { DB *sql.DB } type VfsNodeType int const ( VfsNodeTypeFile VfsNodeType = iota VfsNodeTypeService VfsNodeTypeDirectory VfsNodeTypeSymlink ) type VfsNode struct { ID uint64 Name string ParentID uint64 Type VfsNodeType CreatedAt time.Time UpdatedAt time.Time } type VfsDirEntry struct { ID uint64 Name string Type VfsNodeType } // NewVfs 创建新的 VFS 实例 func NewVfs(dbPath string) (*Vfs, error) { db, err := sql.Open("sqlite3", dbPath) if err != nil { return nil, err } // 创建表 _, err = db.Exec(` CREATE TABLE IF NOT EXISTS vfs_nodes ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, parent_id INTEGER, type INTEGER NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(parent_id, name) )`) if err != nil { return nil, err } return &Vfs{DB: db}, nil } // GetChildrenID 获取目录下所有子项的 ID func (v *Vfs) GetChildren(parentID uint64) ([]VfsDirEntry, error) { rows, err := v.DB.Query("SELECT id, name, type FROM vfs_nodes WHERE parent_id = ?", parentID) if err != nil { return nil, err } defer rows.Close() var dirEntrys []VfsDirEntry for rows.Next() { var entry VfsDirEntry if err := rows.Scan(&entry.ID, &entry.Name, &entry.Type); err != nil { return nil, err } dirEntrys = append(dirEntrys, entry) } return dirEntrys, nil } // GetParentID 根据父路径查找父节点 ID // parentPath 应该是 ParsePathComponents 的第一个返回值 func (v *Vfs) GetParentID(parentPath string) (uint64, error) { // 根目录特殊处理 if parentPath == "/" || parentPath == "" { return 0, nil } // 递归查找父路径ID // 先解析父路径的父路径和节点名 grandParentPath, parentName, _, err := ParsePathComponents(parentPath) if err != nil { return 0, err } // 递归获取祖父节点ID grandParentID, err := v.GetParentID(grandParentPath) if err != nil { return 0, err } // 在祖父节点下查找父节点 var parentID uint64 err = v.DB.QueryRow("SELECT id FROM vfs_nodes WHERE parent_id = ? AND name = ?", grandParentID, parentName).Scan(&parentID) if err != nil { if err == sql.ErrNoRows { return 0, errors.New("parent path not found") } return 0, err } return parentID, nil } // GetNodeByPath 根据完整路径查找节点 func (v *Vfs) GetNodeByPath(fullPath string) (*VfsNode, error) { // 根目录特殊处理 if path.Clean(fullPath) == "/" { return &VfsNode{ ID: 0, Name: "/", ParentID: 0, Type: VfsNodeTypeDirectory, CreatedAt: time.Now(), UpdatedAt: time.Now(), }, nil } // 使用 ParsePathComponents 解析路径 parentPath, nodeName, nodeType, err := ParsePathComponents(fullPath) if err != nil { return nil, err } // 获取父节点ID parentID, err := v.GetParentID(parentPath) if err != nil { return nil, err } // 根据 parentID, nodeName, nodeType 查找或创建节点 node, err := v.GetNodeByParentIDAndName(parentID, nodeName) if err != nil { // 如果节点不存在,可以选择创建它或者返回错误 // 这里根据你的需求决定是返回错误还是创建节点 return nil, err } if node.Type != nodeType { return nil, errors.New("node type mismatch") } return node, nil } // GetNodeByParentIDAndName 根据父ID和名称查找节点 func (v *Vfs) GetNodeByParentIDAndName(parentID uint64, name string) (*VfsNode, error) { node := &VfsNode{} err := v.DB.QueryRow(` SELECT id, name, parent_id, type, created_at, updated_at FROM vfs_nodes WHERE parent_id = ? AND name = ?`, parentID, name).Scan( &node.ID, &node.Name, &node.ParentID, &node.Type, &node.CreatedAt, &node.UpdatedAt) if err != nil { if err == sql.ErrNoRows { return nil, errors.New("node not found") } return nil, err } return node, nil } // CreateNodeByComponents 根据路径组件创建节点 func (v *Vfs) CreateNodeByComponents(parentPath, nodeName string, nodeType VfsNodeType) (*VfsNode, error) { // 获取父节点ID parentID, err := v.GetParentID(parentPath) if err != nil { return nil, err } // 创建新节点 node := &VfsNode{ Name: nodeName, ParentID: parentID, Type: nodeType, CreatedAt: time.Now(), UpdatedAt: time.Now(), } // 保存到数据库 result, err := v.DB.Exec(` INSERT INTO vfs_nodes (name, parent_id, type, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`, node.Name, node.ParentID, node.Type, node.CreatedAt, node.UpdatedAt) if err != nil { return nil, err } // 获取插入的ID id, err := result.LastInsertId() if err != nil { return nil, err } node.ID = uint64(id) return node, nil } func ParsePathComponents(pathStr string) (parentPath, nodeName string, nodeType VfsNodeType, err error) { abspath := path.Clean(pathStr) if !path.IsAbs(abspath) { return "", "", 0, errors.New("path must be absolute") } // 特殊处理根路径 if abspath == "/" { return "", "", VfsNodeTypeDirectory, nil } // 判断是文件还是目录 nodeType = VfsNodeTypeFile // 如果原始路径以 / 结尾,则为目录 if len(pathStr) > 1 && pathStr[len(pathStr)-1] == '/' { nodeType = VfsNodeTypeDirectory } if nodeType == VfsNodeTypeFile && path.Ext(pathStr) == ".api" { nodeType = VfsNodeTypeService } // 分割路径 parentPath, nodeName = path.Split(abspath) // 清理父路径 if parentPath != "/" && parentPath != "" { parentPath = path.Clean(parentPath) } // 处理特殊情况 if parentPath == "." { parentPath = "/" } return parentPath, nodeName, nodeType, nil } func (v *Vfs) CreateVFSNode(p *VfsNode) error { _, err := v.DB.Exec(` INSERT INTO vfs_nodes (name, parent_id, type, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`, p.Name, p.ParentID, p.Type, time.Now(), time.Now()) return err } func (v *Vfs) DeleteVFSNode(p *VfsNode) error { _, err := v.DB.Exec("DELETE FROM vfs_nodes WHERE id = ?", p.ID) return err } func (v *Vfs) GetVFSNode(p *VfsNode) *VfsNode { node := &VfsNode{} err := v.DB.QueryRow(` SELECT id, name, parent_id, type, created_at, updated_at FROM vfs_nodes WHERE id = ?`, p.ID).Scan( &node.ID, &node.Name, &node.ParentID, &node.Type, &node.CreatedAt, &node.UpdatedAt) if err != nil { return nil } return node } func (v *Vfs) UpdateVFSNode(p *VfsNode) error { _, err := v.DB.Exec(` UPDATE vfs_nodes SET name = ?, parent_id = ?, type = ?, updated_at = ? WHERE id = ?`, p.Name, p.ParentID, p.Type, time.Now(), p.ID) return err }