diff --git a/src/internal/m365/collection/groups/collection.go b/src/internal/m365/collection/groups/collection.go index 533e42e9e..2ca70c3f0 100644 --- a/src/internal/m365/collection/groups/collection.go +++ b/src/internal/m365/collection/groups/collection.go @@ -133,8 +133,7 @@ func (col Collection) State() data.CollectionState { } func (col Collection) DoNotMergeItems() bool { - // TODO: depends on whether or not deltas are valid - return true + return col.doNotMergeItems } // --------------------------------------------------------------------------- diff --git a/src/internal/m365/collection/groups/metadata.go b/src/internal/m365/collection/groups/metadata.go index ee4a70c71..e34cab250 100644 --- a/src/internal/m365/collection/groups/metadata.go +++ b/src/internal/m365/collection/groups/metadata.go @@ -69,7 +69,15 @@ func parseMetadataCollections( switch item.ID() { case metadata.PreviousPathFileName: - // no-op at this time, previous paths not needed + if _, ok := found[category][metadata.PathKey]; ok { + return nil, false, clues.Wrap(clues.New(category.String()), "multiple versions of path metadata").WithClues(ctx) + } + + for k, p := range m { + cdps.AddPath(k, p) + } + + found[category][metadata.PathKey] = struct{}{} case metadata.DeltaURLsFileName: if _, ok := found[category][metadata.DeltaKey]; ok { @@ -100,9 +108,16 @@ func parseMetadataCollections( }, false, nil } - // Do not remove entries that contain only a path or a delta, but not both. - // This condition is expected. Channels only record their path. Messages - // only record their deltas. + // Remove any entries that contain a path or a delta, but not both. + // That metadata is considered incomplete, and needs to incur a + // complete backup on the next run. + for _, dps := range cdp { + for k, dp := range dps { + if len(dp.Path) == 0 { + delete(dps, k) + } + } + } return cdp, true, nil } diff --git a/src/internal/operations/backup.go b/src/internal/operations/backup.go index 54f321472..316e3e8ee 100644 --- a/src/internal/operations/backup.go +++ b/src/internal/operations/backup.go @@ -365,7 +365,11 @@ func (op *BackupOperation) do( return nil, clues.Wrap(err, "producing manifests and metadata") } - ctx = clues.Add(ctx, "can_use_metadata", canUseMetadata) + ctx = clues.Add( + ctx, + "can_use_metadata", canUseMetadata, + "assist_bases", len(mans.AssistBases()), + "merge_bases", len(mans.MergeBases())) if canUseMetadata { lastBackupVersion = mans.MinBackupVersion() @@ -711,6 +715,7 @@ func mergeDetails( // Don't bother loading any of the base details if there's nothing we need to merge. if bases == nil || dataFromBackup == nil || dataFromBackup.ItemsToMerge() == 0 { + logger.Ctx(ctx).Info("no base details to merge") return nil } diff --git a/src/pkg/services/m365/api/channels_pager.go b/src/pkg/services/m365/api/channels_pager.go index 026348106..3eb410d2a 100644 --- a/src/pkg/services/m365/api/channels_pager.go +++ b/src/pkg/services/m365/api/channels_pager.go @@ -129,7 +129,7 @@ func (c Channels) GetChannelMessageIDsDelta( } for _, v := range vals { - if v.GetAdditionalData()[graph.AddtlDataRemoved] == nil { + if v.GetDeletedDateTime() == nil { added[ptr.Val(v.GetId())] = struct{}{} } else { deleted[ptr.Val(v.GetId())] = struct{}{} diff --git a/website/docs/support/known-issues.md b/website/docs/support/known-issues.md index e6bc12809..f7e8e5ff3 100644 --- a/website/docs/support/known-issues.md +++ b/website/docs/support/known-issues.md @@ -25,3 +25,5 @@ Below is a list of known Corso issues and limitations: not be inheritable by children. * Link shares with password protection can't be restored. + +* All replies in a Teams Conversation are removed from backup when the root message gets deleted. \ No newline at end of file