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:
parent
ac2a299c51
commit
8acff1ad93
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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},
|
||||
}
|
||||
|
||||
|
||||
@ -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{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user