check for flag population instead of empty string (#1075)
Adds a processor that confirms whether user has added a value for a flag in the cmd, or if it is the default value. This map of valued flags is added to the service opts structs to for validation. Also migrates many service flags to utils as consts so that these values can be maintained as consistent across packages.
This commit is contained in:
parent
4a29d22216
commit
65d6780906
@ -110,11 +110,11 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
// More generic (ex: --user) and more frequently used flags take precedence.
|
||||
fs.StringSliceVar(
|
||||
&user,
|
||||
"user", nil,
|
||||
utils.UserFN, nil,
|
||||
"Backup Exchange data by user ID; accepts '"+utils.Wildcard+"' to select all users")
|
||||
fs.StringSliceVar(
|
||||
&exchangeData,
|
||||
"data", nil,
|
||||
utils.DataFN, nil,
|
||||
"Select one or more types of data to backup: "+dataEmail+", "+dataContacts+", or "+dataEvents)
|
||||
options.AddOperationFlags(c)
|
||||
|
||||
@ -134,83 +134,83 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
// Flags addition ordering should follow the order we want them to appear in help and docs:
|
||||
// More generic (ex: --user) and more frequently used flags take precedence.
|
||||
fs.StringVar(&backupID,
|
||||
"backup", "",
|
||||
utils.BackupFN, "",
|
||||
"ID of the backup to explore. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
||||
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||
fs.StringSliceVar(
|
||||
&user,
|
||||
"user", nil,
|
||||
utils.UserFN, nil,
|
||||
"Select backup details by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
||||
|
||||
// email flags
|
||||
fs.StringSliceVar(
|
||||
&email,
|
||||
"email", nil,
|
||||
utils.EmailFN, nil,
|
||||
"Select backup details for emails by email ID; accepts '"+utils.Wildcard+"' to select all emails.")
|
||||
fs.StringSliceVar(
|
||||
&emailFolder,
|
||||
"email-folder", nil,
|
||||
utils.EmailFolderFN, nil,
|
||||
"Select backup details for emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
|
||||
fs.StringVar(
|
||||
&emailSubject,
|
||||
"email-subject", "",
|
||||
utils.EmailSubjectFN, "",
|
||||
"Select backup details for emails with a subject containing this value.")
|
||||
fs.StringVar(
|
||||
&emailSender,
|
||||
"email-sender", "",
|
||||
utils.EmailSenderFN, "",
|
||||
"Select backup details for emails from a specific sender.")
|
||||
fs.StringVar(
|
||||
&emailReceivedAfter,
|
||||
"email-received-after", "",
|
||||
utils.EmailReceivedAfterFN, "",
|
||||
"Select backup details for emails received after this datetime.")
|
||||
fs.StringVar(
|
||||
&emailReceivedBefore,
|
||||
"email-received-before", "",
|
||||
utils.EmailReceivedBeforeFN, "",
|
||||
"Select backup details for emails received before this datetime.")
|
||||
|
||||
// event flags
|
||||
fs.StringSliceVar(
|
||||
&event,
|
||||
"event", nil,
|
||||
utils.EventFN, nil,
|
||||
"Select backup details for events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
|
||||
fs.StringSliceVar(
|
||||
&eventCalendar,
|
||||
"event-calendar", nil,
|
||||
utils.EventCalendarFN, nil,
|
||||
"Select backup details for events under a calendar; accepts '"+utils.Wildcard+"' to select all events.")
|
||||
fs.StringVar(
|
||||
&eventSubject,
|
||||
"event-subject", "",
|
||||
utils.EventSubjectFN, "",
|
||||
"Select backup details for events with a subject containing this value.")
|
||||
fs.StringVar(
|
||||
&eventOrganizer,
|
||||
"event-organizer", "",
|
||||
utils.EventOrganizerFN, "",
|
||||
"Select backup details for events from a specific organizer.")
|
||||
fs.StringVar(
|
||||
&eventRecurs,
|
||||
"event-recurs", "",
|
||||
utils.EventRecursFN, "",
|
||||
"Select backup details for recurring events. Use `--event-recurs false` to select non-recurring events.")
|
||||
fs.StringVar(
|
||||
&eventStartsAfter,
|
||||
"event-starts-after", "",
|
||||
utils.EventStartsAfterFN, "",
|
||||
"Select backup details for events starting after this datetime.")
|
||||
fs.StringVar(
|
||||
&eventStartsBefore,
|
||||
"event-starts-before", "",
|
||||
utils.EventStartsBeforeFN, "",
|
||||
"Select backup details for events starting before this datetime.")
|
||||
|
||||
// contact flags
|
||||
fs.StringSliceVar(
|
||||
&contact,
|
||||
"contact", nil,
|
||||
utils.ContactFN, nil,
|
||||
"Select backup details for contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
|
||||
fs.StringSliceVar(
|
||||
&contactFolder,
|
||||
"contact-folder", nil,
|
||||
utils.ContactFolderFN, nil,
|
||||
"Select backup details for contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
|
||||
|
||||
fs.StringVar(
|
||||
&contactName,
|
||||
"contact-name", "",
|
||||
utils.ContactNameFN, "",
|
||||
"Select backup details for contacts whose contact name contains this value.")
|
||||
|
||||
case deleteCommand:
|
||||
@ -219,8 +219,10 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
c.Use = c.Use + " " + exchangeServiceCommandDeleteUseSuffix
|
||||
c.Example = exchangeServiceCommandDeleteExamples
|
||||
|
||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to delete. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
||||
fs.StringVar(&backupID,
|
||||
utils.BackupFN, "",
|
||||
"ID of the backup to delete. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||
}
|
||||
|
||||
return c
|
||||
@ -401,12 +403,12 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
|
||||
ctx := cmd.Context()
|
||||
opts := utils.ExchangeOpts{
|
||||
Contacts: contact,
|
||||
ContactFolders: contactFolder,
|
||||
Emails: email,
|
||||
EmailFolders: emailFolder,
|
||||
Events: event,
|
||||
EventCalendars: eventCalendar,
|
||||
Contact: contact,
|
||||
ContactFolder: contactFolder,
|
||||
Email: email,
|
||||
EmailFolder: emailFolder,
|
||||
Event: event,
|
||||
EventCalendar: eventCalendar,
|
||||
Users: user,
|
||||
ContactName: contactName,
|
||||
EmailReceivedAfter: emailReceivedAfter,
|
||||
@ -418,6 +420,8 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
EventStartsAfter: eventStartsAfter,
|
||||
EventStartsBefore: eventStartsBefore,
|
||||
EventSubject: eventSubject,
|
||||
|
||||
Populated: utils.GetPopulatedFlags(cmd),
|
||||
}
|
||||
|
||||
s, acct, err := config.GetStorageAndAccount(ctx, true, nil)
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"github.com/alcionai/corso/src/cli"
|
||||
"github.com/alcionai/corso/src/cli/config"
|
||||
"github.com/alcionai/corso/src/cli/print"
|
||||
"github.com/alcionai/corso/src/cli/utils"
|
||||
"github.com/alcionai/corso/src/internal/connector/exchange"
|
||||
"github.com/alcionai/corso/src/internal/operations"
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
@ -108,8 +109,8 @@ func (suite *BackupExchangeIntegrationSuite) TestExchangeBackupCmd() {
|
||||
cmd := tester.StubRootCmd(
|
||||
"backup", "create", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--user", suite.m365UserID,
|
||||
"--data", set.String())
|
||||
"--"+utils.UserFN, suite.m365UserID,
|
||||
"--"+utils.DataFN, set.String())
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
cmd.SetOut(&recorder)
|
||||
@ -327,7 +328,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
||||
cmd := tester.StubRootCmd(
|
||||
"backup", "details", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--backup", string(bID))
|
||||
"--"+utils.BackupFN, string(bID))
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
cmd.SetOut(&suite.recorder)
|
||||
@ -358,7 +359,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
||||
}
|
||||
|
||||
// At least the prefix of the path should be encoded as folders.
|
||||
assert.Greater(suite.T(), foundFolders, 4)
|
||||
assert.Greater(t, foundFolders, 4)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -441,7 +442,7 @@ func (suite *BackupDeleteExchangeIntegrationSuite) TestExchangeBackupDeleteCmd()
|
||||
cmd := tester.StubRootCmd(
|
||||
"backup", "delete", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--backup", string(suite.backupOp.Results.BackupID))
|
||||
"--"+utils.BackupFN, string(suite.backupOp.Results.BackupID))
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
// run the command
|
||||
@ -467,7 +468,7 @@ func (suite *BackupDeleteExchangeIntegrationSuite) TestExchangeBackupDeleteCmd_U
|
||||
cmd := tester.StubRootCmd(
|
||||
"backup", "delete", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--backup", uuid.NewString())
|
||||
"--"+utils.BackupFN, uuid.NewString())
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
// unknown backupIDs should error since the modelStore can't find the backup
|
||||
|
||||
@ -79,7 +79,8 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
|
||||
c.Use = c.Use + " " + oneDriveServiceCommandCreateUseSuffix
|
||||
c.Example = oneDriveServiceCommandCreateExamples
|
||||
|
||||
fs.StringArrayVar(&user, "user", nil,
|
||||
fs.StringArrayVar(&user,
|
||||
utils.UserFN, nil,
|
||||
"Backup OneDrive data by user ID; accepts '"+utils.Wildcard+"' to select all users. (required)")
|
||||
options.AddOperationFlags(c)
|
||||
|
||||
@ -96,39 +97,41 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
|
||||
c.Use = c.Use + " " + oneDriveServiceCommandDetailsUseSuffix
|
||||
c.Example = oneDriveServiceCommandDetailsExamples
|
||||
|
||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to explore. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
||||
fs.StringVar(&backupID,
|
||||
utils.BackupFN, "",
|
||||
"ID of the backup to explore. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||
|
||||
// onedrive hierarchy flags
|
||||
|
||||
fs.StringSliceVar(
|
||||
&folderPaths,
|
||||
"folder", nil,
|
||||
utils.FolderFN, nil,
|
||||
"Select backup details by OneDrive folder; defaults to root.")
|
||||
|
||||
fs.StringSliceVar(
|
||||
&fileNames,
|
||||
"file", nil,
|
||||
utils.FileFN, nil,
|
||||
"Select backup details by file name or ID.")
|
||||
|
||||
// onedrive info flags
|
||||
|
||||
fs.StringVar(
|
||||
&fileCreatedAfter,
|
||||
"file-created-after", "",
|
||||
utils.FileCreatedAfterFN, "",
|
||||
"Select backup details for files created after this datetime.")
|
||||
fs.StringVar(
|
||||
&fileCreatedBefore,
|
||||
"file-created-before", "",
|
||||
utils.FileCreatedBeforeFN, "",
|
||||
"Select backup details for files created before this datetime.")
|
||||
|
||||
fs.StringVar(
|
||||
&fileModifiedAfter,
|
||||
"file-modified-after", "",
|
||||
utils.FileModifiedAfterFN, "",
|
||||
"Select backup details for files modified after this datetime.")
|
||||
fs.StringVar(
|
||||
&fileModifiedBefore,
|
||||
"file-modified-before", "",
|
||||
utils.FileModifiedBeforeFN, "",
|
||||
"Select backup details for files modified before this datetime.")
|
||||
|
||||
case deleteCommand:
|
||||
@ -137,8 +140,10 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
|
||||
c.Use = c.Use + " " + oneDriveServiceCommandDeleteUseSuffix
|
||||
c.Example = oneDriveServiceCommandDeleteExamples
|
||||
|
||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to delete. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
||||
fs.StringVar(&backupID,
|
||||
utils.BackupFN, "",
|
||||
"ID of the backup to delete. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||
}
|
||||
|
||||
return c
|
||||
@ -311,13 +316,15 @@ func detailsOneDriveCmd(cmd *cobra.Command, args []string) error {
|
||||
defer utils.CloseRepo(ctx, r)
|
||||
|
||||
opts := utils.OneDriveOpts{
|
||||
Users: user,
|
||||
Paths: folderPaths,
|
||||
Names: fileNames,
|
||||
CreatedAfter: fileCreatedAfter,
|
||||
CreatedBefore: fileCreatedBefore,
|
||||
ModifiedAfter: fileModifiedAfter,
|
||||
ModifiedBefore: fileModifiedBefore,
|
||||
Users: user,
|
||||
Paths: folderPaths,
|
||||
Names: fileNames,
|
||||
FileCreatedAfter: fileCreatedAfter,
|
||||
FileCreatedBefore: fileCreatedBefore,
|
||||
FileModifiedAfter: fileModifiedAfter,
|
||||
FileModifiedBefore: fileModifiedBefore,
|
||||
|
||||
Populated: utils.GetPopulatedFlags(cmd),
|
||||
}
|
||||
|
||||
ds, err := runDetailsOneDriveCmd(ctx, r, backupID, opts)
|
||||
|
||||
@ -56,79 +56,81 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
||||
// Flags addition ordering should follow the order we want them to appear in help and docs:
|
||||
// More generic (ex: --user) and more frequently used flags take precedence.
|
||||
// general flags
|
||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to restore. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
||||
fs.StringVar(&backupID,
|
||||
utils.BackupFN, "",
|
||||
"ID of the backup to restore. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||
|
||||
fs.StringSliceVar(&user,
|
||||
"user", nil,
|
||||
utils.UserFN, nil,
|
||||
"Restore data by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
||||
|
||||
// email flags
|
||||
fs.StringSliceVar(&email,
|
||||
"email", nil,
|
||||
utils.EmailFN, nil,
|
||||
"Restore emails by ID; accepts '"+utils.Wildcard+"' to select all emails.")
|
||||
fs.StringSliceVar(
|
||||
&emailFolder,
|
||||
"email-folder", nil,
|
||||
utils.EmailFolderFN, nil,
|
||||
"Restore emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
|
||||
fs.StringVar(
|
||||
&emailSubject,
|
||||
"email-subject", "",
|
||||
utils.EmailSubjectFN, "",
|
||||
"Restore emails with a subject containing this value.")
|
||||
fs.StringVar(
|
||||
&emailSender,
|
||||
"email-sender", "",
|
||||
utils.EmailSenderFN, "",
|
||||
"Restore emails from a specific sender.")
|
||||
fs.StringVar(
|
||||
&emailReceivedAfter,
|
||||
"email-received-after", "",
|
||||
utils.EmailReceivedAfterFN, "",
|
||||
"Restore emails received after this datetime.")
|
||||
fs.StringVar(
|
||||
&emailReceivedBefore,
|
||||
"email-received-before", "",
|
||||
utils.EmailReceivedBeforeFN, "",
|
||||
"Restore emails received before this datetime.")
|
||||
|
||||
// event flags
|
||||
fs.StringSliceVar(&event,
|
||||
"event", nil,
|
||||
utils.EventFN, nil,
|
||||
"Restore events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
|
||||
fs.StringSliceVar(
|
||||
&eventCalendar,
|
||||
"event-calendar", nil,
|
||||
utils.EventCalendarFN, nil,
|
||||
"Restore events under a calendar; accepts '"+utils.Wildcard+"' to select all event calendars.")
|
||||
fs.StringVar(
|
||||
&eventSubject,
|
||||
"event-subject", "",
|
||||
utils.EventSubjectFN, "",
|
||||
"Restore events with a subject containing this value.")
|
||||
fs.StringVar(
|
||||
&eventOrganizer,
|
||||
"event-organizer", "",
|
||||
utils.EventOrganizerFN, "",
|
||||
"Restore events from a specific organizer.")
|
||||
fs.StringVar(
|
||||
&eventRecurs,
|
||||
"event-recurs", "",
|
||||
utils.EventRecursFN, "",
|
||||
"Restore recurring events. Use `--event-recurs false` to restore non-recurring events.")
|
||||
fs.StringVar(
|
||||
&eventStartsAfter,
|
||||
"event-starts-after", "",
|
||||
utils.EventStartsAfterFN, "",
|
||||
"Restore events starting after this datetime.")
|
||||
fs.StringVar(
|
||||
&eventStartsBefore,
|
||||
"event-starts-before", "",
|
||||
utils.EventStartsBeforeFN, "",
|
||||
"Restore events starting before this datetime.")
|
||||
|
||||
// contacts flags
|
||||
fs.StringSliceVar(
|
||||
&contact,
|
||||
"contact", nil,
|
||||
utils.ContactFN, nil,
|
||||
"Restore contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
|
||||
fs.StringSliceVar(
|
||||
&contactFolder,
|
||||
"contact-folder", nil,
|
||||
utils.ContactFolderFN, nil,
|
||||
"Restore contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
|
||||
fs.StringVar(
|
||||
&contactName,
|
||||
"contact-name", "",
|
||||
utils.ContactNameFN, "",
|
||||
"Restore contacts whose contact name contains this value.")
|
||||
|
||||
// others
|
||||
@ -177,12 +179,12 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
opts := utils.ExchangeOpts{
|
||||
Contacts: contact,
|
||||
ContactFolders: contactFolder,
|
||||
Emails: email,
|
||||
EmailFolders: emailFolder,
|
||||
Events: event,
|
||||
EventCalendars: eventCalendar,
|
||||
Contact: contact,
|
||||
ContactFolder: contactFolder,
|
||||
Email: email,
|
||||
EmailFolder: emailFolder,
|
||||
Event: event,
|
||||
EventCalendar: eventCalendar,
|
||||
Users: user,
|
||||
ContactName: contactName,
|
||||
EmailReceivedAfter: emailReceivedAfter,
|
||||
@ -194,6 +196,8 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
||||
EventStartsAfter: eventStartsAfter,
|
||||
EventStartsBefore: eventStartsBefore,
|
||||
EventSubject: eventSubject,
|
||||
|
||||
Populated: utils.GetPopulatedFlags(cmd),
|
||||
}
|
||||
|
||||
if err := utils.ValidateExchangeRestoreFlags(backupID, opts); err != nil {
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/alcionai/corso/src/cli"
|
||||
"github.com/alcionai/corso/src/cli/config"
|
||||
"github.com/alcionai/corso/src/cli/utils"
|
||||
"github.com/alcionai/corso/src/internal/connector/exchange"
|
||||
"github.com/alcionai/corso/src/internal/operations"
|
||||
"github.com/alcionai/corso/src/internal/tester"
|
||||
@ -136,7 +137,7 @@ func (suite *RestoreExchangeIntegrationSuite) TestExchangeRestoreCmd() {
|
||||
cmd := tester.StubRootCmd(
|
||||
"restore", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--backup", string(suite.backupOps[set].Results.BackupID))
|
||||
"--"+utils.BackupFN, string(suite.backupOps[set].Results.BackupID))
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
// run the command
|
||||
@ -160,15 +161,15 @@ func (suite *RestoreExchangeIntegrationSuite) TestExchangeRestoreCmd_badTimeFlag
|
||||
var timeFilter string
|
||||
switch set {
|
||||
case email:
|
||||
timeFilter = "--email-received-after"
|
||||
timeFilter = "--" + utils.EmailReceivedAfterFN
|
||||
case events:
|
||||
timeFilter = "--event-starts-after"
|
||||
timeFilter = "--" + utils.EventStartsAfterFN
|
||||
}
|
||||
|
||||
cmd := tester.StubRootCmd(
|
||||
"restore", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--backup", string(suite.backupOps[set].Results.BackupID),
|
||||
"--"+utils.BackupFN, string(suite.backupOps[set].Results.BackupID),
|
||||
timeFilter, "smarf")
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
@ -192,13 +193,13 @@ func (suite *RestoreExchangeIntegrationSuite) TestExchangeRestoreCmd_badBoolFlag
|
||||
var timeFilter string
|
||||
switch set {
|
||||
case events:
|
||||
timeFilter = "--event-recurs"
|
||||
timeFilter = "--" + utils.EventRecursFN
|
||||
}
|
||||
|
||||
cmd := tester.StubRootCmd(
|
||||
"restore", "exchange",
|
||||
"--config-file", suite.cfgFP,
|
||||
"--backup", string(suite.backupOps[set].Results.BackupID),
|
||||
"--"+utils.BackupFN, string(suite.backupOps[set].Results.BackupID),
|
||||
timeFilter, "wingbat")
|
||||
cli.BuildCommandTree(cmd)
|
||||
|
||||
|
||||
@ -42,43 +42,45 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
|
||||
// More generic (ex: --user) and more frequently used flags take precedence.
|
||||
fs.SortFlags = false
|
||||
|
||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to restore. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
||||
fs.StringVar(&backupID,
|
||||
utils.BackupFN, "",
|
||||
"ID of the backup to restore. (required)")
|
||||
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||
|
||||
fs.StringSliceVar(&user,
|
||||
"user", nil,
|
||||
utils.UserFN, nil,
|
||||
"Restore data by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
||||
|
||||
// onedrive hierarchy (path/name) flags
|
||||
|
||||
fs.StringSliceVar(
|
||||
&folderPaths,
|
||||
"folder", nil,
|
||||
utils.FolderFN, nil,
|
||||
"Restore items by OneDrive folder; defaults to root")
|
||||
|
||||
fs.StringSliceVar(
|
||||
&fileNames,
|
||||
"file", nil,
|
||||
utils.FileFN, nil,
|
||||
"Restore items by file name or ID")
|
||||
|
||||
// onedrive info flags
|
||||
|
||||
fs.StringVar(
|
||||
&fileCreatedAfter,
|
||||
"file-created-after", "",
|
||||
utils.FileCreatedAfterFN, "",
|
||||
"Restore files created after this datetime")
|
||||
fs.StringVar(
|
||||
&fileCreatedBefore,
|
||||
"file-created-before", "",
|
||||
utils.FileCreatedBeforeFN, "",
|
||||
"Restore files created before this datetime")
|
||||
|
||||
fs.StringVar(
|
||||
&fileModifiedAfter,
|
||||
"file-modified-after", "",
|
||||
utils.FileModifiedAfterFN, "",
|
||||
"Restore files modified after this datetime")
|
||||
fs.StringVar(
|
||||
&fileModifiedBefore,
|
||||
"file-modified-before", "",
|
||||
utils.FileModifiedBeforeFN, "",
|
||||
"Restore files modified before this datetime")
|
||||
|
||||
// others
|
||||
@ -124,13 +126,15 @@ func restoreOneDriveCmd(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
opts := utils.OneDriveOpts{
|
||||
Users: user,
|
||||
Paths: folderPaths,
|
||||
Names: fileNames,
|
||||
CreatedAfter: fileCreatedAfter,
|
||||
CreatedBefore: fileCreatedBefore,
|
||||
ModifiedAfter: fileModifiedAfter,
|
||||
ModifiedBefore: fileModifiedBefore,
|
||||
Users: user,
|
||||
Paths: folderPaths,
|
||||
Names: fileNames,
|
||||
FileCreatedAfter: fileCreatedAfter,
|
||||
FileCreatedBefore: fileCreatedBefore,
|
||||
FileModifiedAfter: fileModifiedAfter,
|
||||
FileModifiedBefore: fileModifiedBefore,
|
||||
|
||||
Populated: utils.GetPopulatedFlags(cmd),
|
||||
}
|
||||
|
||||
if err := utils.ValidateOneDriveRestoreFlags(backupID, opts); err != nil {
|
||||
|
||||
@ -6,13 +6,33 @@ import (
|
||||
"github.com/alcionai/corso/src/pkg/selectors"
|
||||
)
|
||||
|
||||
// flag names
|
||||
const (
|
||||
ContactFN = "contacts"
|
||||
ContactFolderFN = "contact-folder"
|
||||
EmailFN = "email"
|
||||
EmailFolderFN = "email-folder"
|
||||
EventFN = "events"
|
||||
EventCalendarFN = "event-calendar"
|
||||
ContactNameFN = "contact-name"
|
||||
EmailReceivedAfterFN = "email-received-after"
|
||||
EmailReceivedBeforeFN = "email-received-before"
|
||||
EmailSenderFN = "email-sender"
|
||||
EmailSubjectFN = "email-subject"
|
||||
EventOrganizerFN = "event-organizer"
|
||||
EventRecursFN = "event-recurs"
|
||||
EventStartsAfterFN = "event-starts-after"
|
||||
EventStartsBeforeFN = "event-starts-before"
|
||||
EventSubjectFN = "event-subject"
|
||||
)
|
||||
|
||||
type ExchangeOpts struct {
|
||||
Contacts []string
|
||||
ContactFolders []string
|
||||
Emails []string
|
||||
EmailFolders []string
|
||||
Events []string
|
||||
EventCalendars []string
|
||||
Contact []string
|
||||
ContactFolder []string
|
||||
Email []string
|
||||
EmailFolder []string
|
||||
Event []string
|
||||
EventCalendar []string
|
||||
Users []string
|
||||
ContactName string
|
||||
EmailReceivedAfter string
|
||||
@ -24,6 +44,8 @@ type ExchangeOpts struct {
|
||||
EventStartsAfter string
|
||||
EventStartsBefore string
|
||||
EventSubject string
|
||||
|
||||
Populated PopulatedFlags
|
||||
}
|
||||
|
||||
// AddExchangeInclude adds the scope of the provided values to the selector's
|
||||
@ -77,23 +99,23 @@ func ValidateExchangeRestoreFlags(backupID string, opts ExchangeOpts) error {
|
||||
return errors.New("a backup ID is required")
|
||||
}
|
||||
|
||||
if !IsValidTimeFormat(opts.EmailReceivedAfter) {
|
||||
if _, ok := opts.Populated[EmailReceivedAfterFN]; ok && !IsValidTimeFormat(opts.EmailReceivedAfter) {
|
||||
return errors.New("invalid time format for email-received-after")
|
||||
}
|
||||
|
||||
if !IsValidTimeFormat(opts.EmailReceivedBefore) {
|
||||
if _, ok := opts.Populated[EmailReceivedBeforeFN]; ok && !IsValidTimeFormat(opts.EmailReceivedBefore) {
|
||||
return errors.New("invalid time format for email-received-before")
|
||||
}
|
||||
|
||||
if !IsValidTimeFormat(opts.EventStartsAfter) {
|
||||
if _, ok := opts.Populated[EventStartsAfterFN]; ok && !IsValidTimeFormat(opts.EventStartsAfter) {
|
||||
return errors.New("invalid time format for event-starts-after")
|
||||
}
|
||||
|
||||
if !IsValidTimeFormat(opts.EventStartsBefore) {
|
||||
if _, ok := opts.Populated[EventStartsBeforeFN]; ok && !IsValidTimeFormat(opts.EventStartsBefore) {
|
||||
return errors.New("invalid time format for event-starts-before")
|
||||
}
|
||||
|
||||
if !IsValidBool(opts.EventRecurs) {
|
||||
if _, ok := opts.Populated[EventRecursFN]; ok && !IsValidBool(opts.EventRecurs) {
|
||||
return errors.New("invalid format for event-recurs")
|
||||
}
|
||||
|
||||
@ -106,9 +128,9 @@ func IncludeExchangeRestoreDataSelectors(
|
||||
sel *selectors.ExchangeRestore,
|
||||
opts ExchangeOpts,
|
||||
) {
|
||||
lc, lcf := len(opts.Contacts), len(opts.ContactFolders)
|
||||
le, lef := len(opts.Emails), len(opts.EmailFolders)
|
||||
lev, lec := len(opts.Events), len(opts.EventCalendars)
|
||||
lc, lcf := len(opts.Contact), len(opts.ContactFolder)
|
||||
le, lef := len(opts.Email), len(opts.EmailFolder)
|
||||
lev, lec := len(opts.Event), len(opts.EventCalendar)
|
||||
// either scope the request to a set of users
|
||||
if lc+lcf+le+lef+lev+lec == 0 {
|
||||
if len(opts.Users) == 0 {
|
||||
@ -121,9 +143,9 @@ func IncludeExchangeRestoreDataSelectors(
|
||||
}
|
||||
|
||||
// or add selectors for each type of data
|
||||
AddExchangeInclude(sel, opts.Users, opts.ContactFolders, opts.Contacts, sel.Contacts)
|
||||
AddExchangeInclude(sel, opts.Users, opts.EmailFolders, opts.Emails, sel.Mails)
|
||||
AddExchangeInclude(sel, opts.Users, opts.EventCalendars, opts.Events, sel.Events)
|
||||
AddExchangeInclude(sel, opts.Users, opts.ContactFolder, opts.Contact, sel.Contacts)
|
||||
AddExchangeInclude(sel, opts.Users, opts.EmailFolder, opts.Email, sel.Mails)
|
||||
AddExchangeInclude(sel, opts.Users, opts.EventCalendar, opts.Event, sel.Events)
|
||||
}
|
||||
|
||||
// FilterExchangeRestoreInfoSelectors builds the common info-selector filters.
|
||||
|
||||
@ -94,207 +94,207 @@ func (suite *ExchangeUtilsSuite) TestIncludeExchangeBackupDetailDataSelectors()
|
||||
{
|
||||
name: "any users, any data",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: a,
|
||||
ContactFolders: a,
|
||||
Emails: a,
|
||||
EmailFolders: a,
|
||||
Events: a,
|
||||
EventCalendars: a,
|
||||
Users: a,
|
||||
Contact: a,
|
||||
ContactFolder: a,
|
||||
Email: a,
|
||||
EmailFolder: a,
|
||||
Event: a,
|
||||
EventCalendar: a,
|
||||
Users: a,
|
||||
},
|
||||
expectIncludeLen: 3,
|
||||
},
|
||||
{
|
||||
name: "any users, any folders",
|
||||
opts: utils.ExchangeOpts{
|
||||
ContactFolders: a,
|
||||
EmailFolders: a,
|
||||
EventCalendars: a,
|
||||
Users: a,
|
||||
ContactFolder: a,
|
||||
EmailFolder: a,
|
||||
EventCalendar: a,
|
||||
Users: a,
|
||||
},
|
||||
expectIncludeLen: 3,
|
||||
},
|
||||
{
|
||||
name: "single user, single of each data",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: stub,
|
||||
ContactFolders: stub,
|
||||
Emails: stub,
|
||||
EmailFolders: stub,
|
||||
Events: stub,
|
||||
EventCalendars: stub,
|
||||
Users: stub,
|
||||
Contact: stub,
|
||||
ContactFolder: stub,
|
||||
Email: stub,
|
||||
EmailFolder: stub,
|
||||
Event: stub,
|
||||
EventCalendar: stub,
|
||||
Users: stub,
|
||||
},
|
||||
expectIncludeLen: 3,
|
||||
},
|
||||
{
|
||||
name: "single user, single of each folder",
|
||||
opts: utils.ExchangeOpts{
|
||||
ContactFolders: stub,
|
||||
EmailFolders: stub,
|
||||
EventCalendars: stub,
|
||||
Users: stub,
|
||||
ContactFolder: stub,
|
||||
EmailFolder: stub,
|
||||
EventCalendar: stub,
|
||||
Users: stub,
|
||||
},
|
||||
expectIncludeLen: 3,
|
||||
},
|
||||
{
|
||||
name: "any users, contacts",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: a,
|
||||
ContactFolders: stub,
|
||||
Users: a,
|
||||
Contact: a,
|
||||
ContactFolder: stub,
|
||||
Users: a,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "single user, contacts",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: stub,
|
||||
ContactFolders: stub,
|
||||
Users: stub,
|
||||
Contact: stub,
|
||||
ContactFolder: stub,
|
||||
Users: stub,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "any users, emails",
|
||||
opts: utils.ExchangeOpts{
|
||||
Emails: a,
|
||||
EmailFolders: stub,
|
||||
Users: a,
|
||||
Email: a,
|
||||
EmailFolder: stub,
|
||||
Users: a,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "single user, emails",
|
||||
opts: utils.ExchangeOpts{
|
||||
Emails: stub,
|
||||
EmailFolders: stub,
|
||||
Users: stub,
|
||||
Email: stub,
|
||||
EmailFolder: stub,
|
||||
Users: stub,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "any users, events",
|
||||
opts: utils.ExchangeOpts{
|
||||
Events: a,
|
||||
EventCalendars: a,
|
||||
Users: a,
|
||||
Event: a,
|
||||
EventCalendar: a,
|
||||
Users: a,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "single user, events",
|
||||
opts: utils.ExchangeOpts{
|
||||
Events: stub,
|
||||
EventCalendars: stub,
|
||||
Users: stub,
|
||||
Event: stub,
|
||||
EventCalendar: stub,
|
||||
Users: stub,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "any users, contacts + email",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: a,
|
||||
ContactFolders: a,
|
||||
Emails: a,
|
||||
EmailFolders: a,
|
||||
Users: a,
|
||||
Contact: a,
|
||||
ContactFolder: a,
|
||||
Email: a,
|
||||
EmailFolder: a,
|
||||
Users: a,
|
||||
},
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "single users, contacts + email",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: stub,
|
||||
ContactFolders: stub,
|
||||
Emails: stub,
|
||||
EmailFolders: stub,
|
||||
Users: stub,
|
||||
Contact: stub,
|
||||
ContactFolder: stub,
|
||||
Email: stub,
|
||||
EmailFolder: stub,
|
||||
Users: stub,
|
||||
},
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "any users, email + event",
|
||||
opts: utils.ExchangeOpts{
|
||||
Emails: a,
|
||||
EmailFolders: a,
|
||||
Events: a,
|
||||
EventCalendars: a,
|
||||
Users: a,
|
||||
Email: a,
|
||||
EmailFolder: a,
|
||||
Event: a,
|
||||
EventCalendar: a,
|
||||
Users: a,
|
||||
},
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "single users, email + event",
|
||||
opts: utils.ExchangeOpts{
|
||||
Emails: stub,
|
||||
EmailFolders: stub,
|
||||
Events: stub,
|
||||
EventCalendars: stub,
|
||||
Users: stub,
|
||||
Email: stub,
|
||||
EmailFolder: stub,
|
||||
Event: stub,
|
||||
EventCalendar: stub,
|
||||
Users: stub,
|
||||
},
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "any users, event + contact",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: a,
|
||||
ContactFolders: a,
|
||||
Events: a,
|
||||
EventCalendars: a,
|
||||
Users: a,
|
||||
Contact: a,
|
||||
ContactFolder: a,
|
||||
Event: a,
|
||||
EventCalendar: a,
|
||||
Users: a,
|
||||
},
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "single users, event + contact",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: stub,
|
||||
ContactFolders: stub,
|
||||
Events: stub,
|
||||
EventCalendars: stub,
|
||||
Users: stub,
|
||||
Contact: stub,
|
||||
ContactFolder: stub,
|
||||
Event: stub,
|
||||
EventCalendar: stub,
|
||||
Users: stub,
|
||||
},
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "many users, events",
|
||||
opts: utils.ExchangeOpts{
|
||||
Events: many,
|
||||
EventCalendars: many,
|
||||
Users: many,
|
||||
Event: many,
|
||||
EventCalendar: many,
|
||||
Users: many,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "many users, events + contacts",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: many,
|
||||
ContactFolders: many,
|
||||
Events: many,
|
||||
EventCalendars: many,
|
||||
Users: many,
|
||||
Contact: many,
|
||||
ContactFolder: many,
|
||||
Event: many,
|
||||
EventCalendar: many,
|
||||
Users: many,
|
||||
},
|
||||
expectIncludeLen: 2,
|
||||
},
|
||||
{
|
||||
name: "mail, no folder or user",
|
||||
opts: utils.ExchangeOpts{
|
||||
Emails: stub,
|
||||
Email: stub,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "contacts, no folder or user",
|
||||
opts: utils.ExchangeOpts{
|
||||
Contacts: stub,
|
||||
Contact: stub,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
{
|
||||
name: "event, no folder or user",
|
||||
opts: utils.ExchangeOpts{
|
||||
Events: stub,
|
||||
Event: stub,
|
||||
},
|
||||
expectIncludeLen: 1,
|
||||
},
|
||||
|
||||
52
src/cli/utils/flags.go
Normal file
52
src/cli/utils/flags.go
Normal file
@ -0,0 +1,52 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common"
|
||||
)
|
||||
|
||||
type PopulatedFlags map[string]struct{}
|
||||
|
||||
func (fs PopulatedFlags) populate(pf *pflag.Flag) {
|
||||
if pf == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if pf.Changed {
|
||||
fs[pf.Name] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// GetPopulatedFlags returns a map of flags that have been
|
||||
// populated by the user. Entry keys match the flag's long
|
||||
// name. Values are empty.
|
||||
func GetPopulatedFlags(cmd *cobra.Command) PopulatedFlags {
|
||||
pop := PopulatedFlags{}
|
||||
|
||||
fs := cmd.Flags()
|
||||
if fs == nil {
|
||||
return pop
|
||||
}
|
||||
|
||||
fs.VisitAll(pop.populate)
|
||||
|
||||
return pop
|
||||
}
|
||||
|
||||
// IsValidTimeFormat returns true if the input is recognized as a
|
||||
// supported format by the common time parser.
|
||||
func IsValidTimeFormat(in string) bool {
|
||||
_, err := common.ParseTime(in)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsValidTimeFormat returns true if the input is recognized as a
|
||||
// boolean.
|
||||
func IsValidBool(in string) bool {
|
||||
_, err := strconv.ParseBool(in)
|
||||
return err == nil
|
||||
}
|
||||
@ -6,14 +6,27 @@ import (
|
||||
"github.com/alcionai/corso/src/pkg/selectors"
|
||||
)
|
||||
|
||||
const (
|
||||
FileFN = "file"
|
||||
FolderFN = "folders"
|
||||
NamesFN = "names"
|
||||
PathsFN = "paths"
|
||||
FileCreatedAfterFN = "file-created-after"
|
||||
FileCreatedBeforeFN = "file-created-before"
|
||||
FileModifiedAfterFN = "file-modified-after"
|
||||
FileModifiedBeforeFN = "file-modified-before"
|
||||
)
|
||||
|
||||
type OneDriveOpts struct {
|
||||
Users []string
|
||||
Names []string
|
||||
Paths []string
|
||||
CreatedAfter string
|
||||
CreatedBefore string
|
||||
ModifiedAfter string
|
||||
ModifiedBefore string
|
||||
Users []string
|
||||
Names []string
|
||||
Paths []string
|
||||
FileCreatedAfter string
|
||||
FileCreatedBefore string
|
||||
FileModifiedAfter string
|
||||
FileModifiedBefore string
|
||||
|
||||
Populated PopulatedFlags
|
||||
}
|
||||
|
||||
// ValidateOneDriveRestoreFlags checks common flags for correctness and interdependencies
|
||||
@ -22,19 +35,19 @@ func ValidateOneDriveRestoreFlags(backupID string, opts OneDriveOpts) error {
|
||||
return errors.New("a backup ID is required")
|
||||
}
|
||||
|
||||
if !IsValidTimeFormat(opts.CreatedAfter) {
|
||||
if _, ok := opts.Populated[FileCreatedAfterFN]; ok && !IsValidTimeFormat(opts.FileCreatedAfter) {
|
||||
return errors.New("invalid time format for created-after")
|
||||
}
|
||||
|
||||
if !IsValidTimeFormat(opts.CreatedBefore) {
|
||||
if _, ok := opts.Populated[FileCreatedBeforeFN]; ok && !IsValidTimeFormat(opts.FileCreatedBefore) {
|
||||
return errors.New("invalid time format for created-before")
|
||||
}
|
||||
|
||||
if !IsValidTimeFormat(opts.ModifiedAfter) {
|
||||
if _, ok := opts.Populated[FileModifiedAfterFN]; ok && !IsValidTimeFormat(opts.FileModifiedAfter) {
|
||||
return errors.New("invalid time format for modified-after")
|
||||
}
|
||||
|
||||
if !IsValidTimeFormat(opts.ModifiedBefore) {
|
||||
if _, ok := opts.Populated[FileModifiedAfterFN]; ok && !IsValidTimeFormat(opts.FileModifiedBefore) {
|
||||
return errors.New("invalid time format for modified-before")
|
||||
}
|
||||
|
||||
@ -90,8 +103,8 @@ func FilterOneDriveRestoreInfoSelectors(
|
||||
sel *selectors.OneDriveRestore,
|
||||
opts OneDriveOpts,
|
||||
) {
|
||||
AddOneDriveFilter(sel, opts.CreatedAfter, sel.CreatedAfter)
|
||||
AddOneDriveFilter(sel, opts.CreatedBefore, sel.CreatedBefore)
|
||||
AddOneDriveFilter(sel, opts.ModifiedAfter, sel.ModifiedAfter)
|
||||
AddOneDriveFilter(sel, opts.ModifiedBefore, sel.ModifiedBefore)
|
||||
AddOneDriveFilter(sel, opts.FileCreatedAfter, sel.CreatedAfter)
|
||||
AddOneDriveFilter(sel, opts.FileCreatedBefore, sel.CreatedBefore)
|
||||
AddOneDriveFilter(sel, opts.FileModifiedAfter, sel.ModifiedAfter)
|
||||
AddOneDriveFilter(sel, opts.FileModifiedBefore, sel.ModifiedBefore)
|
||||
}
|
||||
|
||||
76
src/cli/utils/testdata/opts.go
vendored
76
src/cli/utils/testdata/opts.go
vendored
@ -31,30 +31,90 @@ var (
|
||||
Name: "BadEmailReceiveAfter",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailReceivedAfter: "foo",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EmailReceivedAfterFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmptyEmailReceiveAfter",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailReceivedAfter: "",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EmailReceivedAfterFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "BadEmailReceiveBefore",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailReceivedBefore: "foo",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EmailReceivedBeforeFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmptyEmailReceiveBefore",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailReceivedBefore: "",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EmailReceivedBeforeFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "BadEventRecurs",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventRecurs: "foo",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EventRecursFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmptyEventRecurs",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventRecurs: "",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EventRecursFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "BadEventStartsAfter",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventStartsAfter: "foo",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EventStartsAfterFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmptyEventStartsAfter",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventStartsAfter: "",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EventStartsAfterFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "BadEventStartsBefore",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventStartsBefore: "foo",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EventStartsBeforeFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmptyEventStartsBefore",
|
||||
Opts: utils.ExchangeOpts{
|
||||
EventStartsBefore: "",
|
||||
Populated: utils.PopulatedFlags{
|
||||
utils.EventStartsBeforeFN: struct{}{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -68,14 +128,14 @@ var (
|
||||
Name: "Emails",
|
||||
Expected: testdata.ExchangeEmailItems,
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: selectors.Any(),
|
||||
Email: selectors.Any(),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "EmailsFolderPrefixMatch",
|
||||
Expected: testdata.ExchangeEmailItems,
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailFolders: []string{testdata.ExchangeEmailInboxPath.Folder()},
|
||||
EmailFolder: []string{testdata.ExchangeEmailInboxPath.Folder()},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -109,21 +169,21 @@ var (
|
||||
Name: "MailID",
|
||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: []string{testdata.ExchangeEmailItemPath1.Item()},
|
||||
Email: []string{testdata.ExchangeEmailItemPath1.Item()},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MailShortRef",
|
||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
||||
Email: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "MultipleMailShortRef",
|
||||
Expected: testdata.ExchangeEmailItems,
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: []string{
|
||||
Email: []string{
|
||||
testdata.ExchangeEmailItemPath1.ShortRef(),
|
||||
testdata.ExchangeEmailItemPath2.ShortRef(),
|
||||
},
|
||||
@ -134,7 +194,7 @@ var (
|
||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||
Opts: utils.ExchangeOpts{
|
||||
EmailSubject: "foo",
|
||||
Events: selectors.Any(),
|
||||
Event: selectors.Any(),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -152,8 +212,8 @@ var (
|
||||
testdata.ExchangeEventsItems[0],
|
||||
},
|
||||
Opts: utils.ExchangeOpts{
|
||||
Emails: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
||||
Events: []string{testdata.ExchangeEventsItemPath1.ShortRef()},
|
||||
Email: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
||||
Event: []string{testdata.ExchangeEventsItemPath1.ShortRef()},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -4,15 +4,20 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/alcionai/corso/src/internal/common"
|
||||
"github.com/alcionai/corso/src/pkg/repository"
|
||||
)
|
||||
|
||||
// common flag names
|
||||
const (
|
||||
BackupFN = "backup"
|
||||
DataFN = "data"
|
||||
UserFN = "user"
|
||||
)
|
||||
|
||||
const (
|
||||
Wildcard = "*"
|
||||
)
|
||||
@ -59,30 +64,3 @@ func AddCommand(parent, c *cobra.Command) (*cobra.Command, *pflag.FlagSet) {
|
||||
|
||||
return c, c.Flags()
|
||||
}
|
||||
|
||||
// IsValidTimeFormat returns true if the input is regonized as a
|
||||
// supported format by the common time parser. Returns true if
|
||||
// the input is zero valued, which indicates that the flag was not
|
||||
// called.
|
||||
func IsValidTimeFormat(in string) bool {
|
||||
if len(in) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
_, err := common.ParseTime(in)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsValidTimeFormat returns true if the input is regonized as a
|
||||
// boolean. Returns true if the input is zero valued, which
|
||||
// indicates that the flag was not called.
|
||||
func IsValidBool(in string) bool {
|
||||
if len(in) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
_, err := strconv.ParseBool(in)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user