Documentation ¶
Index ¶
- Constants
- Variables
- func DiffTrees(a, b *Tree, arootpath, brootpath string, options ...DiffTreesOption) error
- type Codec
- type DiffTreesOption
- type Node
- func (node *Node) Children() []*Node
- func (node *Node) Info() NodeInfo
- func (node *Node) IsDir() bool
- func (node *Node) IsRoot() bool
- func (node *Node) Path() string
- func (node *Node) ReadAt(p []byte, off int64) (int, error)
- func (node *Node) Ref() int
- func (node *Node) Rename(newName string) error
- func (node *Node) SetMode(mode uint32)
- func (node *Node) String() string
- func (node *Node) Touch(seconds uint32)
- func (node *Node) Truncate(requestedSize uint64) error
- func (node *Node) Unlinked() bool
- func (node *Node) Unref() int
- func (node *Node) WriteAt(p []byte, off int64) error
- type NodeInfo
- type Revision
- func (r *Revision) Key() storage.Pointer
- func (r *Revision) Parent(tagName string) (Tag, bool)
- func (r *Revision) RootIs(key storage.Pointer) bool
- func (r *Revision) RootKey() storage.Pointer
- func (r *Revision) ShortString() string
- func (r *Revision) String() string
- func (r *Revision) Time() time.Time
- type Store
- func (s *Store) History(maxRevisions int, head *Revision, tagName string) (rr []*Revision, err error)
- func (s *Store) LoadNode(dst *Node) error
- func (s *Store) LoadRevisionByKey(key storage.Pointer) (*Revision, error)
- func (s *Store) LocalBasePointer() (storage.Pointer, error)
- func (s *Store) LocalRoot() (*Node, error)
- func (s *Store) LocalRootKey() (storage.Pointer, error)
- func (s *Store) RemoteTag(tagName string) (tag Tag, err error)
- func (s *Store) RemoteTags(tagNames []string) (tags []Tag, err error)
- func (s *Store) SealNode(node *Node) error
- func (s *Store) SetLocalBasePointer(pointer storage.Pointer) error
- func (s *Store) SetRemoteTags(tagNames []string, pointer storage.Pointer) error
- func (s *Store) StoreNode(node *Node) error
- func (s *Store) StoreRevision(r *Revision) error
- type Tag
- type Tree
- func (tree *Tree) Add(node *Node, name string, perm uint32) (*Node, error)
- func (tree *Tree) Attach() *Node
- func (tree *Tree) Discard(node *Node)
- func (tree *Tree) DumpNodes(w io.Writer)
- func (tree *Tree) Flush() error
- func (tree *Tree) FlushIfNotDoneRecently() error
- func (tree *Tree) Graft(parent *Node, child *Node, childName string) error
- func (tree *Tree) Grow(parent *Node) error
- func (tree *Tree) Ignore(revision string, pathname string)
- func (tree *Tree) ListNodesInUse() (paths []string)
- func (tree *Tree) PullWorklog(cfg *config.C, baseTree *Tree, remoteTree *Tree) (output string, err error)
- func (tree *Tree) ReachableKeys(accumulator map[string]struct{}) (map[string]struct{}, error)
- func (tree *Tree) RemoveForMerge(node *Node) error
- func (tree *Tree) Rename(sourcepath, targetpath string) error
- func (tree *Tree) Root() (storage.Pointer, *Node)
- func (tree *Tree) Seal() error
- func (tree *Tree) SetRevision(r *Revision)
- func (tree *Tree) Trim()
- func (tree *Tree) Unlink(node *Node) error
- func (tree *Tree) Walk(sourceNode *Node, branchNames ...string) (visitedNodes []*Node, err error)
- type TreeOption
Constants ¶
const ( DMDIR = 0x80000000 DMAPPEND = 0x40000000 DMEXCL = 0x20000000 DMTMP = 0x04000000 )
const SnapshotFrequency = 3 * time.Minute
Variables ¶
var ( ErrExist = fmt.Errorf("exists") ErrNotEmpty = fmt.Errorf("not empty") ErrNotExist = fmt.Errorf("does not exist") ErrPermission = fmt.Errorf("permission denied") ErrReadOnly = fmt.Errorf("read-only") )
var ErrInUse = errors.New("in use")
var FixBlockSize = false
FixBlockSize guards the block size fix code in the write path. Doing it always would break all tests. So I'm placing this terrible flag here and set it in musclefs.
var RemoteRootKeyPrefix = "remote.root."
Functions ¶
Types ¶
type Codec ¶
type Codec interface {
// contains filtered or unexported methods
}
Codec defines how we serialize and deserialize our types.
type DiffTreesOption ¶
type DiffTreesOption func(*diffTreesOptions)
DiffTreesOption follows the functional options pattern to pass options to DiffTrees.
func DiffTreesInitialPath ¶
func DiffTreesInitialPath(pathname string) DiffTreesOption
func DiffTreesNamesOnly ¶
func DiffTreesNamesOnly(value bool) DiffTreesOption
func DiffTreesOutput ¶
func DiffTreesOutput(w io.Writer) DiffTreesOption
func DiffTreesVerbose ¶
func DiffTreesVerbose(value bool) DiffTreesOption
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
Node describes a node in the filesystem tree.
func (*Node) Path ¶
Path returns the full path to the node, e.g., "/src/muscle/tree/node.go". A non-loaded node is represented by an asterisk; as a consequence, a path can take the form "/src/muscle/tree/*".
func (*Node) Ref ¶
Ref increments the node's ref count, and that of all its ancestors. It also sets the node's access time. Since we can only stat() after walk(), this means we're updating the atime also to answer a stat syscall. That's not correct. But the use case for atime is, as I said, to track when last used in musclefs. It should perhaps be called last ref'd.
func (*Node) Rename ¶
Rename changes the node's name. If the parent already contains a file/empty directory with the new name, that file/directory is unlinked first. Stat(5) says that renaming should fail in that case, but conforming to the manual page makes it impossible to use git (which renames 'index.lock' to an already existing 'index', for example) under both 9pfuse and v9fs.
func (*Node) String ¶
String returns the path to the node and its hash pointer, plus a "-dirty" suffix if the node hasn't been flushed to disk.
func (*Node) Touch ¶
Touch updates the modification timestamp of the node and marks the node dirty, so that it is later flushed to disk.
type Revision ¶
type Revision struct {
// contains filtered or unexported fields
}
Revision is the analogue of a git commit.
func NewRevision ¶
func (*Revision) ShortString ¶
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is a high-level entity that takes care of loading and storing objects (nodes, revisions) from/to a store. Such operations require encryption/decryption, encoding/decoding, actual store put/get. It is built on top of the more basic functionality in muscle/storage.
func (*Store) LoadNode ¶
LoadNode assumes that dst.key is the destination node's key, and the parent pointer is also correct. Loading will overwrite any other data.
func (*Store) LoadRevisionByKey ¶
func (*Store) LocalBasePointer ¶
LocalBasePointer reads the file $HOME/lib/muscle/base, expecting to find a hex-encoded storage.Pointer that points to a revision.
func (*Store) SetLocalBasePointer ¶
SetLocalBasePointer atomically updates $HOME/lib/muscle/base, and adds an entry to $HOME/lib/muscle/base.history for the previous base pointer.
func (*Store) SetRemoteTags ¶
pointer must point to a revision.
func (*Store) StoreRevision ¶
type Tree ¶
type Tree struct {
// contains filtered or unexported fields
}
func NewTree ¶
func NewTree(store *Store, opts ...TreeOption) (*Tree, error)
NewTree constructs a new tree object using the given store, and according to the given options (see the TreeOption section).
func (*Tree) FlushIfNotDoneRecently ¶
FlushIfNotDoneRecently dumps the in-memory changes to the staging area if not done recently (according to the snapshot frequency constant).
func (*Tree) Graft ¶
Graft is a low-level operation. The child may come from a historical tree. The parent from the local tree. We will make the child a child of the parent.
func (*Tree) Grow ¶
Grow expands the tree at node (if necessary), by loading child nodes (where necessary). This method protects against the case where the node has more than one child with any given name, by adding a random UUID extension to the duplicates. (Unfortunately this type of inconsistency has happened during development of the merge operation.) This method will also add a random UUID extension to every node that is not found in the storage layer. Such nodes will then represent empty files.
func (*Tree) Ignore ¶
Ignore marks the given pathname within the given revision as ignored for the purpose of pull (merge) operations. In other words, a conflict for pathname when merging the revision will result in the local version to be kept.
func (*Tree) ListNodesInUse ¶
func (*Tree) PullWorklog ¶
func (tree *Tree) PullWorklog(cfg *config.C, baseTree *Tree, remoteTree *Tree) (output string, err error)
Returns proposed commands to execute via the ctl file. If empty, and no error, it means there's nothing to pull.
func (*Tree) ReachableKeys ¶
func (*Tree) RemoveForMerge ¶
RemoveForMerge unlinks the node from its parent even if it is a non-empty directory. This is required when running the 3-way merge algorithm. Also, if we don't find the node within the parent, we return an error, as that is an inconsistency. If we have to remove more than one node (the parent has more than one child matching the name), we do so, and log an error about the inconsistency. We don't return an error as we don't want to prevent the merge algorithm from resolving the inconsistency somehow. It is an error trying to remove the root (it has no parent). The code will panic if the parent of the node is nil. That would be a programming error and I don't want to defend against that.
type TreeOption ¶
TreeOption values influence the behavior of NewTree.
func WithMutable ¶
func WithMutable() TreeOption
The WithMutable option specifies that the tree to be constructed should allow mutating operations, like writing data, changing file names, and adding new nodes.
func WithRevision ¶
func WithRevision(p storage.Pointer) TreeOption
WithRevision specifies that the tree's root node should be the revision's root node.
func WithRoot ¶
func WithRoot(p storage.Pointer) TreeOption
WithRoot specifies the tree's root node.
func WithRootName ¶
func WithRootName(name string) TreeOption