diff --git a/repository/index.go b/repository/index.go index ca81d545c..a964006c6 100644 --- a/repository/index.go +++ b/repository/index.go @@ -319,6 +319,19 @@ func (idx *Index) Dump(w io.Writer) error { return nil } +// isErrOldIndex returns true if the error may be caused by an old index +// format. +func isErrOldIndex(err error) bool { + if e, ok := err.(*json.UnmarshalTypeError); ok && e.Value == "array" { + return true + } + + return false +} + +// ErrOldIndexFormat means an index with the old format was detected. +var ErrOldIndexFormat = errors.New("index has old format") + // DecodeIndex loads and unserializes an index from rd. func DecodeIndex(rd io.Reader) (*Index, backend.IDs, error) { debug.Log("Index.DecodeIndex", "Start decoding index") @@ -328,6 +341,12 @@ func DecodeIndex(rd io.Reader) (*Index, backend.IDs, error) { err := dec.Decode(&idxJSON) if err != nil { debug.Log("Index.DecodeIndex", "Error %#v", err) + + if isErrOldIndex(err) { + debug.Log("Index.DecodeIndex", "index is probably old format, trying that") + err = ErrOldIndexFormat + } + return nil, nil, err } diff --git a/repository/repository.go b/repository/repository.go index 6263ce448..8c3d81fa9 100644 --- a/repository/repository.go +++ b/repository/repository.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "io/ioutil" + "os" "sync" "github.com/restic/chunker" @@ -540,7 +541,21 @@ func (r *Repository) LoadIndex() error { // LoadIndex loads the index id from backend and returns it. func LoadIndex(repo *Repository, id string) (*Index, error) { - debug.Log("LoadIndex", "Loading index %v", id[:8]) + idx, err := loadIndex(repo, id, false) + if err == nil { + return idx, nil + } + + if err == ErrOldIndexFormat { + fmt.Fprintf(os.Stderr, "index %v has old format\n", id) + return loadIndex(repo, id, true) + } + + return nil, err +} + +func loadIndex(repo *Repository, id string, oldFormat bool) (*Index, error) { + debug.Log("loadIndex", "Loading index %v", id[:8]) rd, err := repo.be.Get(backend.Index, id) defer rd.Close() @@ -555,9 +570,16 @@ func LoadIndex(repo *Repository, id string) (*Index, error) { return nil, err } - idx, _, err := DecodeIndex(decryptRd) + var idx *Index + + if !oldFormat { + idx, _, err = DecodeIndex(decryptRd) + } else { + idx, _, err = DecodeOldIndex(decryptRd) + } + if err != nil { - debug.Log("LoadIndex", "error while decoding index %v: %v", id, err) + debug.Log("loadIndex", "error while decoding index %v: %v", id, err) return nil, err }