List snapshots, accept snapshot id prefix

Example:

    $ ./khepri snapshots
    ID        Date                 Source      Directory
    --------------------------------------------------------------------------------
    fa31d65b  2014-11-24 19:45:11  kasimir     /home/user/testdata
    20bdc140  2014-11-24 20:00:47  kasimir     /home/user/testdata
    326cb59d  2014-11-24 20:01:40  kasimir     /home/user/testdata
    20ff988b  2014-11-24 20:35:35  kasimir     /home/user
This commit is contained in:
Alexander Neumann
2014-11-24 21:12:32 +01:00
parent 26cd6c5372
commit 2c5d07a571
6 changed files with 137 additions and 19 deletions
+58
View File
@@ -4,12 +4,19 @@ import (
"bytes"
"compress/zlib"
"crypto/sha256"
"encoding/hex"
"errors"
"io/ioutil"
"sync"
)
var idPool = sync.Pool{New: func() interface{} { return ID(make([]byte, IDSize)) }}
var (
ErrNoIDPrefixFound = errors.New("no ID found")
ErrMultipleIDMatches = errors.New("multiple IDs with prefix found")
)
// Each lists all entries of type t in the backend and calls function f() with
// the id and data.
func Each(be Server, t Type, f func(id ID, data []byte, err error)) error {
@@ -85,3 +92,54 @@ func Hash(data []byte) ID {
copy(id, h[:])
return id
}
// Find loads the list of all blobs of type t and searches for IDs which start
// with prefix. If none is found, nil and ErrNoIDPrefixFound is returned. If
// more than one is found, nil and ErrMultipleIDMatches is returned.
func Find(be Server, t Type, prefix string) (ID, error) {
p, err := hex.DecodeString(prefix)
if err != nil {
return nil, err
}
list, err := be.List(t)
if err != nil {
return nil, err
}
match := ID(nil)
// TODO: optimize by sorting list etc.
for _, id := range list {
if bytes.Equal(p, id[:len(p)]) {
if match == nil {
match = id
} else {
return nil, ErrMultipleIDMatches
}
}
}
if match != nil {
return match, nil
}
return nil, ErrNoIDPrefixFound
}
// FindSnapshot takes a string and tries to find a snapshot whose ID matches
// the string as closely as possible.
func FindSnapshot(be Server, s string) (ID, error) {
// parse ID directly
if id, err := ParseID(s); err == nil {
return id, nil
}
// find snapshot id with prefix
id, err := Find(be, Snapshot, s)
if err != nil {
return nil, err
}
return id, nil
}