Trim trailing '/' from CLI input for restore/details (#1175)
## Description Use paths package to trim unescaped trailing '/' characters from input for Exchange mail and OneDrive folder names. Add tests for Exchange showing that the trimming also works properly if the folder name ends with '/'. ## Type of change <!--- Please check the type of change your PR introduces: ---> - [ ] 🌻 Feature - [x] 🐛 Bugfix - [ ] 🗺️ Documentation - [ ] 🤖 Test - [ ] 💻 CI/Deployment - [ ] 🐹 Trivial/Minor ## Issue(s) * closes #1147 ## Test Plan <!-- How will this be tested prior to merging.--> - [x] 💪 Manual - [x] ⚡ Unit test - [ ] 💚 E2E
This commit is contained in:
parent
7d72cd12a4
commit
72a3c7ab3b
@ -142,6 +142,8 @@ func IncludeExchangeRestoreDataSelectors(
|
||||
return
|
||||
}
|
||||
|
||||
opts.EmailFolder = trimFolderSlash(opts.EmailFolder)
|
||||
|
||||
// or add selectors for each type of data
|
||||
AddExchangeInclude(sel, opts.Users, opts.ContactFolder, opts.Contact, sel.Contacts)
|
||||
AddExchangeInclude(sel, opts.Users, opts.EmailFolder, opts.Email, sel.Mails)
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common"
|
||||
"github.com/alcionai/corso/src/pkg/path"
|
||||
)
|
||||
|
||||
type PopulatedFlags map[string]struct{}
|
||||
@ -50,3 +51,16 @@ func IsValidBool(in string) bool {
|
||||
_, err := strconv.ParseBool(in)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// trimFolderSlash takes a set of folder paths and returns a set of folder paths
|
||||
// with any unescaped trailing `/` characters removed.
|
||||
func trimFolderSlash(folders []string) []string {
|
||||
res := make([]string, 0, len(folders))
|
||||
|
||||
for _, p := range folders {
|
||||
// Use path package because it has logic to handle escaping already.
|
||||
res = append(res, path.TrimTrailingSlash(p))
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
@ -87,6 +87,8 @@ func IncludeOneDriveRestoreDataSelectors(
|
||||
return
|
||||
}
|
||||
|
||||
opts.Paths = trimFolderSlash(opts.Paths)
|
||||
|
||||
if lp == 0 {
|
||||
opts.Paths = selectors.Any()
|
||||
}
|
||||
|
||||
37
src/cli/utils/testdata/opts.go
vendored
37
src/cli/utils/testdata/opts.go
vendored
@ -139,8 +139,38 @@ var (
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmailsBySubject",
|
||||
Name: "EmailsFolderPrefixMatchTrailingSlash",
|
||||
Expected: testdata.ExchangeEmailItems,
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailFolder: []string{testdata.ExchangeEmailInboxPath.Folder() + "/"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmailsFolderWithSlashPrefixMatch",
|
||||
Expected: []details.DetailsEntry{
|
||||
testdata.ExchangeEmailItems[1],
|
||||
testdata.ExchangeEmailItems[2],
|
||||
},
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailFolder: []string{testdata.ExchangeEmailBasePath2.Folder()},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmailsFolderWithSlashPrefixMatchTrailingSlash",
|
||||
Expected: []details.DetailsEntry{
|
||||
testdata.ExchangeEmailItems[1],
|
||||
testdata.ExchangeEmailItems[2],
|
||||
},
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailFolder: []string{testdata.ExchangeEmailBasePath2.Folder() + "/"},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmailsBySubject",
|
||||
Expected: []details.DetailsEntry{
|
||||
testdata.ExchangeEmailItems[0],
|
||||
testdata.ExchangeEmailItems[1],
|
||||
},
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailSender: "a-person",
|
||||
},
|
||||
@ -181,7 +211,10 @@ var (
|
||||
},
|
||||
{
|
||||
Name: "MultipleMailShortRef",
|
||||
Expected: testdata.ExchangeEmailItems,
|
||||
Expected: []details.DetailsEntry{
|
||||
testdata.ExchangeEmailItems[0],
|
||||
testdata.ExchangeEmailItems[1],
|
||||
},
|
||||
Opts: utils.ExchangeOpts{
|
||||
Email: []string{
|
||||
testdata.ExchangeEmailItemPath1.ShortRef(),
|
||||
|
||||
@ -145,7 +145,7 @@ func (pb *Builder) appendElements(escaped bool, elements []string) error {
|
||||
tmp := e
|
||||
|
||||
if escaped {
|
||||
tmp = trimTrailingSlash(tmp)
|
||||
tmp = TrimTrailingSlash(tmp)
|
||||
// If tmp was just the path separator then it will be empty now.
|
||||
if len(tmp) == 0 {
|
||||
continue
|
||||
@ -310,7 +310,7 @@ func (pb Builder) ToDataLayerOneDrivePath(
|
||||
// resource-specific type. If p does not match any resource-specific paths or
|
||||
// is malformed returns an error.
|
||||
func FromDataLayerPath(p string, isItem bool) (Path, error) {
|
||||
p = trimTrailingSlash(p)
|
||||
p = TrimTrailingSlash(p)
|
||||
// If p was just the path separator then it will be empty now.
|
||||
if len(p) == 0 {
|
||||
return nil, errors.Errorf("logically empty path given: %s", p)
|
||||
@ -437,11 +437,11 @@ func validateEscapedElement(element string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// trimTrailingSlash takes an escaped path element and returns an escaped path
|
||||
// TrimTrailingSlash takes an escaped path element and returns an escaped path
|
||||
// element with the trailing path separator character(s) removed if they were not
|
||||
// escaped. If there were no trailing path separator character(s) or the separator(s)
|
||||
// were escaped the input is returned unchanged.
|
||||
func trimTrailingSlash(element string) string {
|
||||
func TrimTrailingSlash(element string) string {
|
||||
for len(element) > 0 && element[len(element)-1] == pathSeparator {
|
||||
lastIdx := len(element) - 1
|
||||
numSlashes := 0
|
||||
|
||||
@ -92,7 +92,10 @@ func (suite *SelectorReduceSuite) TestReduce() {
|
||||
|
||||
return sel
|
||||
},
|
||||
expected: testdata.ExchangeEmailItems,
|
||||
expected: []details.DetailsEntry{
|
||||
testdata.ExchangeEmailItems[0],
|
||||
testdata.ExchangeEmailItems[1],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ExchangeMailReceivedTime",
|
||||
|
||||
18
src/pkg/selectors/testdata/details.go
vendored
18
src/pkg/selectors/testdata/details.go
vendored
@ -36,6 +36,7 @@ func mustAppendPath(p path.Path, newElement string, isItem bool) path.Path {
|
||||
const (
|
||||
ItemName1 = "item1"
|
||||
ItemName2 = "item2"
|
||||
ItemName3 = "item3"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -44,9 +45,11 @@ var (
|
||||
|
||||
ExchangeEmailInboxPath = mustParsePath("tenant-id/exchange/user-id/email/Inbox", false)
|
||||
ExchangeEmailBasePath = mustAppendPath(ExchangeEmailInboxPath, "subfolder", false)
|
||||
ExchangeEmailBasePath2 = mustAppendPath(ExchangeEmailInboxPath, "othersubfolder", false)
|
||||
ExchangeEmailBasePath2 = mustAppendPath(ExchangeEmailInboxPath, "othersubfolder/", false)
|
||||
ExchangeEmailBasePath3 = mustAppendPath(ExchangeEmailBasePath2, "subsubfolder", false)
|
||||
ExchangeEmailItemPath1 = mustAppendPath(ExchangeEmailBasePath, ItemName1, true)
|
||||
ExchangeEmailItemPath2 = mustAppendPath(ExchangeEmailBasePath2, ItemName2, true)
|
||||
ExchangeEmailItemPath3 = mustAppendPath(ExchangeEmailBasePath3, ItemName3, true)
|
||||
|
||||
ExchangeEmailItems = []details.DetailsEntry{
|
||||
{
|
||||
@ -75,6 +78,19 @@ var (
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
RepoRef: ExchangeEmailItemPath3.String(),
|
||||
ShortRef: ExchangeEmailItemPath3.ShortRef(),
|
||||
ParentRef: ExchangeEmailItemPath3.ToBuilder().Dir().ShortRef(),
|
||||
ItemInfo: details.ItemInfo{
|
||||
Exchange: &details.ExchangeInfo{
|
||||
ItemType: details.ExchangeMail,
|
||||
Sender: "another-person",
|
||||
Subject: "baz",
|
||||
Received: Time2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ExchangeContactsRootPath = mustParsePath("tenant-id/exchange/user-id/contacts/contacts", false)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user