added ability to mount special object 'all' that exposes the whole set of snapshots grouped by user@host, path and time

This commit is contained in:
Jarek Kowalski
2017-08-19 19:49:18 -07:00
parent 484db94e23
commit ff487d1e85
5 changed files with 196 additions and 4 deletions

View File

@@ -43,12 +43,22 @@ func runMountCommand(context *kingpin.ParseContext) error {
fuse.VolumeName("Kopia"),
)
oid, err := parseObjectID(*mountObjectID, rep)
if err != nil {
return err
}
entry := repofs.Directory(rep, oid)
var entry fs.Directory
if *mountObjectID == "all" {
entry = repofs.AllSources(rep)
} else {
oid, err := parseObjectID(*mountObjectID, rep)
if err != nil {
return err
}
entry = repofs.Directory(rep, oid)
}
if *mountTraceFS {
entry = loggingfs.Wrap(entry).(fs.Directory)
}

59
fs/repofs/all_sources.go Normal file
View File

@@ -0,0 +1,59 @@
package repofs
import (
"fmt"
"time"
"github.com/kopia/kopia/fs"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/snapshot"
)
type repositoryAllSources struct {
repo *repo.Repository
snapshotManager *snapshot.Manager
}
func (s *repositoryAllSources) Parent() fs.Directory {
return nil
}
func (s *repositoryAllSources) Metadata() *fs.EntryMetadata {
return &fs.EntryMetadata{
Name: "/",
Permissions: 0555,
Type: fs.EntryTypeDirectory,
ModTime: time.Now(),
}
}
func (s *repositoryAllSources) Readdir() (fs.Entries, error) {
srcs, err := s.snapshotManager.ListSources()
if err != nil {
return nil, err
}
users := map[string]bool{}
for _, src := range srcs {
users[fmt.Sprintf("%v@%v", src.UserName, src.Host)] = true
}
var result fs.Entries
for u := range users {
result = append(result, &sourceDirectories{
parent: s,
repo: s.repo,
snapshotManager: s.snapshotManager,
userHost: u,
})
}
return result, nil
}
// AllSources returns fs.Directory that contains the list of all snapshot sources found in the repository.
func AllSources(r *repo.Repository) fs.Directory {
sm := snapshot.NewManager(r)
return &repositoryAllSources{repo: r, snapshotManager: sm}
}

View File

@@ -0,0 +1,48 @@
package repofs
import (
"time"
"github.com/kopia/kopia/fs"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/snapshot"
)
type sourceDirectories struct {
parent fs.Directory
repo *repo.Repository
snapshotManager *snapshot.Manager
userHost string
}
func (s *sourceDirectories) Parent() fs.Directory {
return s.parent
}
func (s *sourceDirectories) Metadata() *fs.EntryMetadata {
return &fs.EntryMetadata{
Name: s.userHost,
Permissions: 0555,
Type: fs.EntryTypeDirectory,
ModTime: time.Now(),
}
}
func (s *sourceDirectories) Readdir() (fs.Entries, error) {
sources, err := s.snapshotManager.ListSources()
if err != nil {
return nil, err
}
var result fs.Entries
for _, src := range sources {
if src.UserName+"@"+src.Host != s.userHost {
continue
}
result = append(result, &sourceSnapshots{s, s.repo, s.snapshotManager, src})
}
return result, nil
}

View File

@@ -0,0 +1,64 @@
package repofs
import (
"fmt"
"strings"
"github.com/kopia/kopia/fs"
"github.com/kopia/kopia/internal/dir"
"github.com/kopia/kopia/repo"
"github.com/kopia/kopia/snapshot"
)
type sourceSnapshots struct {
parent fs.Directory
repo *repo.Repository
snapshotManager *snapshot.Manager
src *snapshot.SourceInfo
}
func (s *sourceSnapshots) Parent() fs.Directory {
return s.parent
}
func (s *sourceSnapshots) Metadata() *fs.EntryMetadata {
return &fs.EntryMetadata{
Name: fmt.Sprintf("%v", safeName(s.src.Path)),
Permissions: 0555,
Type: fs.EntryTypeDirectory,
}
}
func safeName(path string) string {
path = strings.TrimLeft(path, "/")
return strings.Replace(path, "/", "_", -1)
}
func (s *sourceSnapshots) Readdir() (fs.Entries, error) {
manifests, err := s.snapshotManager.ListSnapshots(s.src, -1)
if err != nil {
return nil, err
}
var result fs.Entries
for _, m := range manifests {
name := m.StartTime.Format("20060102-150405")
if m.IncompleteReason != "" {
name += fmt.Sprintf(" (%v)", m.IncompleteReason)
}
e := newRepoEntry(s.repo, &dir.Entry{
EntryMetadata: fs.EntryMetadata{
Name: name,
Permissions: 0555,
Type: fs.EntryTypeDirectory,
ModTime: m.StartTime,
},
ObjectID: m.RootObjectID,
}, s)
result = append(result, e)
}
return result, nil
}

View File

@@ -9,6 +9,7 @@
"fmt"
"io/ioutil"
"os"
"sort"
"github.com/kopia/kopia/fs"
@@ -72,11 +73,21 @@ func (dir *fuseDirectoryNode) Lookup(ctx context.Context, fileName string) (fuse
}
return newFuseNode(e, dir.cache)
}
func (dir *fuseDirectoryNode) readPossiblyCachedReaddir() (fs.Entries, error) {
return dir.cache.getEntries(dir.cacheID, func() (fs.Entries, error) { return dir.directory().Readdir() })
return dir.cache.getEntries(dir.cacheID, func() (fs.Entries, error) {
entries, err := dir.directory().Readdir()
if err != nil {
return nil, err
}
sort.Slice(entries, func(i, j int) bool {
return entries[i].Metadata().Name < entries[j].Metadata().Name
})
return entries, nil
})
}
func (dir *fuseDirectoryNode) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {