Wrapper for Collections to make them RestoreCollections (#2431)

## Description

Create a wrapper struct that provides a `Fetch(ctx, name) (Stream, error)` function that always returns `ErrNotFound`. A future PR is going to expand the `RestoreCollection` interface to include that function and I wanted to reduce the amount of chaff that would come out of it

This PR just creates the wrapper and moves `ErrNotFound` from the kopia package to `data` package to avoid import cycles

## Does this PR need a docs update or release note?

- [ ]  Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [x]  No 

## Type of change

- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [x] 🤖 Test
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup

## Issue(s)

* #1944

## Test Plan

- [ ] 💪 Manual
- [x]  Unit test
- [ ] 💚 E2E
This commit is contained in:
ashmrtn 2023-02-08 10:59:41 -08:00 committed by GitHub
parent 3d244c9fea
commit c63aa94204
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 58 additions and 43 deletions

View File

@ -12,7 +12,7 @@ import (
"github.com/alcionai/corso/src/cli/options" "github.com/alcionai/corso/src/cli/options"
. "github.com/alcionai/corso/src/cli/print" . "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/kopia" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
@ -323,16 +323,16 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func exchangeBackupCreateSelectors(userIDs, data []string) *selectors.ExchangeBackup { func exchangeBackupCreateSelectors(userIDs, cats []string) *selectors.ExchangeBackup {
sel := selectors.NewExchangeBackup(userIDs) sel := selectors.NewExchangeBackup(userIDs)
if len(data) == 0 { if len(cats) == 0 {
sel.Include(sel.ContactFolders(selectors.Any())) sel.Include(sel.ContactFolders(selectors.Any()))
sel.Include(sel.MailFolders(selectors.Any())) sel.Include(sel.MailFolders(selectors.Any()))
sel.Include(sel.EventCalendars(selectors.Any())) sel.Include(sel.EventCalendars(selectors.Any()))
} }
for _, d := range data { for _, d := range cats {
switch d { switch d {
case dataContacts: case dataContacts:
sel.Include(sel.ContactFolders(selectors.Any())) sel.Include(sel.ContactFolders(selectors.Any()))
@ -346,12 +346,12 @@ func exchangeBackupCreateSelectors(userIDs, data []string) *selectors.ExchangeBa
return sel return sel
} }
func validateExchangeBackupCreateFlags(userIDs, data []string) error { func validateExchangeBackupCreateFlags(userIDs, cats []string) error {
if len(userIDs) == 0 { if len(userIDs) == 0 {
return errors.New("--user requires one or more email addresses or the wildcard '*'") return errors.New("--user requires one or more email addresses or the wildcard '*'")
} }
for _, d := range data { for _, d := range cats {
if d != dataContacts && d != dataEmail && d != dataEvents { if d != dataContacts && d != dataEmail && d != dataEvents {
return errors.New( return errors.New(
d + " is an unrecognized data type; must be one of " + dataContacts + ", " + dataEmail + ", or " + dataEvents) d + " is an unrecognized data type; must be one of " + dataContacts + ", " + dataEmail + ", or " + dataEvents)
@ -394,7 +394,7 @@ func listExchangeCmd(cmd *cobra.Command, args []string) error {
if len(backupID) > 0 { if len(backupID) > 0 {
b, err := r.Backup(ctx, model.StableID(backupID)) b, err := r.Backup(ctx, model.StableID(backupID))
if err != nil { if err != nil {
if errors.Is(err, kopia.ErrNotFound) { if errors.Is(err, data.ErrNotFound) {
return Only(ctx, errors.Errorf("No backup exists with the id %s", backupID)) return Only(ctx, errors.Errorf("No backup exists with the id %s", backupID))
} }
@ -502,7 +502,7 @@ func runDetailsExchangeCmd(
d, _, errs := r.BackupDetails(ctx, backupID) d, _, errs := r.BackupDetails(ctx, backupID)
// TODO: log/track recoverable errors // TODO: log/track recoverable errors
if errs.Err() != nil { if errs.Err() != nil {
if errors.Is(errs.Err(), kopia.ErrNotFound) { if errors.Is(errs.Err(), data.ErrNotFound) {
return nil, errors.Errorf("No backup exists with the id %s", backupID) return nil, errors.Errorf("No backup exists with the id %s", backupID)
} }

View File

@ -12,7 +12,7 @@ import (
"github.com/alcionai/corso/src/cli/options" "github.com/alcionai/corso/src/cli/options"
. "github.com/alcionai/corso/src/cli/print" . "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/kopia" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
@ -294,7 +294,7 @@ func listOneDriveCmd(cmd *cobra.Command, args []string) error {
if len(backupID) > 0 { if len(backupID) > 0 {
b, err := r.Backup(ctx, model.StableID(backupID)) b, err := r.Backup(ctx, model.StableID(backupID))
if err != nil { if err != nil {
if errors.Is(err, kopia.ErrNotFound) { if errors.Is(err, data.ErrNotFound) {
return Only(ctx, errors.Errorf("No backup exists with the id %s", backupID)) return Only(ctx, errors.Errorf("No backup exists with the id %s", backupID))
} }
@ -394,7 +394,7 @@ func runDetailsOneDriveCmd(
d, _, errs := r.BackupDetails(ctx, backupID) d, _, errs := r.BackupDetails(ctx, backupID)
// TODO: log/track recoverable errors // TODO: log/track recoverable errors
if errs.Err() != nil { if errs.Err() != nil {
if errors.Is(errs.Err(), kopia.ErrNotFound) { if errors.Is(errs.Err(), data.ErrNotFound) {
return nil, errors.Errorf("no backup exists with the id %s", backupID) return nil, errors.Errorf("no backup exists with the id %s", backupID)
} }

View File

@ -14,7 +14,7 @@ import (
"github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/connector" "github.com/alcionai/corso/src/internal/connector"
"github.com/alcionai/corso/src/internal/connector/graph" "github.com/alcionai/corso/src/internal/connector/graph"
"github.com/alcionai/corso/src/internal/kopia" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/backup"
"github.com/alcionai/corso/src/pkg/backup/details" "github.com/alcionai/corso/src/pkg/backup/details"
@ -266,7 +266,7 @@ func createSharePointCmd(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func validateSharePointBackupCreateFlags(sites, weburls, data []string) error { func validateSharePointBackupCreateFlags(sites, weburls, cats []string) error {
if len(sites) == 0 && len(weburls) == 0 { if len(sites) == 0 && len(weburls) == 0 {
return errors.New( return errors.New(
"requires one or more --" + "requires one or more --" +
@ -276,7 +276,7 @@ func validateSharePointBackupCreateFlags(sites, weburls, data []string) error {
) )
} }
for _, d := range data { for _, d := range cats {
if d != dataLibraries && d != dataPages { if d != dataLibraries && d != dataPages {
return errors.New( return errors.New(
d + " is an unrecognized data type; either " + dataLibraries + "or " + dataPages, d + " is an unrecognized data type; either " + dataLibraries + "or " + dataPages,
@ -290,7 +290,7 @@ func validateSharePointBackupCreateFlags(sites, weburls, data []string) error {
// TODO: users might specify a data type, this only supports AllData(). // TODO: users might specify a data type, this only supports AllData().
func sharePointBackupCreateSelectors( func sharePointBackupCreateSelectors(
ctx context.Context, ctx context.Context,
sites, weburls, data []string, sites, weburls, cats []string,
gc *connector.GraphConnector, gc *connector.GraphConnector,
) (*selectors.SharePointBackup, error) { ) (*selectors.SharePointBackup, error) {
if len(sites) == 0 && len(weburls) == 0 { if len(sites) == 0 && len(weburls) == 0 {
@ -321,13 +321,13 @@ func sharePointBackupCreateSelectors(
} }
sel := selectors.NewSharePointBackup(union) sel := selectors.NewSharePointBackup(union)
if len(data) == 0 { if len(cats) == 0 {
sel.Include(sel.AllData()) sel.Include(sel.AllData())
return sel, nil return sel, nil
} }
for _, d := range data { for _, d := range cats {
switch d { switch d {
case dataLibraries: case dataLibraries:
sel.Include(sel.Libraries(selectors.Any())) sel.Include(sel.Libraries(selectors.Any()))
@ -372,7 +372,7 @@ func listSharePointCmd(cmd *cobra.Command, args []string) error {
if len(backupID) > 0 { if len(backupID) > 0 {
b, err := r.Backup(ctx, model.StableID(backupID)) b, err := r.Backup(ctx, model.StableID(backupID))
if err != nil { if err != nil {
if errors.Is(err, kopia.ErrNotFound) { if errors.Is(err, data.ErrNotFound) {
return Only(ctx, errors.Errorf("No backup exists with the id %s", backupID)) return Only(ctx, errors.Errorf("No backup exists with the id %s", backupID))
} }
@ -513,7 +513,7 @@ func runDetailsSharePointCmd(
d, _, errs := r.BackupDetails(ctx, backupID) d, _, errs := r.BackupDetails(ctx, backupID)
// TODO: log/track recoverable errors // TODO: log/track recoverable errors
if errs.Err() != nil { if errs.Err() != nil {
if errors.Is(errs.Err(), kopia.ErrNotFound) { if errors.Is(errs.Err(), data.ErrNotFound) {
return nil, errors.Errorf("no backup exists with the id %s", backupID) return nil, errors.Errorf("no backup exists with the id %s", backupID)
} }

View File

@ -10,7 +10,7 @@ import (
. "github.com/alcionai/corso/src/cli/print" . "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/common" "github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/kopia" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/repository" "github.com/alcionai/corso/src/pkg/repository"
) )
@ -228,7 +228,7 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
ds, err := ro.Run(ctx) ds, err := ro.Run(ctx)
if err != nil { if err != nil {
if errors.Is(err, kopia.ErrNotFound) { if errors.Is(err, data.ErrNotFound) {
return Only(ctx, errors.Errorf("Backup or backup details missing for id %s", backupID)) return Only(ctx, errors.Errorf("Backup or backup details missing for id %s", backupID))
} }

View File

@ -10,7 +10,7 @@ import (
. "github.com/alcionai/corso/src/cli/print" . "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/common" "github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/kopia" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/repository" "github.com/alcionai/corso/src/pkg/repository"
) )
@ -171,7 +171,7 @@ func restoreOneDriveCmd(cmd *cobra.Command, args []string) error {
ds, err := ro.Run(ctx) ds, err := ro.Run(ctx)
if err != nil { if err != nil {
if errors.Is(err, kopia.ErrNotFound) { if errors.Is(err, data.ErrNotFound) {
return Only(ctx, errors.Errorf("Backup or backup details missing for id %s", backupID)) return Only(ctx, errors.Errorf("Backup or backup details missing for id %s", backupID))
} }

View File

@ -10,7 +10,7 @@ import (
. "github.com/alcionai/corso/src/cli/print" . "github.com/alcionai/corso/src/cli/print"
"github.com/alcionai/corso/src/cli/utils" "github.com/alcionai/corso/src/cli/utils"
"github.com/alcionai/corso/src/internal/common" "github.com/alcionai/corso/src/internal/common"
"github.com/alcionai/corso/src/internal/kopia" "github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/pkg/control" "github.com/alcionai/corso/src/pkg/control"
"github.com/alcionai/corso/src/pkg/repository" "github.com/alcionai/corso/src/pkg/repository"
) )
@ -166,7 +166,7 @@ func restoreSharePointCmd(cmd *cobra.Command, args []string) error {
ds, err := ro.Run(ctx) ds, err := ro.Run(ctx)
if err != nil { if err != nil {
if errors.Is(err, kopia.ErrNotFound) { if errors.Is(err, data.ErrNotFound) {
return Only(ctx, errors.Errorf("Backup or backup details missing for id %s", backupID)) return Only(ctx, errors.Errorf("Backup or backup details missing for id %s", backupID))
} }

View File

@ -1,6 +1,8 @@
package data package data
import ( import (
"context"
"errors"
"io" "io"
"time" "time"
@ -12,6 +14,8 @@ import (
// standard ifaces // standard ifaces
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
var ErrNotFound = errors.New("not found")
type CollectionState int type CollectionState int
const ( const (
@ -66,6 +70,16 @@ type RestoreCollection interface {
Collection Collection
} }
// NotFoundRestoreCollection is a wrapper for a Collection that returns
// ErrNotFound for all Fetch calls.
type NotFoundRestoreCollection struct {
Collection
}
func (c NotFoundRestoreCollection) Fetch(context.Context, string) (Stream, error) {
return nil, ErrNotFound
}
// Stream represents a single item within a Collection // Stream represents a single item within a Collection
// that can be consumed as a stream (it embeds io.Reader) // that can be consumed as a stream (it embeds io.Reader)
type Stream interface { type Stream interface {

View File

@ -10,6 +10,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"golang.org/x/exp/maps" "golang.org/x/exp/maps"
"github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/model"
) )
@ -20,7 +21,6 @@ const (
) )
var ( var (
ErrNotFound = errors.New("not found")
errNoModelStoreID = errors.New("model has no ModelStoreID") errNoModelStoreID = errors.New("model has no ModelStoreID")
errNoStableID = errors.New("model has no StableID") errNoStableID = errors.New("model has no StableID")
errBadTagKey = errors.New("tag key overlaps with required key") errBadTagKey = errors.New("tag key overlaps with required key")
@ -281,7 +281,7 @@ func (ms *ModelStore) getModelStoreID(
} }
if len(metadata) == 0 { if len(metadata) == 0 {
return "", errors.Wrap(ErrNotFound, "getting ModelStoreID") return "", errors.Wrap(data.ErrNotFound, "getting ModelStoreID")
} }
if len(metadata) != 1 { if len(metadata) != 1 {
@ -302,7 +302,7 @@ func (ms *ModelStore) Get(
ctx context.Context, ctx context.Context,
s model.Schema, s model.Schema,
id model.StableID, id model.StableID,
data model.Model, m model.Model,
) error { ) error {
if !s.Valid() { if !s.Valid() {
return errors.WithStack(errUnrecognizedSchema) return errors.WithStack(errUnrecognizedSchema)
@ -313,7 +313,7 @@ func (ms *ModelStore) Get(
return err return err
} }
return transmuteErr(ms.GetWithModelStoreID(ctx, s, modelID, data)) return transmuteErr(ms.GetWithModelStoreID(ctx, s, modelID, m))
} }
// GetWithModelStoreID deserializes the model with the given ModelStoreID into // GetWithModelStoreID deserializes the model with the given ModelStoreID into
@ -323,7 +323,7 @@ func (ms *ModelStore) GetWithModelStoreID(
ctx context.Context, ctx context.Context,
s model.Schema, s model.Schema,
id manifest.ID, id manifest.ID,
data model.Model, m model.Model,
) error { ) error {
if !s.Valid() { if !s.Valid() {
return errors.WithStack(errUnrecognizedSchema) return errors.WithStack(errUnrecognizedSchema)
@ -333,7 +333,7 @@ func (ms *ModelStore) GetWithModelStoreID(
return errors.WithStack(errNoModelStoreID) return errors.WithStack(errNoModelStoreID)
} }
metadata, err := ms.c.GetManifest(ctx, id, data) metadata, err := ms.c.GetManifest(ctx, id, m)
if err != nil { if err != nil {
return errors.Wrap(transmuteErr(err), "getting model data") return errors.Wrap(transmuteErr(err), "getting model data")
} }
@ -343,7 +343,7 @@ func (ms *ModelStore) GetWithModelStoreID(
} }
return errors.Wrap( return errors.Wrap(
ms.populateBaseModelFromMetadata(data.Base(), metadata), ms.populateBaseModelFromMetadata(m.Base(), metadata),
"getting model by ID", "getting model by ID",
) )
} }
@ -457,7 +457,7 @@ func (ms *ModelStore) Delete(ctx context.Context, s model.Schema, id model.Stabl
latest, err := ms.getModelStoreID(ctx, s, id) latest, err := ms.getModelStoreID(ctx, s, id)
if err != nil { if err != nil {
if errors.Is(err, ErrNotFound) { if errors.Is(err, data.ErrNotFound) {
return nil return nil
} }
@ -490,7 +490,7 @@ func (ms *ModelStore) DeleteWithModelStoreID(ctx context.Context, id manifest.ID
func transmuteErr(err error) error { func transmuteErr(err error) error {
switch { switch {
case errors.Is(err, manifest.ErrNotFound): case errors.Is(err, manifest.ErrNotFound):
return ErrNotFound return data.ErrNotFound
default: default:
return err return err
} }

View File

@ -12,6 +12,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"github.com/alcionai/corso/src/internal/data"
"github.com/alcionai/corso/src/internal/model" "github.com/alcionai/corso/src/internal/model"
"github.com/alcionai/corso/src/internal/tester" "github.com/alcionai/corso/src/internal/tester"
"github.com/alcionai/corso/src/pkg/backup" "github.com/alcionai/corso/src/pkg/backup"
@ -360,9 +361,9 @@ func (suite *ModelStoreIntegrationSuite) TestPutGet_WithTags() {
func (suite *ModelStoreIntegrationSuite) TestGet_NotFoundErrors() { func (suite *ModelStoreIntegrationSuite) TestGet_NotFoundErrors() {
t := suite.T() t := suite.T()
assert.ErrorIs(t, suite.m.Get(suite.ctx, model.BackupOpSchema, "baz", nil), ErrNotFound) assert.ErrorIs(t, suite.m.Get(suite.ctx, model.BackupOpSchema, "baz", nil), data.ErrNotFound)
assert.ErrorIs( assert.ErrorIs(
t, suite.m.GetWithModelStoreID(suite.ctx, model.BackupOpSchema, "baz", nil), ErrNotFound) t, suite.m.GetWithModelStoreID(suite.ctx, model.BackupOpSchema, "baz", nil), data.ErrNotFound)
} }
func (suite *ModelStoreIntegrationSuite) TestPutGetOfTypeBadVersion() { func (suite *ModelStoreIntegrationSuite) TestPutGetOfTypeBadVersion() {
@ -630,7 +631,7 @@ func (suite *ModelStoreIntegrationSuite) TestPutUpdate() {
} }
err = m.GetWithModelStoreID(ctx, theModelType, oldModelID, nil) err = m.GetWithModelStoreID(ctx, theModelType, oldModelID, nil)
assert.ErrorIs(t, err, ErrNotFound) assert.ErrorIs(t, err, data.ErrNotFound)
}) })
} }
} }
@ -691,7 +692,7 @@ func (suite *ModelStoreIntegrationSuite) TestPutDelete() {
returned := &fooModel{} returned := &fooModel{}
err := suite.m.GetWithModelStoreID(suite.ctx, theModelType, foo.ModelStoreID, returned) err := suite.m.GetWithModelStoreID(suite.ctx, theModelType, foo.ModelStoreID, returned)
assert.ErrorIs(t, err, ErrNotFound) assert.ErrorIs(t, err, data.ErrNotFound)
} }
func (suite *ModelStoreIntegrationSuite) TestPutDelete_BadIDsNoop() { func (suite *ModelStoreIntegrationSuite) TestPutDelete_BadIDsNoop() {
@ -775,7 +776,7 @@ func (suite *ModelStoreRegressionSuite) TestFailDuringWriteSessionHasNoVisibleEf
assert.ErrorIs(t, err, assert.AnError) assert.ErrorIs(t, err, assert.AnError)
err = m.GetWithModelStoreID(ctx, theModelType, newID, nil) err = m.GetWithModelStoreID(ctx, theModelType, newID, nil)
assert.ErrorIs(t, err, ErrNotFound) assert.ErrorIs(t, err, data.ErrNotFound)
returned := &fooModel{} returned := &fooModel{}
require.NoError( require.NoError(

View File

@ -317,7 +317,7 @@ func getItemStream(
) )
if err != nil { if err != nil {
if strings.Contains(err.Error(), "entry not found") { if strings.Contains(err.Error(), "entry not found") {
err = errors.Wrap(ErrNotFound, err.Error()) err = errors.Wrap(data.ErrNotFound, err.Error())
} }
return nil, errors.Wrap(err, "getting nested object handle") return nil, errors.Wrap(err, "getting nested object handle")

View File

@ -500,7 +500,7 @@ func (suite *KopiaIntegrationSuite) TestBackupCollections_ReaderError() {
// Files that had an error shouldn't make a dir entry in kopia. If they do we // Files that had an error shouldn't make a dir entry in kopia. If they do we
// may run into kopia-assisted incrementals issues because only mod time and // may run into kopia-assisted incrementals issues because only mod time and
// not file size is checked for StreamingFiles. // not file size is checked for StreamingFiles.
assert.ErrorIs(t, err, ErrNotFound, "errored file is restorable") assert.ErrorIs(t, err, data.ErrNotFound, "errored file is restorable")
} }
type backedupFile struct { type backedupFile struct {

View File

@ -97,7 +97,7 @@ func produceManifestsAndMetadata(
if err != nil { if err != nil {
// if no backup exists for any of the complete manifests, we want // if no backup exists for any of the complete manifests, we want
// to fall back to a complete backup. // to fall back to a complete backup.
if errors.Is(err, kopia.ErrNotFound) { if errors.Is(err, data.ErrNotFound) {
logger.Ctx(ctx).Infow("backup missing, falling back to full backup", clues.In(mctx).Slice()...) logger.Ctx(ctx).Infow("backup missing, falling back to full backup", clues.In(mctx).Slice()...)
return ms, nil, false, nil return ms, nil, false, nil
} }
@ -118,7 +118,7 @@ func produceManifestsAndMetadata(
} }
colls, err := collectMetadata(mctx, mr, man, metadataFiles, tenantID) colls, err := collectMetadata(mctx, mr, man, metadataFiles, tenantID)
if err != nil && !errors.Is(err, kopia.ErrNotFound) { if err != nil && !errors.Is(err, data.ErrNotFound) {
// prior metadata isn't guaranteed to exist. // prior metadata isn't guaranteed to exist.
// if it doesn't, we'll just have to do a // if it doesn't, we'll just have to do a
// full backup for that data. // full backup for that data.