From d3573d12dcf8551a609570acf154d5523a44ccfc Mon Sep 17 00:00:00 2001 From: ashmrtn Date: Wed, 21 Dec 2022 16:09:40 -0800 Subject: [PATCH] Allow updating portions of ItemInfo for some types (#1883) ## Description Add helper functions that allows updating ItemInfo given a new path.Path. This is required because some items embed portions of the path in their details. ## Does this PR need a docs update or release note? - [ ] :white_check_mark: Yes, it's included - [ ] :clock1: Yes, but in a later PR - [x] :no_entry: No ## Type of change - [x] :sunflower: Feature - [ ] :bug: Bugfix - [ ] :world_map: Documentation - [ ] :robot: Test - [ ] :computer: CI/Deployment - [ ] :hamster: Trivial/Minor ## Issue(s) * #1800 ## Test Plan - [ ] :muscle: Manual - [x] :zap: Unit test - [ ] :green_heart: E2E --- src/pkg/backup/details/details.go | 38 ++++++ src/pkg/backup/details/details_test.go | 180 +++++++++++++++++++++++++ 2 files changed, 218 insertions(+) diff --git a/src/pkg/backup/details/details.go b/src/pkg/backup/details/details.go index 79f85cc31..c64ecce51 100644 --- a/src/pkg/backup/details/details.go +++ b/src/pkg/backup/details/details.go @@ -7,9 +7,11 @@ import ( "time" "github.com/dustin/go-humanize" + "github.com/pkg/errors" "github.com/alcionai/corso/src/cli/print" "github.com/alcionai/corso/src/internal/common" + "github.com/alcionai/corso/src/pkg/path" ) type FolderEntry struct { @@ -297,6 +299,20 @@ const ( FolderItem ItemType = iota + 300 ) +func UpdateItem(item *ItemInfo, newPath path.Path) error { + // Only OneDrive and SharePoint have information about parent folders + // contained in them. + switch item.infoType() { + case SharePointItem: + return item.SharePoint.UpdateParentPath(newPath) + + case OneDriveItem: + return item.OneDrive.UpdateParentPath(newPath) + } + + return nil +} + // ItemInfo is a oneOf that contains service specific // information about the item it tracks type ItemInfo struct { @@ -435,6 +451,17 @@ func (i SharePointInfo) Values() []string { } } +func (i *SharePointInfo) UpdateParentPath(newPath path.Path) error { + newParent, err := path.GetDriveFolderPath(newPath) + if err != nil { + return errors.Wrapf(err, "making sharepoint path from %s", newPath) + } + + i.ParentPath = newParent + + return nil +} + // OneDriveInfo describes a oneDrive item type OneDriveInfo struct { Created time.Time `json:"created,omitempty"` @@ -464,3 +491,14 @@ func (i OneDriveInfo) Values() []string { common.FormatTabularDisplayTime(i.Modified), } } + +func (i *OneDriveInfo) UpdateParentPath(newPath path.Path) error { + newParent, err := path.GetDriveFolderPath(newPath) + if err != nil { + return errors.Wrapf(err, "making drive path from %s", newPath) + } + + i.ParentPath = newParent + + return nil +} diff --git a/src/pkg/backup/details/details_test.go b/src/pkg/backup/details/details_test.go index bd764ae6b..af363317f 100644 --- a/src/pkg/backup/details/details_test.go +++ b/src/pkg/backup/details/details_test.go @@ -10,6 +10,7 @@ import ( "github.com/alcionai/corso/src/internal/common" "github.com/alcionai/corso/src/pkg/backup/details" + "github.com/alcionai/corso/src/pkg/path" ) // ------------------------------------------------------------ @@ -411,3 +412,182 @@ func (suite *DetailsUnitSuite) TestDetails_AddFoldersDifferentServices() { }) } } + +func makeItemPath( + t *testing.T, + service path.ServiceType, + category path.CategoryType, + tenant, resourceOwner string, + elems []string, +) path.Path { + t.Helper() + + p, err := path.Builder{}.Append(elems...). + ToDataLayerPath( + tenant, + resourceOwner, + service, + category, + true, + ) + require.NoError(t, err) + + return p +} + +func (suite *DetailsUnitSuite) TestUpdateItem() { + const ( + tenant = "a-tenant" + resourceOwner = "a-user" + driveID = "abcd" + folder1 = "f1" + folder2 = "f2" + item = "hello.txt" + ) + + // Making both OneDrive paths is alright because right now they're the same as + // SharePoint path and there's no extra validation. + newOneDrivePath := makeItemPath( + suite.T(), + path.OneDriveService, + path.FilesCategory, + tenant, + resourceOwner, + []string{ + "drives", + driveID, + "root:", + folder2, + item, + }, + ) + badOneDrivePath := makeItemPath( + suite.T(), + path.OneDriveService, + path.FilesCategory, + tenant, + resourceOwner, + []string{item}, + ) + + table := []struct { + name string + input details.ItemInfo + newPath path.Path + errCheck assert.ErrorAssertionFunc + expectedItem details.ItemInfo + }{ + { + name: "ExchangeEventNoChange", + input: details.ItemInfo{ + Exchange: &details.ExchangeInfo{ + ItemType: details.ExchangeEvent, + }, + }, + errCheck: assert.NoError, + expectedItem: details.ItemInfo{ + Exchange: &details.ExchangeInfo{ + ItemType: details.ExchangeEvent, + }, + }, + }, + { + name: "ExchangeContactNoChange", + input: details.ItemInfo{ + Exchange: &details.ExchangeInfo{ + ItemType: details.ExchangeContact, + }, + }, + errCheck: assert.NoError, + expectedItem: details.ItemInfo{ + Exchange: &details.ExchangeInfo{ + ItemType: details.ExchangeContact, + }, + }, + }, + { + name: "ExchangeMailNoChange", + input: details.ItemInfo{ + Exchange: &details.ExchangeInfo{ + ItemType: details.ExchangeMail, + }, + }, + errCheck: assert.NoError, + expectedItem: details.ItemInfo{ + Exchange: &details.ExchangeInfo{ + ItemType: details.ExchangeMail, + }, + }, + }, + { + name: "OneDrive", + input: details.ItemInfo{ + OneDrive: &details.OneDriveInfo{ + ItemType: details.OneDriveItem, + ParentPath: folder1, + }, + }, + newPath: newOneDrivePath, + errCheck: assert.NoError, + expectedItem: details.ItemInfo{ + OneDrive: &details.OneDriveInfo{ + ItemType: details.OneDriveItem, + ParentPath: folder2, + }, + }, + }, + { + name: "SharePoint", + input: details.ItemInfo{ + SharePoint: &details.SharePointInfo{ + ItemType: details.SharePointItem, + ParentPath: folder1, + }, + }, + newPath: newOneDrivePath, + errCheck: assert.NoError, + expectedItem: details.ItemInfo{ + SharePoint: &details.SharePointInfo{ + ItemType: details.SharePointItem, + ParentPath: folder2, + }, + }, + }, + { + name: "OneDriveBadPath", + input: details.ItemInfo{ + OneDrive: &details.OneDriveInfo{ + ItemType: details.OneDriveItem, + ParentPath: folder1, + }, + }, + newPath: badOneDrivePath, + errCheck: assert.Error, + }, + { + name: "SharePointBadPath", + input: details.ItemInfo{ + SharePoint: &details.SharePointInfo{ + ItemType: details.SharePointItem, + ParentPath: folder1, + }, + }, + newPath: badOneDrivePath, + errCheck: assert.Error, + }, + } + + for _, test := range table { + suite.T().Run(test.name, func(t *testing.T) { + item := test.input + err := details.UpdateItem(&item, test.newPath) + test.errCheck(t, err) + + if err != nil { + return + } + + assert.Equal(t, test.expectedItem, item) + }) + } +}