fix sharepoint library folder selection (#2962)

Bugfix:
Sharepoint LibraryFolder scopes always return
zero matches in filtering with a prefix due to the
path not having the drive root prefix truncated, as is
expected of onedrive-based storage paths.

---

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

- [x]  Yes, it's included

#### Type of change

- [x] 🐛 Bugfix

#### Test Plan

- [x] 💪 Manual
- [x]  Unit test
This commit is contained in:
Keepers 2023-03-27 19:21:20 -06:00 committed by GitHub
parent ac2a299c51
commit 8acff1ad93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 45 additions and 23 deletions

View File

@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Handle calendar events with no body.
- Items not being deleted if they were created and deleted during item enumeration of a OneDrive backup.
- Enable compression for all data uploaded by kopia.
- SharePoint --folder selectors correctly return items.
## [v0.6.1] (beta) - 2023-03-21
@ -33,8 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Known Issues
- Owner (Full control) or empty (Restricted View) roles cannot be restored for OneDrive
- OneDrive will not do an incremental backup if permissions are being backed up.
### Known Issues
- SharePoint --folder selection in details and restore always return "no items match the specified selectors".
- Event instance exceptions (ie: changes to a single event within a recurring series) are not backed up.
## [v0.5.0] (beta) - 2023-03-13

View File

@ -342,6 +342,8 @@ func runDetailsExchangeCmd(
return nil, errors.Wrap(errs.Failure(), "Failed to get backup details in the repository")
}
ctx = clues.Add(ctx, "details_entries", len(d.Entries))
if !skipReduce {
sel := utils.IncludeExchangeRestoreDataSelectors(opts)
utils.FilterExchangeRestoreInfoSelectors(sel, opts)

View File

@ -281,6 +281,8 @@ func runDetailsOneDriveCmd(
return nil, errors.Wrap(errs.Failure(), "Failed to get backup details in the repository")
}
ctx = clues.Add(ctx, "details_entries", len(d.Entries))
if !skipReduce {
sel := utils.IncludeOneDriveRestoreDataSelectors(opts)
utils.FilterOneDriveRestoreInfoSelectors(sel, opts)

View File

@ -389,6 +389,8 @@ func runDetailsSharePointCmd(
return nil, errors.Wrap(errs.Failure(), "Failed to get backup details in the repository")
}
ctx = clues.Add(ctx, "details_entries", len(d.Entries))
if !skipReduce {
sel := utils.IncludeSharePointRestoreDataSelectors(opts)
utils.FilterSharePointRestoreInfoSelectors(sel, opts)

View File

@ -196,6 +196,7 @@ func (op *RestoreOperation) do(
ctx = clues.Add(
ctx,
"resource_owner", bup.Selector.DiscreteOwner,
"details_entries", len(deets.Entries),
"details_paths", len(paths),
"backup_snapshot_id", bup.SnapshotID,
"backup_version", bup.Version)

View File

@ -503,8 +503,9 @@ func (c sharePointCategory) pathValues(
ent details.DetailsEntry,
) (map[categorizer][]string, error) {
var (
folderCat, itemCat categorizer
itemName = repo.Item()
folderCat, itemCat categorizer
itemName = repo.Item()
dropDriveFolderPrefix bool
)
switch c {
@ -513,6 +514,7 @@ func (c sharePointCategory) pathValues(
return nil, clues.New("no SharePoint ItemInfo in details")
}
dropDriveFolderPrefix = true
folderCat, itemCat = SharePointLibraryFolder, SharePointLibraryItem
itemName = ent.SharePoint.ItemName
@ -526,8 +528,14 @@ func (c sharePointCategory) pathValues(
return nil, clues.New("unrecognized sharePointCategory").With("category", c)
}
rFld := repo.Folder(false)
if dropDriveFolderPrefix {
// like onedrive, ignore `drives/<driveID>/root:` for library folder comparison
rFld = path.Builder{}.Append(repo.Folders()...).PopFront().PopFront().PopFront().String()
}
result := map[categorizer][]string{
folderCat: {repo.Folder(false)},
folderCat: {rFld},
itemCat: {itemName, ent.ShortRef},
}

View File

@ -199,13 +199,14 @@ func (suite *SharePointSelectorSuite) TestToSharePointRestore() {
func (suite *SharePointSelectorSuite) TestSharePointRestore_Reduce() {
var (
pairAC = "folderA/folderC"
pairGH = "folderG/folderH"
item = stubRepoRef(path.SharePointService, path.LibrariesCategory, "sid", "folderA/folderB", "item")
item2 = stubRepoRef(path.SharePointService, path.LibrariesCategory, "sid", pairAC, "item2")
item3 = stubRepoRef(path.SharePointService, path.LibrariesCategory, "sid", "folderD/folderE", "item3")
item4 = stubRepoRef(path.SharePointService, path.PagesCategory, "sid", pairGH, "item4")
item5 = stubRepoRef(path.SharePointService, path.PagesCategory, "sid", pairGH, "item5")
drivePfx = "drive/drive!id/root:/"
pairAC = "folderA/folderC"
pairGH = "folderG/folderH"
item = stubRepoRef(path.SharePointService, path.LibrariesCategory, "sid", drivePfx+"folderA/folderB", "item")
item2 = stubRepoRef(path.SharePointService, path.LibrariesCategory, "sid", drivePfx+pairAC, "item2")
item3 = stubRepoRef(path.SharePointService, path.LibrariesCategory, "sid", drivePfx+"folderD/folderE", "item3")
item4 = stubRepoRef(path.SharePointService, path.PagesCategory, "sid", pairGH, "item4")
item5 = stubRepoRef(path.SharePointService, path.PagesCategory, "sid", pairGH, "item5")
)
deets := &details.Details{
@ -327,26 +328,32 @@ func (suite *SharePointSelectorSuite) TestSharePointRestore_Reduce() {
}
func (suite *SharePointSelectorSuite) TestSharePointCategory_PathValues() {
itemName := "item"
shortRef := "short"
elems := []string{"dir1", "dir2", itemName + "-id"}
var (
itemName = "item"
shortRef = "short"
driveElems = []string{"drive", "drive!id", "root:", "dir1", "dir2", itemName + "-id"}
elems = []string{"dir1", "dir2", itemName + "-id"}
)
table := []struct {
name string
sc sharePointCategory
expected map[categorizer][]string
name string
sc sharePointCategory
pathElems []string
expected map[categorizer][]string
}{
{
name: "SharePoint Libraries",
sc: SharePointLibraryItem,
name: "SharePoint Libraries",
sc: SharePointLibraryItem,
pathElems: driveElems,
expected: map[categorizer][]string{
SharePointLibraryFolder: {"dir1/dir2"},
SharePointLibraryItem: {itemName, shortRef},
},
},
{
name: "SharePoint Lists",
sc: SharePointListItem,
name: "SharePoint Lists",
sc: SharePointListItem,
pathElems: elems,
expected: map[categorizer][]string{
SharePointList: {"dir1/dir2"},
SharePointListItem: {"item-id", shortRef},
@ -364,7 +371,7 @@ func (suite *SharePointSelectorSuite) TestSharePointCategory_PathValues() {
path.SharePointService,
test.sc.PathType(),
true,
elems...)
test.pathElems...)
require.NoError(t, err, clues.ToCore(err))
ent := details.DetailsEntry{