Alternative way to handle 2-level calendars hierarchy (#2397)
All calendars except the default are nested under a "Other Calendars" folder. Having a non-default calendar named the same as the default calendar does not cause problems when fetching the default calendar by name. Only the default calendar will be returned in that situation. This fixes the bug where we had multiple collections for the same path but representing different folders. Also updates the restore execution path to handle the new nested folder structure. Backup, incremental backup, and restore flows tested manually - [x] ✅ Yes, it's included - [ ] 🕐 Yes, but in a later PR - [ ] ⛔ No - [ ] 🌻 Feature - [x] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Test - [ ] 💻 CI/Deployment - [ ] 🧹 Tech Debt/Cleanup * #2388 - [x] 💪 Manual - [ ] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
6a1dbd388b
commit
d4bb22f498
13
CHANGELOG.md
13
CHANGELOG.md
@ -12,6 +12,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Document Corso's fault-tolerance and restartability features
|
||||
- Add retries on timeouts and status code 500 for Exchange
|
||||
- Increase page size preference for delta requests for Exchange to reduce number of roundtrips
|
||||
- OneDrive file/folder permissions can now be backed up and restored
|
||||
- Add `--restore-permissions` flag to toggle restoration of OneDrive permissions
|
||||
- Add versions to backups so that we can understand/handle older backup formats
|
||||
|
||||
### Fixed
|
||||
- Backing up a calendar that has the same name as the default calendar
|
||||
|
||||
### Known Issues
|
||||
|
||||
- When the same user has permissions to a file and the containing
|
||||
folder, we only restore folder level permissions for the user and no
|
||||
separate file only permission is restored.
|
||||
- Link shares are not restored
|
||||
|
||||
## [v0.2.0] (alpha) - 2023-1-29
|
||||
|
||||
|
||||
@ -501,10 +501,11 @@ func (suite *FolderCacheIntegrationSuite) TestCreateContainerDestination() {
|
||||
directoryCaches = make(map[path.CategoryType]graph.ContainerResolver)
|
||||
folderName = tester.DefaultTestRestoreDestination().ContainerName
|
||||
tests = []struct {
|
||||
name string
|
||||
pathFunc1 func(t *testing.T) path.Path
|
||||
pathFunc2 func(t *testing.T) path.Path
|
||||
category path.CategoryType
|
||||
name string
|
||||
pathFunc1 func(t *testing.T) path.Path
|
||||
pathFunc2 func(t *testing.T) path.Path
|
||||
category path.CategoryType
|
||||
folderPrefix string
|
||||
}{
|
||||
{
|
||||
name: "Mail Cache Test",
|
||||
@ -587,6 +588,7 @@ func (suite *FolderCacheIntegrationSuite) TestCreateContainerDestination() {
|
||||
require.NoError(t, err)
|
||||
return aPath
|
||||
},
|
||||
folderPrefix: calendarOthersFolder,
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -617,8 +619,9 @@ func (suite *FolderCacheIntegrationSuite) TestCreateContainerDestination() {
|
||||
_, err = resolver.IDToPath(ctx, secondID)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, ok := resolver.PathInCache(folderName)
|
||||
require.True(t, ok)
|
||||
p := stdpath.Join(test.folderPrefix, folderName)
|
||||
_, ok := resolver.PathInCache(p)
|
||||
require.True(t, ok, "looking for path in cache: %s", p)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,9 +537,9 @@ func (suite *DataCollectionsIntegrationSuite) TestEventsSerializationRegression(
|
||||
},
|
||||
{
|
||||
name: "Birthday Calendar",
|
||||
expected: "Birthdays",
|
||||
expected: calendarOthersFolder + "/Birthdays",
|
||||
scope: selectors.NewExchangeBackup(users).EventCalendars(
|
||||
[]string{"Birthdays"},
|
||||
[]string{calendarOthersFolder + "/Birthdays"},
|
||||
selectors.PrefixMatch(),
|
||||
)[0],
|
||||
},
|
||||
|
||||
@ -64,7 +64,15 @@ func (ecc *eventCalendarCache) Populate(
|
||||
return errors.Wrap(err, "initializing")
|
||||
}
|
||||
|
||||
err := ecc.enumer.EnumerateContainers(ctx, ecc.userID, "", ecc.addFolder)
|
||||
err := ecc.enumer.EnumerateContainers(
|
||||
ctx,
|
||||
ecc.userID,
|
||||
"",
|
||||
func(cf graph.CacheFolder) error {
|
||||
cf.SetPath(path.Builder{}.Append(calendarOthersFolder, *cf.GetDisplayName()))
|
||||
return ecc.addFolder(cf)
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "enumerating containers")
|
||||
}
|
||||
@ -83,7 +91,7 @@ func (ecc *eventCalendarCache) AddToCache(ctx context.Context, f graph.Container
|
||||
return errors.Wrap(err, "validating container")
|
||||
}
|
||||
|
||||
temp := graph.NewCacheFolder(f, path.Builder{}.Append(*f.GetDisplayName()))
|
||||
temp := graph.NewCacheFolder(f, path.Builder{}.Append(calendarOthersFolder, *f.GetDisplayName()))
|
||||
|
||||
if err := ecc.addFolder(temp); err != nil {
|
||||
return errors.Wrap(err, "adding container")
|
||||
|
||||
@ -38,4 +38,5 @@ const (
|
||||
rootFolderAlias = "msgfolderroot"
|
||||
DefaultContactFolder = "Contacts"
|
||||
DefaultCalendar = "Calendar"
|
||||
calendarOthersFolder = "Other Calendars"
|
||||
)
|
||||
|
||||
@ -637,7 +637,11 @@ func establishEventsRestoreLocation(
|
||||
user string,
|
||||
isNewCache bool,
|
||||
) (string, error) {
|
||||
cached, ok := ecc.PathInCache(folders[0])
|
||||
// Need to prefix with the "Other Calendars" folder so lookup happens properly.
|
||||
cached, ok := ecc.PathInCache(path.Builder{}.Append(
|
||||
calendarOthersFolder,
|
||||
folders[0],
|
||||
).String())
|
||||
if ok {
|
||||
return cached, nil
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user