select list by name while export and restore (#4999)

selects list by name while export and restore

#### Does this PR need a docs update or release note?
- [x]  No

#### Type of change

<!--- Please check the type of change your PR introduces: --->
- [x] 🧹 Tech Debt/Cleanup

#### Issue(s)
#4754 
#### Test Plan

<!-- How will this be tested prior to merging.-->
- [x] 💪 Manual
- [x]  Unit test
- [x] 💚 E2E
This commit is contained in:
Hitesh Pattanayak 2024-01-12 21:24:58 +05:30 committed by GitHub
parent 985220562c
commit e16d4c5bd9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 242 additions and 198 deletions

View File

@ -60,8 +60,7 @@ func (suite *SharePointUnitSuite) TestAddSharePointCommands() {
"--" + flags.FileCreatedBeforeFN, flagsTD.FileCreatedBeforeInput,
"--" + flags.FileModifiedAfterFN, flagsTD.FileModifiedAfterInput,
"--" + flags.FileModifiedBeforeFN, flagsTD.FileModifiedBeforeInput,
"--" + flags.ListItemFN, flagsTD.FlgInputs(flagsTD.ListItemInput),
"--" + flags.ListFolderFN, flagsTD.FlgInputs(flagsTD.ListFolderInput),
"--" + flags.ListFN, flagsTD.FlgInputs(flagsTD.ListsInput),
"--" + flags.PageFN, flagsTD.FlgInputs(flagsTD.PageInput),
"--" + flags.PageFolderFN, flagsTD.FlgInputs(flagsTD.PageFolderInput),
"--" + flags.FormatFN, flagsTD.FormatType,
@ -88,8 +87,7 @@ func (suite *SharePointUnitSuite) TestAddSharePointCommands() {
assert.Equal(t, flagsTD.FileCreatedBeforeInput, opts.FileCreatedBefore)
assert.Equal(t, flagsTD.FileModifiedAfterInput, opts.FileModifiedAfter)
assert.Equal(t, flagsTD.FileModifiedBeforeInput, opts.FileModifiedBefore)
assert.ElementsMatch(t, flagsTD.ListItemInput, opts.ListItem)
assert.ElementsMatch(t, flagsTD.ListFolderInput, opts.ListFolder)
assert.ElementsMatch(t, flagsTD.ListsInput, opts.Lists)
assert.ElementsMatch(t, flagsTD.PageInput, opts.Page)
assert.ElementsMatch(t, flagsTD.PageFolderInput, opts.PageFolder)
assert.Equal(t, flagsTD.Archive, opts.ExportCfg.Archive)

View File

@ -12,8 +12,7 @@ const (
const (
LibraryFN = "library"
ListFolderFN = "list"
ListItemFN = "list-item"
ListFN = "list"
PageFolderFN = "page-folder"
PageFN = "page"
SiteFN = "site" // site only accepts WebURL values
@ -22,8 +21,7 @@ const (
var (
LibraryFV string
ListFolderFV []string
ListItemFV []string
ListFV []string
PageFolderFV []string
PageFV []string
SiteIDFV []string
@ -67,17 +65,11 @@ func AddSharePointDetailsAndRestoreFlags(cmd *cobra.Command) {
"Select files modified before this datetime.")
// lists
fs.StringSliceVar(
&ListFolderFV,
ListFolderFN, nil,
&ListFV,
ListFN, nil,
"Select lists by name; accepts '"+Wildcard+"' to select all lists.")
cobra.CheckErr(fs.MarkHidden(ListFolderFN))
fs.StringSliceVar(
&ListItemFV,
ListItemFN, nil,
"Select lists by item name; accepts '"+Wildcard+"' to select all lists.")
cobra.CheckErr(fs.MarkHidden(ListItemFN))
cobra.CheckErr(fs.MarkHidden(ListFN))
// pages

View File

@ -59,8 +59,7 @@ var (
FileModifiedAfterInput = "fileModifiedAfter"
FileModifiedBeforeInput = "fileModifiedBefore"
ListFolderInput = []string{"listFolder1", "listFolder2"}
ListItemInput = []string{"listItem1", "listItem2"}
ListsInput = []string{"listName1", "listName2"}
PageFolderInput = []string{"pageFolder1", "pageFolder2"}
PageInput = []string{"page1", "page2"}

View File

@ -60,8 +60,7 @@ func (suite *GroupsUnitSuite) TestAddGroupsCommands() {
"--" + flags.FileCreatedBeforeFN, flagsTD.FileCreatedBeforeInput,
"--" + flags.FileModifiedAfterFN, flagsTD.FileModifiedAfterInput,
"--" + flags.FileModifiedBeforeFN, flagsTD.FileModifiedBeforeInput,
"--" + flags.ListItemFN, flagsTD.FlgInputs(flagsTD.ListItemInput),
"--" + flags.ListFolderFN, flagsTD.FlgInputs(flagsTD.ListFolderInput),
"--" + flags.ListFN, flagsTD.FlgInputs(flagsTD.ListsInput),
"--" + flags.PageFN, flagsTD.FlgInputs(flagsTD.PageInput),
"--" + flags.PageFolderFN, flagsTD.FlgInputs(flagsTD.PageFolderInput),
"--" + flags.CollisionsFN, flagsTD.Collisions,
@ -92,6 +91,7 @@ func (suite *GroupsUnitSuite) TestAddGroupsCommands() {
assert.Equal(t, flagsTD.FileModifiedBeforeInput, opts.FileModifiedBefore)
assert.Equal(t, flagsTD.Collisions, opts.RestoreCfg.Collisions)
assert.Equal(t, flagsTD.Destination, opts.RestoreCfg.Destination)
assert.ElementsMatch(t, flagsTD.ListsInput, opts.Lists)
// assert.Equal(t, flagsTD.ToResource, opts.RestoreCfg.ProtectedResource)
assert.True(t, flags.NoPermissionsFV)
flagsTD.AssertProviderFlags(t, cmd)

View File

@ -59,8 +59,7 @@ func (suite *SharePointUnitSuite) TestAddSharePointCommands() {
"--" + flags.FileCreatedBeforeFN, flagsTD.FileCreatedBeforeInput,
"--" + flags.FileModifiedAfterFN, flagsTD.FileModifiedAfterInput,
"--" + flags.FileModifiedBeforeFN, flagsTD.FileModifiedBeforeInput,
"--" + flags.ListItemFN, flagsTD.FlgInputs(flagsTD.ListItemInput),
"--" + flags.ListFolderFN, flagsTD.FlgInputs(flagsTD.ListFolderInput),
"--" + flags.ListFN, flagsTD.FlgInputs(flagsTD.ListsInput),
"--" + flags.PageFN, flagsTD.FlgInputs(flagsTD.PageInput),
"--" + flags.PageFolderFN, flagsTD.FlgInputs(flagsTD.PageFolderInput),
"--" + flags.CollisionsFN, flagsTD.Collisions,
@ -89,8 +88,7 @@ func (suite *SharePointUnitSuite) TestAddSharePointCommands() {
assert.Equal(t, flagsTD.FileCreatedBeforeInput, opts.FileCreatedBefore)
assert.Equal(t, flagsTD.FileModifiedAfterInput, opts.FileModifiedAfter)
assert.Equal(t, flagsTD.FileModifiedBeforeInput, opts.FileModifiedBefore)
assert.ElementsMatch(t, flagsTD.ListItemInput, opts.ListItem)
assert.ElementsMatch(t, flagsTD.ListFolderInput, opts.ListFolder)
assert.ElementsMatch(t, flagsTD.ListsInput, opts.Lists)
assert.ElementsMatch(t, flagsTD.PageInput, opts.Page)
assert.ElementsMatch(t, flagsTD.PageFolderInput, opts.PageFolder)
assert.Equal(t, flagsTD.Collisions, opts.RestoreCfg.Collisions)

View File

@ -1,8 +1,12 @@
package utils
import (
"errors"
"strconv"
"github.com/alcionai/clues"
"github.com/alcionai/corso/src/cli/flags"
"github.com/alcionai/corso/src/pkg/dttm"
"github.com/alcionai/corso/src/pkg/path"
"github.com/alcionai/corso/src/pkg/selectors"
@ -39,3 +43,51 @@ func trimFolderSlash(folders []string) []string {
return res
}
func validateCommonTimeFlags(opts any) error {
timeFlags := []string{
flags.FileCreatedAfterFN,
flags.FileCreatedBeforeFN,
flags.FileModifiedAfterFN,
flags.FileModifiedBeforeFN,
}
isFlagPopulated := func(opts any, flag string) bool {
switch opts := opts.(type) {
case GroupsOpts:
_, ok := opts.Populated[flag]
return ok
case SharePointOpts:
_, ok := opts.Populated[flag]
return ok
default:
return false
}
}
getTimeField := func(opts any, flag string) (string, error) {
switch opts := opts.(type) {
case GroupsOpts:
return opts.GetFileTimeField(flag), nil
case SharePointOpts:
return opts.GetFileTimeField(flag), nil
default:
return "", errors.New("unsupported type")
}
}
for _, flag := range timeFlags {
if populated := isFlagPopulated(opts, flag); populated {
timeField, err := getTimeField(opts, flag)
if err != nil {
return err
}
if !IsValidTimeFormat(timeField) {
return clues.New("invalid time format for " + flag)
}
}
}
return nil
}

View File

@ -32,8 +32,7 @@ type GroupsOpts struct {
FileModifiedAfter string
FileModifiedBefore string
ListFolder []string
ListItem []string
Lists []string
PageFolder []string
Page []string
@ -44,6 +43,21 @@ type GroupsOpts struct {
Populated flags.PopulatedFlags
}
func (g GroupsOpts) GetFileTimeField(flag string) string {
switch flag {
case flags.FileCreatedAfterFN:
return g.FileCreatedAfter
case flags.FileCreatedBeforeFN:
return g.FileCreatedBefore
case flags.FileModifiedAfterFN:
return g.FileModifiedAfter
case flags.FileModifiedBeforeFN:
return g.FileModifiedBefore
default:
return ""
}
}
func GroupsAllowedCategories() map[string]struct{} {
return map[string]struct{}{
flags.DataLibraries: {},
@ -93,8 +107,7 @@ func MakeGroupsOpts(cmd *cobra.Command) GroupsOpts {
MessageLastReplyAfter: flags.MessageLastReplyAfterFV,
MessageLastReplyBefore: flags.MessageLastReplyBeforeFV,
ListFolder: flags.ListFolderFV,
ListItem: flags.ListItemFV,
Lists: flags.ListFV,
Page: flags.PageFV,
PageFolder: flags.PageFolderFV,
@ -126,22 +139,6 @@ func ValidateGroupsRestoreFlags(backupID string, opts GroupsOpts, isRestore bool
}
}
if _, ok := opts.Populated[flags.FileCreatedAfterFN]; ok && !IsValidTimeFormat(opts.FileCreatedAfter) {
return clues.New("invalid time format for " + flags.FileCreatedAfterFN)
}
if _, ok := opts.Populated[flags.FileCreatedBeforeFN]; ok && !IsValidTimeFormat(opts.FileCreatedBefore) {
return clues.New("invalid time format for " + flags.FileCreatedBeforeFN)
}
if _, ok := opts.Populated[flags.FileModifiedAfterFN]; ok && !IsValidTimeFormat(opts.FileModifiedAfter) {
return clues.New("invalid time format for " + flags.FileModifiedAfterFN)
}
if _, ok := opts.Populated[flags.FileModifiedBeforeFN]; ok && !IsValidTimeFormat(opts.FileModifiedBefore) {
return clues.New("invalid time format for " + flags.FileModifiedBeforeFN)
}
if _, ok := opts.Populated[flags.MessageCreatedAfterFN]; ok && !IsValidTimeFormat(opts.MessageCreatedAfter) {
return clues.New("invalid time format for " + flags.MessageCreatedAfterFN)
}
@ -158,7 +155,7 @@ func ValidateGroupsRestoreFlags(backupID string, opts GroupsOpts, isRestore bool
return clues.New("invalid time format for " + flags.MessageLastReplyBeforeFN)
}
return nil
return validateCommonTimeFlags(opts)
}
// AddGroupsFilter adds the scope of the provided values to the selector's
@ -181,7 +178,7 @@ func IncludeGroupsRestoreDataSelectors(ctx context.Context, opts GroupsOpts) *se
var (
groups = opts.Groups
folderPaths, fileNames = len(opts.FolderPath), len(opts.FileName)
listFolders, listItems = len(opts.ListFolder), len(opts.ListItem)
lists = len(opts.Lists)
pageFolders, pageItems = len(opts.PageFolder), len(opts.Page)
chans, chanMsgs = len(opts.Channels), len(opts.Messages)
convs, convPosts = len(opts.Conversations), len(opts.Posts)
@ -194,7 +191,7 @@ func IncludeGroupsRestoreDataSelectors(ctx context.Context, opts GroupsOpts) *se
sel := selectors.NewGroupsRestore(groups)
if folderPaths+fileNames+
listFolders+listItems+
lists+
pageFolders+pageItems+
chans+chanMsgs+
convs+convPosts == 0 {
@ -204,58 +201,43 @@ func IncludeGroupsRestoreDataSelectors(ctx context.Context, opts GroupsOpts) *se
// sharepoint site selectors
if folderPaths+fileNames+
listFolders+listItems+
pageFolders+pageItems > 0 {
if folderPaths+fileNames > 0 {
if fileNames == 0 {
opts.FileName = selectors.Any()
}
opts.FolderPath = trimFolderSlash(opts.FolderPath)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.FolderPath)
if len(containsFolders) > 0 {
sel.Include(sel.LibraryItems(containsFolders, opts.FileName))
}
if len(prefixFolders) > 0 {
sel.Include(sel.LibraryItems(prefixFolders, opts.FileName, selectors.PrefixMatch()))
}
if folderPaths+fileNames > 0 {
if fileNames == 0 {
opts.FileName = selectors.Any()
}
if listFolders+listItems > 0 {
if listItems == 0 {
opts.ListItem = selectors.Any()
}
opts.FolderPath = trimFolderSlash(opts.FolderPath)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.FolderPath)
opts.ListFolder = trimFolderSlash(opts.ListFolder)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.ListFolder)
if len(containsFolders) > 0 {
sel.Include(sel.ListItems(containsFolders, opts.ListItem))
}
if len(prefixFolders) > 0 {
sel.Include(sel.ListItems(prefixFolders, opts.ListItem, selectors.PrefixMatch()))
}
if len(containsFolders) > 0 {
sel.Include(sel.LibraryItems(containsFolders, opts.FileName))
}
if pageFolders+pageItems > 0 {
if pageItems == 0 {
opts.Page = selectors.Any()
}
if len(prefixFolders) > 0 {
sel.Include(sel.LibraryItems(prefixFolders, opts.FileName, selectors.PrefixMatch()))
}
}
opts.PageFolder = trimFolderSlash(opts.PageFolder)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.PageFolder)
if lists > 0 {
opts.Lists = trimFolderSlash(opts.Lists)
sel.Include(sel.ListItems(opts.Lists, opts.Lists, selectors.StrictEqualMatch()))
sel.Configure(selectors.Config{OnlyMatchItemNames: true})
}
if len(containsFolders) > 0 {
sel.Include(sel.PageItems(containsFolders, opts.Page))
}
if pageFolders+pageItems > 0 {
if pageItems == 0 {
opts.Page = selectors.Any()
}
if len(prefixFolders) > 0 {
sel.Include(sel.PageItems(prefixFolders, opts.Page, selectors.PrefixMatch()))
}
opts.PageFolder = trimFolderSlash(opts.PageFolder)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.PageFolder)
if len(containsFolders) > 0 {
sel.Include(sel.PageItems(containsFolders, opts.Page))
}
if len(prefixFolders) > 0 {
sel.Include(sel.PageItems(prefixFolders, opts.Page, selectors.PrefixMatch()))
}
}

View File

@ -30,6 +30,7 @@ func (suite *GroupsUtilsSuite) TestIncludeGroupsRestoreDataSelectors() {
containsOnly = []string{"contains"}
prefixOnly = []string{"/prefix"}
containsAndPrefix = []string{"contains", "/prefix"}
listNames = []string{"list-name1"}
onlySlash = []string{string(path.PathSeparator)}
)
@ -91,29 +92,12 @@ func (suite *GroupsUtilsSuite) TestIncludeGroupsRestoreDataSelectors() {
expectIncludeLen: 2,
},
{
name: "list contains",
name: "list names",
opts: utils.GroupsOpts{
FileName: empty,
FolderPath: empty,
ListItem: empty,
ListFolder: containsOnly,
Lists: listNames,
},
expectIncludeLen: 1,
},
{
name: "list prefixes",
opts: utils.GroupsOpts{
ListFolder: prefixOnly,
},
expectIncludeLen: 1,
},
{
name: "list prefixes and contains",
opts: utils.GroupsOpts{
ListFolder: containsAndPrefix,
},
expectIncludeLen: 2,
},
{
name: "Page Folder",
opts: utils.GroupsOpts{

View File

@ -25,8 +25,7 @@ type SharePointOpts struct {
FileModifiedAfter string
FileModifiedBefore string
ListFolder []string
ListItem []string
Lists []string
PageFolder []string
Page []string
@ -37,6 +36,21 @@ type SharePointOpts struct {
Populated flags.PopulatedFlags
}
func (s SharePointOpts) GetFileTimeField(flag string) string {
switch flag {
case flags.FileCreatedAfterFN:
return s.FileCreatedAfter
case flags.FileCreatedBeforeFN:
return s.FileCreatedBefore
case flags.FileModifiedAfterFN:
return s.FileModifiedAfter
case flags.FileModifiedBeforeFN:
return s.FileModifiedBefore
default:
return ""
}
}
func MakeSharePointOpts(cmd *cobra.Command) SharePointOpts {
return SharePointOpts{
SiteID: flags.SiteIDFV,
@ -50,8 +64,7 @@ func MakeSharePointOpts(cmd *cobra.Command) SharePointOpts {
FileModifiedAfter: flags.FileModifiedAfterFV,
FileModifiedBefore: flags.FileModifiedBeforeFV,
ListFolder: flags.ListFolderFV,
ListItem: flags.ListItemFV,
Lists: flags.ListFV,
Page: flags.PageFV,
PageFolder: flags.PageFolderFV,
@ -108,23 +121,7 @@ func ValidateSharePointRestoreFlags(backupID string, opts SharePointOpts) error
}
}
if _, ok := opts.Populated[flags.FileCreatedAfterFN]; ok && !IsValidTimeFormat(opts.FileCreatedAfter) {
return clues.New("invalid time format for " + flags.FileCreatedAfterFN)
}
if _, ok := opts.Populated[flags.FileCreatedBeforeFN]; ok && !IsValidTimeFormat(opts.FileCreatedBefore) {
return clues.New("invalid time format for " + flags.FileCreatedBeforeFN)
}
if _, ok := opts.Populated[flags.FileModifiedAfterFN]; ok && !IsValidTimeFormat(opts.FileModifiedAfter) {
return clues.New("invalid time format for " + flags.FileModifiedAfterFN)
}
if _, ok := opts.Populated[flags.FileModifiedBeforeFN]; ok && !IsValidTimeFormat(opts.FileModifiedBefore) {
return clues.New("invalid time format for " + flags.FileModifiedBeforeFN)
}
return nil
return validateCommonTimeFlags(opts)
}
// AddSharePointInfo adds the scope of the provided values to the selector's
@ -146,24 +143,24 @@ func AddSharePointInfo(
func IncludeSharePointRestoreDataSelectors(ctx context.Context, opts SharePointOpts) *selectors.SharePointRestore {
sites := opts.SiteID
lfp, lfn := len(opts.FolderPath), len(opts.FileName)
ls, lwu := len(opts.SiteID), len(opts.WebURL)
slp, sli := len(opts.ListFolder), len(opts.ListItem)
pf, pi := len(opts.PageFolder), len(opts.Page)
folderPaths, fileNames := len(opts.FolderPath), len(opts.FileName)
siteIDs, webUrls := len(opts.SiteID), len(opts.WebURL)
lists := len(opts.Lists)
pageFolders, pageItems := len(opts.PageFolder), len(opts.Page)
if ls == 0 {
if siteIDs == 0 {
sites = selectors.Any()
}
sel := selectors.NewSharePointRestore(sites)
if lfp+lfn+lwu+slp+sli+pf+pi == 0 {
if folderPaths+fileNames+webUrls+lists+pageFolders+pageItems == 0 {
sel.Include(sel.AllData())
return sel
}
if lfp+lfn > 0 {
if lfn == 0 {
if folderPaths+fileNames > 0 {
if fileNames == 0 {
opts.FileName = selectors.Any()
}
@ -179,25 +176,14 @@ func IncludeSharePointRestoreDataSelectors(ctx context.Context, opts SharePointO
}
}
if slp+sli > 0 {
if sli == 0 {
opts.ListItem = selectors.Any()
}
opts.ListFolder = trimFolderSlash(opts.ListFolder)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.ListFolder)
if len(containsFolders) > 0 {
sel.Include(sel.ListItems(containsFolders, opts.ListItem))
}
if len(prefixFolders) > 0 {
sel.Include(sel.ListItems(prefixFolders, opts.ListItem, selectors.PrefixMatch()))
}
if lists > 0 {
opts.Lists = trimFolderSlash(opts.Lists)
sel.Include(sel.ListItems(opts.Lists, opts.Lists, selectors.StrictEqualMatch()))
sel.Configure(selectors.Config{OnlyMatchItemNames: true})
}
if pf+pi > 0 {
if pi == 0 {
if pageFolders+pageItems > 0 {
if pageItems == 0 {
opts.Page = selectors.Any()
}
@ -213,7 +199,7 @@ func IncludeSharePointRestoreDataSelectors(ctx context.Context, opts SharePointO
}
}
if lwu > 0 {
if webUrls > 0 {
urls := make([]string, 0, len(opts.WebURL))
for _, wu := range opts.WebURL {

View File

@ -31,6 +31,7 @@ func (suite *SharePointUtilsSuite) TestIncludeSharePointRestoreDataSelectors() {
multi = []string{"more", "than", "one"}
containsOnly = []string{"contains"}
prefixOnly = []string{"/prefix"}
listNames = []string{"list-name1"}
containsAndPrefix = []string{"contains", "/prefix"}
onlySlash = []string{string(path.PathSeparator)}
)
@ -60,8 +61,7 @@ func (suite *SharePointUtilsSuite) TestIncludeSharePointRestoreDataSelectors() {
opts: utils.SharePointOpts{
FileName: single,
FolderPath: single,
ListItem: single,
ListFolder: single,
Lists: single,
SiteID: single,
WebURL: single,
},
@ -108,31 +108,12 @@ func (suite *SharePointUtilsSuite) TestIncludeSharePointRestoreDataSelectors() {
expectIncludeLen: 2,
},
{
name: "list contains",
name: "list names",
opts: utils.SharePointOpts{
FileName: empty,
FolderPath: empty,
ListItem: empty,
ListFolder: containsOnly,
SiteID: empty,
WebURL: empty,
Lists: listNames,
},
expectIncludeLen: 1,
},
{
name: "list prefixes",
opts: utils.SharePointOpts{
ListFolder: prefixOnly,
},
expectIncludeLen: 1,
},
{
name: "list prefixes and contains",
opts: utils.SharePointOpts{
ListFolder: containsAndPrefix,
},
expectIncludeLen: 2,
},
{
name: "weburl contains",
opts: utils.SharePointOpts{

View File

@ -263,12 +263,9 @@ func (s *sharePoint) AllData() []SharePointScope {
// If any slice contains selectors.None, that slice is reduced to [selectors.None]
// Any empty slice defaults to [selectors.None]
func (s *sharePoint) Lists(lists []string, opts ...option) []SharePointScope {
var (
scopes = []SharePointScope{}
os = append([]option{pathComparator()}, opts...)
)
scopes := []SharePointScope{}
scopes = append(scopes, makeScope[SharePointScope](SharePointList, lists, os...))
scopes = append(scopes, makeScope[SharePointScope](SharePointList, lists, opts...))
return scopes
}
@ -526,6 +523,7 @@ func (c sharePointCategory) pathValues(
folderCat, itemCat categorizer
itemID string
rFld string
itemName string
)
switch c {
@ -536,14 +534,22 @@ func (c sharePointCategory) pathValues(
folderCat, itemCat = SharePointLibraryFolder, SharePointLibraryItem
rFld = ent.SharePoint.ParentPath
itemName = ent.ItemInfo.SharePoint.ItemName
case SharePointList, SharePointListItem:
folderCat, itemCat = SharePointList, SharePointListItem
rFld = ent.LocationRef
if cfg.OnlyMatchItemNames {
rFld = ent.ItemInfo.SharePoint.List.Name
}
itemName = ent.ItemInfo.SharePoint.List.Name
case SharePointPage, SharePointPageFolder:
folderCat, itemCat = SharePointPageFolder, SharePointPage
rFld = ent.LocationRef
itemName = ent.ItemInfo.SharePoint.ItemName
default:
return nil, clues.New("unrecognized sharePointCategory").With("category", c)
@ -555,7 +561,7 @@ func (c sharePointCategory) pathValues(
}
if cfg.OnlyMatchItemNames {
item = ent.ItemInfo.SharePoint.ItemName
item = itemName
}
result := map[categorizer][]string{
@ -640,7 +646,11 @@ func (s SharePointScope) set(cat sharePointCategory, v []string, opts ...option)
os := []option{}
switch cat {
case SharePointLibraryFolder, SharePointList, SharePointPage:
// SharePointList does not apply here because:
// 1.there is no nested folders -> there cannot be lists within other lists
// 2. list itself is the item -> so container and item are the same
// since there is no path involved here, we do not need any path filters.
case SharePointLibraryFolder, SharePointPage:
os = append(os, pathComparator())
}

View File

@ -170,6 +170,8 @@ func (suite *SharePointSelectorSuite) TestSharePointRestore_Reduce() {
itemElems3 = []string{"folderD", "folderE"}
pairAC = "folderA/folderC"
pairGH = "folderG/folderH"
listID1 = "list1"
listID2 = "list2"
item = toRR(
path.LibrariesCategory,
"sid",
@ -187,6 +189,8 @@ func (suite *SharePointSelectorSuite) TestSharePointRestore_Reduce() {
"item3")
item4 = stubRepoRef(path.SharePointService, path.PagesCategory, "sid", pairGH, "item4")
item5 = stubRepoRef(path.SharePointService, path.PagesCategory, "sid", pairGH, "item5")
list1 = stubRepoRef(path.SharePointService, path.ListsCategory, "sid", listID1, listID1)
list2 = stubRepoRef(path.SharePointService, path.ListsCategory, "sid", listID2, listID2)
)
deets := &details.Details{
@ -252,6 +256,34 @@ func (suite *SharePointSelectorSuite) TestSharePointRestore_Reduce() {
},
},
},
{
RepoRef: list1,
LocationRef: listID1,
ItemRef: "list1",
ItemInfo: details.ItemInfo{
SharePoint: &details.SharePointInfo{
ItemType: details.SharePointList,
List: &details.ListInfo{
Name: "listName1",
},
ParentPath: strings.Join([]string{listID1}, "/"),
},
},
},
{
RepoRef: list2,
LocationRef: listID2,
ItemRef: "list2",
ItemInfo: details.ItemInfo{
SharePoint: &details.SharePointInfo{
ItemType: details.SharePointList,
List: &details.ListInfo{
Name: "listName2",
},
ParentPath: strings.Join([]string{listID2}, "/"),
},
},
},
},
},
}
@ -273,7 +305,7 @@ func (suite *SharePointSelectorSuite) TestSharePointRestore_Reduce() {
odr.Include(odr.AllData())
return odr
},
expect: arr(item, item2, item3, item4, item5),
expect: arr(item, item2, item3, item4, item5, list1, list2),
},
{
name: "only match item",
@ -331,6 +363,25 @@ func (suite *SharePointSelectorSuite) TestSharePointRestore_Reduce() {
},
expect: arr(item4, item5),
},
{
name: "lists match by id",
makeSelector: func() *SharePointRestore {
odr := NewSharePointRestore([]string{"sid"})
odr.Include(odr.Lists([]string{listID1, listID2}))
return odr
},
expect: arr(list1, list2),
},
{
name: "lists match by name",
makeSelector: func() *SharePointRestore {
odr := NewSharePointRestore([]string{"sid"})
odr.Include(odr.ListItems(Any(), []string{"listName2"}))
return odr
},
expect: arr(list2),
cfg: Config{OnlyMatchItemNames: true},
},
}
for _, test := range table {
suite.Run(test.name, func() {
@ -361,7 +412,7 @@ func (suite *SharePointSelectorSuite) TestSharePointCategory_PathValues() {
"dir2.d",
itemID,
}
elems = []string{"dir1", "dir2", itemID}
elems = []string{itemID, itemID}
)
table := []struct {
@ -401,9 +452,9 @@ func (suite *SharePointSelectorSuite) TestSharePointCategory_PathValues() {
name: "SharePoint Lists",
sc: SharePointListItem,
pathElems: elems,
locRef: "dir1/dir2",
locRef: itemID,
expected: map[categorizer][]string{
SharePointList: {"dir1/dir2"},
SharePointList: {itemID},
SharePointListItem: {itemID, shortRef},
},
cfg: Config{},
@ -423,17 +474,28 @@ func (suite *SharePointSelectorSuite) TestSharePointCategory_PathValues() {
test.pathElems...)
require.NoError(t, err, clues.ToCore(err))
di := details.ItemInfo{}
if test.sc.PathType() == path.LibrariesCategory {
di.SharePoint = &details.SharePointInfo{
ItemName: itemName,
ParentPath: test.parentPath,
}
} else if test.sc.PathType() == path.ListsCategory {
di.SharePoint = &details.SharePointInfo{
List: &details.ListInfo{
Name: itemName,
},
ParentPath: test.parentPath,
}
}
ent := details.Entry{
RepoRef: itemPath.String(),
ShortRef: shortRef,
ItemRef: itemPath.Item(),
LocationRef: test.locRef,
ItemInfo: details.ItemInfo{
SharePoint: &details.SharePointInfo{
ItemName: itemName,
ParentPath: test.parentPath,
},
},
ItemInfo: di,
}
pv, err := test.sc.pathValues(itemPath, ent, test.cfg)