github.com/advanderveer/restic@v0.8.1-0.20171209104529-42a8c19aaea6/internal/restic/backend_find.go (about) 1 package restic 2 3 import ( 4 "context" 5 6 "github.com/restic/restic/internal/errors" 7 ) 8 9 // ErrNoIDPrefixFound is returned by Find() when no ID for the given prefix 10 // could be found. 11 var ErrNoIDPrefixFound = errors.New("no ID found") 12 13 // ErrMultipleIDMatches is returned by Find() when multiple IDs with the given 14 // prefix are found. 15 var ErrMultipleIDMatches = errors.New("multiple IDs with prefix found") 16 17 // Find loads the list of all files of type t and searches for names which 18 // start with prefix. If none is found, nil and ErrNoIDPrefixFound is returned. 19 // If more than one is found, nil and ErrMultipleIDMatches is returned. 20 func Find(be Lister, t FileType, prefix string) (string, error) { 21 match := "" 22 23 // TODO: optimize by sorting list etc. 24 for name := range be.List(context.TODO(), t) { 25 if prefix == name[:len(prefix)] { 26 if match == "" { 27 match = name 28 } else { 29 return "", ErrMultipleIDMatches 30 } 31 } 32 } 33 34 if match != "" { 35 return match, nil 36 } 37 38 return "", ErrNoIDPrefixFound 39 } 40 41 const minPrefixLength = 8 42 43 // PrefixLength returns the number of bytes required so that all prefixes of 44 // all names of type t are unique. 45 func PrefixLength(be Lister, t FileType) (int, error) { 46 // load all IDs of the given type 47 list := make([]string, 0, 100) 48 for name := range be.List(context.TODO(), t) { 49 list = append(list, name) 50 } 51 52 // select prefixes of length l, test if the last one is the same as the current one 53 id := ID{} 54 outer: 55 for l := minPrefixLength; l < len(id); l++ { 56 var last string 57 58 for _, name := range list { 59 if last == name[:l] { 60 continue outer 61 } 62 last = name[:l] 63 } 64 65 return l, nil 66 } 67 68 return len(id), nil 69 }