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:
parent
985220562c
commit
e16d4c5bd9
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
3
src/cli/flags/testdata/flags.go
vendored
3
src/cli/flags/testdata/flags.go
vendored
@ -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"}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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,9 +201,6 @@ 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()
|
||||
@ -224,21 +218,10 @@ func IncludeGroupsRestoreDataSelectors(ctx context.Context, opts GroupsOpts) *se
|
||||
}
|
||||
}
|
||||
|
||||
if listFolders+listItems > 0 {
|
||||
if listItems == 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 pageFolders+pageItems > 0 {
|
||||
@ -257,7 +240,6 @@ func IncludeGroupsRestoreDataSelectors(ctx context.Context, opts GroupsOpts) *se
|
||||
sel.Include(sel.PageItems(prefixFolders, opts.Page, selectors.PrefixMatch()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// channel and message selectors
|
||||
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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()
|
||||
if lists > 0 {
|
||||
opts.Lists = trimFolderSlash(opts.Lists)
|
||||
sel.Include(sel.ListItems(opts.Lists, opts.Lists, selectors.StrictEqualMatch()))
|
||||
sel.Configure(selectors.Config{OnlyMatchItemNames: true})
|
||||
}
|
||||
|
||||
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 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 {
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user