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.
|
// More generic (ex: --user) and more frequently used flags take precedence.
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&user,
|
&user,
|
||||||
"user", nil,
|
utils.UserFN, nil,
|
||||||
"Backup Exchange data by user ID; accepts '"+utils.Wildcard+"' to select all users")
|
"Backup Exchange data by user ID; accepts '"+utils.Wildcard+"' to select all users")
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&exchangeData,
|
&exchangeData,
|
||||||
"data", nil,
|
utils.DataFN, nil,
|
||||||
"Select one or more types of data to backup: "+dataEmail+", "+dataContacts+", or "+dataEvents)
|
"Select one or more types of data to backup: "+dataEmail+", "+dataContacts+", or "+dataEvents)
|
||||||
options.AddOperationFlags(c)
|
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:
|
// 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.
|
// More generic (ex: --user) and more frequently used flags take precedence.
|
||||||
fs.StringVar(&backupID,
|
fs.StringVar(&backupID,
|
||||||
"backup", "",
|
utils.BackupFN, "",
|
||||||
"ID of the backup to explore. (required)")
|
"ID of the backup to explore. (required)")
|
||||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&user,
|
&user,
|
||||||
"user", nil,
|
utils.UserFN, nil,
|
||||||
"Select backup details by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
"Select backup details by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
||||||
|
|
||||||
// email flags
|
// email flags
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&email,
|
&email,
|
||||||
"email", nil,
|
utils.EmailFN, nil,
|
||||||
"Select backup details for emails by email ID; accepts '"+utils.Wildcard+"' to select all emails.")
|
"Select backup details for emails by email ID; accepts '"+utils.Wildcard+"' to select all emails.")
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&emailFolder,
|
&emailFolder,
|
||||||
"email-folder", nil,
|
utils.EmailFolderFN, nil,
|
||||||
"Select backup details for emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
|
"Select backup details for emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&emailSubject,
|
&emailSubject,
|
||||||
"email-subject", "",
|
utils.EmailSubjectFN, "",
|
||||||
"Select backup details for emails with a subject containing this value.")
|
"Select backup details for emails with a subject containing this value.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&emailSender,
|
&emailSender,
|
||||||
"email-sender", "",
|
utils.EmailSenderFN, "",
|
||||||
"Select backup details for emails from a specific sender.")
|
"Select backup details for emails from a specific sender.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&emailReceivedAfter,
|
&emailReceivedAfter,
|
||||||
"email-received-after", "",
|
utils.EmailReceivedAfterFN, "",
|
||||||
"Select backup details for emails received after this datetime.")
|
"Select backup details for emails received after this datetime.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&emailReceivedBefore,
|
&emailReceivedBefore,
|
||||||
"email-received-before", "",
|
utils.EmailReceivedBeforeFN, "",
|
||||||
"Select backup details for emails received before this datetime.")
|
"Select backup details for emails received before this datetime.")
|
||||||
|
|
||||||
// event flags
|
// event flags
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&event,
|
&event,
|
||||||
"event", nil,
|
utils.EventFN, nil,
|
||||||
"Select backup details for events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
|
"Select backup details for events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&eventCalendar,
|
&eventCalendar,
|
||||||
"event-calendar", nil,
|
utils.EventCalendarFN, nil,
|
||||||
"Select backup details for events under a calendar; accepts '"+utils.Wildcard+"' to select all events.")
|
"Select backup details for events under a calendar; accepts '"+utils.Wildcard+"' to select all events.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventSubject,
|
&eventSubject,
|
||||||
"event-subject", "",
|
utils.EventSubjectFN, "",
|
||||||
"Select backup details for events with a subject containing this value.")
|
"Select backup details for events with a subject containing this value.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventOrganizer,
|
&eventOrganizer,
|
||||||
"event-organizer", "",
|
utils.EventOrganizerFN, "",
|
||||||
"Select backup details for events from a specific organizer.")
|
"Select backup details for events from a specific organizer.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventRecurs,
|
&eventRecurs,
|
||||||
"event-recurs", "",
|
utils.EventRecursFN, "",
|
||||||
"Select backup details for recurring events. Use `--event-recurs false` to select non-recurring events.")
|
"Select backup details for recurring events. Use `--event-recurs false` to select non-recurring events.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventStartsAfter,
|
&eventStartsAfter,
|
||||||
"event-starts-after", "",
|
utils.EventStartsAfterFN, "",
|
||||||
"Select backup details for events starting after this datetime.")
|
"Select backup details for events starting after this datetime.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventStartsBefore,
|
&eventStartsBefore,
|
||||||
"event-starts-before", "",
|
utils.EventStartsBeforeFN, "",
|
||||||
"Select backup details for events starting before this datetime.")
|
"Select backup details for events starting before this datetime.")
|
||||||
|
|
||||||
// contact flags
|
// contact flags
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&contact,
|
&contact,
|
||||||
"contact", nil,
|
utils.ContactFN, nil,
|
||||||
"Select backup details for contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
|
"Select backup details for contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&contactFolder,
|
&contactFolder,
|
||||||
"contact-folder", nil,
|
utils.ContactFolderFN, nil,
|
||||||
"Select backup details for contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
|
"Select backup details for contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
|
||||||
|
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&contactName,
|
&contactName,
|
||||||
"contact-name", "",
|
utils.ContactNameFN, "",
|
||||||
"Select backup details for contacts whose contact name contains this value.")
|
"Select backup details for contacts whose contact name contains this value.")
|
||||||
|
|
||||||
case deleteCommand:
|
case deleteCommand:
|
||||||
@ -219,8 +219,10 @@ func addExchangeCommands(parent *cobra.Command) *cobra.Command {
|
|||||||
c.Use = c.Use + " " + exchangeServiceCommandDeleteUseSuffix
|
c.Use = c.Use + " " + exchangeServiceCommandDeleteUseSuffix
|
||||||
c.Example = exchangeServiceCommandDeleteExamples
|
c.Example = exchangeServiceCommandDeleteExamples
|
||||||
|
|
||||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to delete. (required)")
|
fs.StringVar(&backupID,
|
||||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
utils.BackupFN, "",
|
||||||
|
"ID of the backup to delete. (required)")
|
||||||
|
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
@ -401,12 +403,12 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
ctx := cmd.Context()
|
ctx := cmd.Context()
|
||||||
opts := utils.ExchangeOpts{
|
opts := utils.ExchangeOpts{
|
||||||
Contacts: contact,
|
Contact: contact,
|
||||||
ContactFolders: contactFolder,
|
ContactFolder: contactFolder,
|
||||||
Emails: email,
|
Email: email,
|
||||||
EmailFolders: emailFolder,
|
EmailFolder: emailFolder,
|
||||||
Events: event,
|
Event: event,
|
||||||
EventCalendars: eventCalendar,
|
EventCalendar: eventCalendar,
|
||||||
Users: user,
|
Users: user,
|
||||||
ContactName: contactName,
|
ContactName: contactName,
|
||||||
EmailReceivedAfter: emailReceivedAfter,
|
EmailReceivedAfter: emailReceivedAfter,
|
||||||
@ -418,6 +420,8 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
EventStartsAfter: eventStartsAfter,
|
EventStartsAfter: eventStartsAfter,
|
||||||
EventStartsBefore: eventStartsBefore,
|
EventStartsBefore: eventStartsBefore,
|
||||||
EventSubject: eventSubject,
|
EventSubject: eventSubject,
|
||||||
|
|
||||||
|
Populated: utils.GetPopulatedFlags(cmd),
|
||||||
}
|
}
|
||||||
|
|
||||||
s, acct, err := config.GetStorageAndAccount(ctx, true, nil)
|
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"
|
||||||
"github.com/alcionai/corso/src/cli/config"
|
"github.com/alcionai/corso/src/cli/config"
|
||||||
"github.com/alcionai/corso/src/cli/print"
|
"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/connector/exchange"
|
||||||
"github.com/alcionai/corso/src/internal/operations"
|
"github.com/alcionai/corso/src/internal/operations"
|
||||||
"github.com/alcionai/corso/src/internal/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
@ -108,8 +109,8 @@ func (suite *BackupExchangeIntegrationSuite) TestExchangeBackupCmd() {
|
|||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
"backup", "create", "exchange",
|
"backup", "create", "exchange",
|
||||||
"--config-file", suite.cfgFP,
|
"--config-file", suite.cfgFP,
|
||||||
"--user", suite.m365UserID,
|
"--"+utils.UserFN, suite.m365UserID,
|
||||||
"--data", set.String())
|
"--"+utils.DataFN, set.String())
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
cmd.SetOut(&recorder)
|
cmd.SetOut(&recorder)
|
||||||
@ -327,7 +328,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
|||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
"backup", "details", "exchange",
|
"backup", "details", "exchange",
|
||||||
"--config-file", suite.cfgFP,
|
"--config-file", suite.cfgFP,
|
||||||
"--backup", string(bID))
|
"--"+utils.BackupFN, string(bID))
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
cmd.SetOut(&suite.recorder)
|
cmd.SetOut(&suite.recorder)
|
||||||
@ -358,7 +359,7 @@ func (suite *PreparedBackupExchangeIntegrationSuite) TestExchangeDetailsCmd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// At least the prefix of the path should be encoded as folders.
|
// 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(
|
cmd := tester.StubRootCmd(
|
||||||
"backup", "delete", "exchange",
|
"backup", "delete", "exchange",
|
||||||
"--config-file", suite.cfgFP,
|
"--config-file", suite.cfgFP,
|
||||||
"--backup", string(suite.backupOp.Results.BackupID))
|
"--"+utils.BackupFN, string(suite.backupOp.Results.BackupID))
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
// run the command
|
// run the command
|
||||||
@ -467,7 +468,7 @@ func (suite *BackupDeleteExchangeIntegrationSuite) TestExchangeBackupDeleteCmd_U
|
|||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
"backup", "delete", "exchange",
|
"backup", "delete", "exchange",
|
||||||
"--config-file", suite.cfgFP,
|
"--config-file", suite.cfgFP,
|
||||||
"--backup", uuid.NewString())
|
"--"+utils.BackupFN, uuid.NewString())
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
// unknown backupIDs should error since the modelStore can't find the backup
|
// 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.Use = c.Use + " " + oneDriveServiceCommandCreateUseSuffix
|
||||||
c.Example = oneDriveServiceCommandCreateExamples
|
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)")
|
"Backup OneDrive data by user ID; accepts '"+utils.Wildcard+"' to select all users. (required)")
|
||||||
options.AddOperationFlags(c)
|
options.AddOperationFlags(c)
|
||||||
|
|
||||||
@ -96,39 +97,41 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
|
|||||||
c.Use = c.Use + " " + oneDriveServiceCommandDetailsUseSuffix
|
c.Use = c.Use + " " + oneDriveServiceCommandDetailsUseSuffix
|
||||||
c.Example = oneDriveServiceCommandDetailsExamples
|
c.Example = oneDriveServiceCommandDetailsExamples
|
||||||
|
|
||||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to explore. (required)")
|
fs.StringVar(&backupID,
|
||||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
utils.BackupFN, "",
|
||||||
|
"ID of the backup to explore. (required)")
|
||||||
|
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||||
|
|
||||||
// onedrive hierarchy flags
|
// onedrive hierarchy flags
|
||||||
|
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&folderPaths,
|
&folderPaths,
|
||||||
"folder", nil,
|
utils.FolderFN, nil,
|
||||||
"Select backup details by OneDrive folder; defaults to root.")
|
"Select backup details by OneDrive folder; defaults to root.")
|
||||||
|
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&fileNames,
|
&fileNames,
|
||||||
"file", nil,
|
utils.FileFN, nil,
|
||||||
"Select backup details by file name or ID.")
|
"Select backup details by file name or ID.")
|
||||||
|
|
||||||
// onedrive info flags
|
// onedrive info flags
|
||||||
|
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&fileCreatedAfter,
|
&fileCreatedAfter,
|
||||||
"file-created-after", "",
|
utils.FileCreatedAfterFN, "",
|
||||||
"Select backup details for files created after this datetime.")
|
"Select backup details for files created after this datetime.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&fileCreatedBefore,
|
&fileCreatedBefore,
|
||||||
"file-created-before", "",
|
utils.FileCreatedBeforeFN, "",
|
||||||
"Select backup details for files created before this datetime.")
|
"Select backup details for files created before this datetime.")
|
||||||
|
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&fileModifiedAfter,
|
&fileModifiedAfter,
|
||||||
"file-modified-after", "",
|
utils.FileModifiedAfterFN, "",
|
||||||
"Select backup details for files modified after this datetime.")
|
"Select backup details for files modified after this datetime.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&fileModifiedBefore,
|
&fileModifiedBefore,
|
||||||
"file-modified-before", "",
|
utils.FileModifiedBeforeFN, "",
|
||||||
"Select backup details for files modified before this datetime.")
|
"Select backup details for files modified before this datetime.")
|
||||||
|
|
||||||
case deleteCommand:
|
case deleteCommand:
|
||||||
@ -137,8 +140,10 @@ func addOneDriveCommands(parent *cobra.Command) *cobra.Command {
|
|||||||
c.Use = c.Use + " " + oneDriveServiceCommandDeleteUseSuffix
|
c.Use = c.Use + " " + oneDriveServiceCommandDeleteUseSuffix
|
||||||
c.Example = oneDriveServiceCommandDeleteExamples
|
c.Example = oneDriveServiceCommandDeleteExamples
|
||||||
|
|
||||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to delete. (required)")
|
fs.StringVar(&backupID,
|
||||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
utils.BackupFN, "",
|
||||||
|
"ID of the backup to delete. (required)")
|
||||||
|
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
@ -311,13 +316,15 @@ func detailsOneDriveCmd(cmd *cobra.Command, args []string) error {
|
|||||||
defer utils.CloseRepo(ctx, r)
|
defer utils.CloseRepo(ctx, r)
|
||||||
|
|
||||||
opts := utils.OneDriveOpts{
|
opts := utils.OneDriveOpts{
|
||||||
Users: user,
|
Users: user,
|
||||||
Paths: folderPaths,
|
Paths: folderPaths,
|
||||||
Names: fileNames,
|
Names: fileNames,
|
||||||
CreatedAfter: fileCreatedAfter,
|
FileCreatedAfter: fileCreatedAfter,
|
||||||
CreatedBefore: fileCreatedBefore,
|
FileCreatedBefore: fileCreatedBefore,
|
||||||
ModifiedAfter: fileModifiedAfter,
|
FileModifiedAfter: fileModifiedAfter,
|
||||||
ModifiedBefore: fileModifiedBefore,
|
FileModifiedBefore: fileModifiedBefore,
|
||||||
|
|
||||||
|
Populated: utils.GetPopulatedFlags(cmd),
|
||||||
}
|
}
|
||||||
|
|
||||||
ds, err := runDetailsOneDriveCmd(ctx, r, backupID, opts)
|
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:
|
// 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.
|
// More generic (ex: --user) and more frequently used flags take precedence.
|
||||||
// general flags
|
// general flags
|
||||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to restore. (required)")
|
fs.StringVar(&backupID,
|
||||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
utils.BackupFN, "",
|
||||||
|
"ID of the backup to restore. (required)")
|
||||||
|
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||||
|
|
||||||
fs.StringSliceVar(&user,
|
fs.StringSliceVar(&user,
|
||||||
"user", nil,
|
utils.UserFN, nil,
|
||||||
"Restore data by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
"Restore data by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
||||||
|
|
||||||
// email flags
|
// email flags
|
||||||
fs.StringSliceVar(&email,
|
fs.StringSliceVar(&email,
|
||||||
"email", nil,
|
utils.EmailFN, nil,
|
||||||
"Restore emails by ID; accepts '"+utils.Wildcard+"' to select all emails.")
|
"Restore emails by ID; accepts '"+utils.Wildcard+"' to select all emails.")
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&emailFolder,
|
&emailFolder,
|
||||||
"email-folder", nil,
|
utils.EmailFolderFN, nil,
|
||||||
"Restore emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
|
"Restore emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&emailSubject,
|
&emailSubject,
|
||||||
"email-subject", "",
|
utils.EmailSubjectFN, "",
|
||||||
"Restore emails with a subject containing this value.")
|
"Restore emails with a subject containing this value.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&emailSender,
|
&emailSender,
|
||||||
"email-sender", "",
|
utils.EmailSenderFN, "",
|
||||||
"Restore emails from a specific sender.")
|
"Restore emails from a specific sender.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&emailReceivedAfter,
|
&emailReceivedAfter,
|
||||||
"email-received-after", "",
|
utils.EmailReceivedAfterFN, "",
|
||||||
"Restore emails received after this datetime.")
|
"Restore emails received after this datetime.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&emailReceivedBefore,
|
&emailReceivedBefore,
|
||||||
"email-received-before", "",
|
utils.EmailReceivedBeforeFN, "",
|
||||||
"Restore emails received before this datetime.")
|
"Restore emails received before this datetime.")
|
||||||
|
|
||||||
// event flags
|
// event flags
|
||||||
fs.StringSliceVar(&event,
|
fs.StringSliceVar(&event,
|
||||||
"event", nil,
|
utils.EventFN, nil,
|
||||||
"Restore events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
|
"Restore events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&eventCalendar,
|
&eventCalendar,
|
||||||
"event-calendar", nil,
|
utils.EventCalendarFN, nil,
|
||||||
"Restore events under a calendar; accepts '"+utils.Wildcard+"' to select all event calendars.")
|
"Restore events under a calendar; accepts '"+utils.Wildcard+"' to select all event calendars.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventSubject,
|
&eventSubject,
|
||||||
"event-subject", "",
|
utils.EventSubjectFN, "",
|
||||||
"Restore events with a subject containing this value.")
|
"Restore events with a subject containing this value.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventOrganizer,
|
&eventOrganizer,
|
||||||
"event-organizer", "",
|
utils.EventOrganizerFN, "",
|
||||||
"Restore events from a specific organizer.")
|
"Restore events from a specific organizer.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventRecurs,
|
&eventRecurs,
|
||||||
"event-recurs", "",
|
utils.EventRecursFN, "",
|
||||||
"Restore recurring events. Use `--event-recurs false` to restore non-recurring events.")
|
"Restore recurring events. Use `--event-recurs false` to restore non-recurring events.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventStartsAfter,
|
&eventStartsAfter,
|
||||||
"event-starts-after", "",
|
utils.EventStartsAfterFN, "",
|
||||||
"Restore events starting after this datetime.")
|
"Restore events starting after this datetime.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&eventStartsBefore,
|
&eventStartsBefore,
|
||||||
"event-starts-before", "",
|
utils.EventStartsBeforeFN, "",
|
||||||
"Restore events starting before this datetime.")
|
"Restore events starting before this datetime.")
|
||||||
|
|
||||||
// contacts flags
|
// contacts flags
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&contact,
|
&contact,
|
||||||
"contact", nil,
|
utils.ContactFN, nil,
|
||||||
"Restore contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
|
"Restore contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&contactFolder,
|
&contactFolder,
|
||||||
"contact-folder", nil,
|
utils.ContactFolderFN, nil,
|
||||||
"Restore contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
|
"Restore contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&contactName,
|
&contactName,
|
||||||
"contact-name", "",
|
utils.ContactNameFN, "",
|
||||||
"Restore contacts whose contact name contains this value.")
|
"Restore contacts whose contact name contains this value.")
|
||||||
|
|
||||||
// others
|
// others
|
||||||
@ -177,12 +179,12 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts := utils.ExchangeOpts{
|
opts := utils.ExchangeOpts{
|
||||||
Contacts: contact,
|
Contact: contact,
|
||||||
ContactFolders: contactFolder,
|
ContactFolder: contactFolder,
|
||||||
Emails: email,
|
Email: email,
|
||||||
EmailFolders: emailFolder,
|
EmailFolder: emailFolder,
|
||||||
Events: event,
|
Event: event,
|
||||||
EventCalendars: eventCalendar,
|
EventCalendar: eventCalendar,
|
||||||
Users: user,
|
Users: user,
|
||||||
ContactName: contactName,
|
ContactName: contactName,
|
||||||
EmailReceivedAfter: emailReceivedAfter,
|
EmailReceivedAfter: emailReceivedAfter,
|
||||||
@ -194,6 +196,8 @@ func restoreExchangeCmd(cmd *cobra.Command, args []string) error {
|
|||||||
EventStartsAfter: eventStartsAfter,
|
EventStartsAfter: eventStartsAfter,
|
||||||
EventStartsBefore: eventStartsBefore,
|
EventStartsBefore: eventStartsBefore,
|
||||||
EventSubject: eventSubject,
|
EventSubject: eventSubject,
|
||||||
|
|
||||||
|
Populated: utils.GetPopulatedFlags(cmd),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := utils.ValidateExchangeRestoreFlags(backupID, opts); err != nil {
|
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"
|
||||||
"github.com/alcionai/corso/src/cli/config"
|
"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/connector/exchange"
|
||||||
"github.com/alcionai/corso/src/internal/operations"
|
"github.com/alcionai/corso/src/internal/operations"
|
||||||
"github.com/alcionai/corso/src/internal/tester"
|
"github.com/alcionai/corso/src/internal/tester"
|
||||||
@ -136,7 +137,7 @@ func (suite *RestoreExchangeIntegrationSuite) TestExchangeRestoreCmd() {
|
|||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
"restore", "exchange",
|
"restore", "exchange",
|
||||||
"--config-file", suite.cfgFP,
|
"--config-file", suite.cfgFP,
|
||||||
"--backup", string(suite.backupOps[set].Results.BackupID))
|
"--"+utils.BackupFN, string(suite.backupOps[set].Results.BackupID))
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
// run the command
|
// run the command
|
||||||
@ -160,15 +161,15 @@ func (suite *RestoreExchangeIntegrationSuite) TestExchangeRestoreCmd_badTimeFlag
|
|||||||
var timeFilter string
|
var timeFilter string
|
||||||
switch set {
|
switch set {
|
||||||
case email:
|
case email:
|
||||||
timeFilter = "--email-received-after"
|
timeFilter = "--" + utils.EmailReceivedAfterFN
|
||||||
case events:
|
case events:
|
||||||
timeFilter = "--event-starts-after"
|
timeFilter = "--" + utils.EventStartsAfterFN
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
"restore", "exchange",
|
"restore", "exchange",
|
||||||
"--config-file", suite.cfgFP,
|
"--config-file", suite.cfgFP,
|
||||||
"--backup", string(suite.backupOps[set].Results.BackupID),
|
"--"+utils.BackupFN, string(suite.backupOps[set].Results.BackupID),
|
||||||
timeFilter, "smarf")
|
timeFilter, "smarf")
|
||||||
cli.BuildCommandTree(cmd)
|
cli.BuildCommandTree(cmd)
|
||||||
|
|
||||||
@ -192,13 +193,13 @@ func (suite *RestoreExchangeIntegrationSuite) TestExchangeRestoreCmd_badBoolFlag
|
|||||||
var timeFilter string
|
var timeFilter string
|
||||||
switch set {
|
switch set {
|
||||||
case events:
|
case events:
|
||||||
timeFilter = "--event-recurs"
|
timeFilter = "--" + utils.EventRecursFN
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := tester.StubRootCmd(
|
cmd := tester.StubRootCmd(
|
||||||
"restore", "exchange",
|
"restore", "exchange",
|
||||||
"--config-file", suite.cfgFP,
|
"--config-file", suite.cfgFP,
|
||||||
"--backup", string(suite.backupOps[set].Results.BackupID),
|
"--"+utils.BackupFN, string(suite.backupOps[set].Results.BackupID),
|
||||||
timeFilter, "wingbat")
|
timeFilter, "wingbat")
|
||||||
cli.BuildCommandTree(cmd)
|
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.
|
// More generic (ex: --user) and more frequently used flags take precedence.
|
||||||
fs.SortFlags = false
|
fs.SortFlags = false
|
||||||
|
|
||||||
fs.StringVar(&backupID, "backup", "", "ID of the backup to restore. (required)")
|
fs.StringVar(&backupID,
|
||||||
cobra.CheckErr(c.MarkFlagRequired("backup"))
|
utils.BackupFN, "",
|
||||||
|
"ID of the backup to restore. (required)")
|
||||||
|
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
|
||||||
|
|
||||||
fs.StringSliceVar(&user,
|
fs.StringSliceVar(&user,
|
||||||
"user", nil,
|
utils.UserFN, nil,
|
||||||
"Restore data by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
"Restore data by user ID; accepts '"+utils.Wildcard+"' to select all users.")
|
||||||
|
|
||||||
// onedrive hierarchy (path/name) flags
|
// onedrive hierarchy (path/name) flags
|
||||||
|
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&folderPaths,
|
&folderPaths,
|
||||||
"folder", nil,
|
utils.FolderFN, nil,
|
||||||
"Restore items by OneDrive folder; defaults to root")
|
"Restore items by OneDrive folder; defaults to root")
|
||||||
|
|
||||||
fs.StringSliceVar(
|
fs.StringSliceVar(
|
||||||
&fileNames,
|
&fileNames,
|
||||||
"file", nil,
|
utils.FileFN, nil,
|
||||||
"Restore items by file name or ID")
|
"Restore items by file name or ID")
|
||||||
|
|
||||||
// onedrive info flags
|
// onedrive info flags
|
||||||
|
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&fileCreatedAfter,
|
&fileCreatedAfter,
|
||||||
"file-created-after", "",
|
utils.FileCreatedAfterFN, "",
|
||||||
"Restore files created after this datetime")
|
"Restore files created after this datetime")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&fileCreatedBefore,
|
&fileCreatedBefore,
|
||||||
"file-created-before", "",
|
utils.FileCreatedBeforeFN, "",
|
||||||
"Restore files created before this datetime")
|
"Restore files created before this datetime")
|
||||||
|
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&fileModifiedAfter,
|
&fileModifiedAfter,
|
||||||
"file-modified-after", "",
|
utils.FileModifiedAfterFN, "",
|
||||||
"Restore files modified after this datetime")
|
"Restore files modified after this datetime")
|
||||||
fs.StringVar(
|
fs.StringVar(
|
||||||
&fileModifiedBefore,
|
&fileModifiedBefore,
|
||||||
"file-modified-before", "",
|
utils.FileModifiedBeforeFN, "",
|
||||||
"Restore files modified before this datetime")
|
"Restore files modified before this datetime")
|
||||||
|
|
||||||
// others
|
// others
|
||||||
@ -124,13 +126,15 @@ func restoreOneDriveCmd(cmd *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts := utils.OneDriveOpts{
|
opts := utils.OneDriveOpts{
|
||||||
Users: user,
|
Users: user,
|
||||||
Paths: folderPaths,
|
Paths: folderPaths,
|
||||||
Names: fileNames,
|
Names: fileNames,
|
||||||
CreatedAfter: fileCreatedAfter,
|
FileCreatedAfter: fileCreatedAfter,
|
||||||
CreatedBefore: fileCreatedBefore,
|
FileCreatedBefore: fileCreatedBefore,
|
||||||
ModifiedAfter: fileModifiedAfter,
|
FileModifiedAfter: fileModifiedAfter,
|
||||||
ModifiedBefore: fileModifiedBefore,
|
FileModifiedBefore: fileModifiedBefore,
|
||||||
|
|
||||||
|
Populated: utils.GetPopulatedFlags(cmd),
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := utils.ValidateOneDriveRestoreFlags(backupID, opts); err != nil {
|
if err := utils.ValidateOneDriveRestoreFlags(backupID, opts); err != nil {
|
||||||
|
|||||||
@ -6,13 +6,33 @@ import (
|
|||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"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 {
|
type ExchangeOpts struct {
|
||||||
Contacts []string
|
Contact []string
|
||||||
ContactFolders []string
|
ContactFolder []string
|
||||||
Emails []string
|
Email []string
|
||||||
EmailFolders []string
|
EmailFolder []string
|
||||||
Events []string
|
Event []string
|
||||||
EventCalendars []string
|
EventCalendar []string
|
||||||
Users []string
|
Users []string
|
||||||
ContactName string
|
ContactName string
|
||||||
EmailReceivedAfter string
|
EmailReceivedAfter string
|
||||||
@ -24,6 +44,8 @@ type ExchangeOpts struct {
|
|||||||
EventStartsAfter string
|
EventStartsAfter string
|
||||||
EventStartsBefore string
|
EventStartsBefore string
|
||||||
EventSubject string
|
EventSubject string
|
||||||
|
|
||||||
|
Populated PopulatedFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddExchangeInclude adds the scope of the provided values to the selector's
|
// 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")
|
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")
|
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")
|
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")
|
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")
|
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")
|
return errors.New("invalid format for event-recurs")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,9 +128,9 @@ func IncludeExchangeRestoreDataSelectors(
|
|||||||
sel *selectors.ExchangeRestore,
|
sel *selectors.ExchangeRestore,
|
||||||
opts ExchangeOpts,
|
opts ExchangeOpts,
|
||||||
) {
|
) {
|
||||||
lc, lcf := len(opts.Contacts), len(opts.ContactFolders)
|
lc, lcf := len(opts.Contact), len(opts.ContactFolder)
|
||||||
le, lef := len(opts.Emails), len(opts.EmailFolders)
|
le, lef := len(opts.Email), len(opts.EmailFolder)
|
||||||
lev, lec := len(opts.Events), len(opts.EventCalendars)
|
lev, lec := len(opts.Event), len(opts.EventCalendar)
|
||||||
// either scope the request to a set of users
|
// either scope the request to a set of users
|
||||||
if lc+lcf+le+lef+lev+lec == 0 {
|
if lc+lcf+le+lef+lev+lec == 0 {
|
||||||
if len(opts.Users) == 0 {
|
if len(opts.Users) == 0 {
|
||||||
@ -121,9 +143,9 @@ func IncludeExchangeRestoreDataSelectors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// or add selectors for each type of data
|
// or add selectors for each type of data
|
||||||
AddExchangeInclude(sel, opts.Users, opts.ContactFolders, opts.Contacts, sel.Contacts)
|
AddExchangeInclude(sel, opts.Users, opts.ContactFolder, opts.Contact, sel.Contacts)
|
||||||
AddExchangeInclude(sel, opts.Users, opts.EmailFolders, opts.Emails, sel.Mails)
|
AddExchangeInclude(sel, opts.Users, opts.EmailFolder, opts.Email, sel.Mails)
|
||||||
AddExchangeInclude(sel, opts.Users, opts.EventCalendars, opts.Events, sel.Events)
|
AddExchangeInclude(sel, opts.Users, opts.EventCalendar, opts.Event, sel.Events)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterExchangeRestoreInfoSelectors builds the common info-selector filters.
|
// FilterExchangeRestoreInfoSelectors builds the common info-selector filters.
|
||||||
|
|||||||
@ -94,207 +94,207 @@ func (suite *ExchangeUtilsSuite) TestIncludeExchangeBackupDetailDataSelectors()
|
|||||||
{
|
{
|
||||||
name: "any users, any data",
|
name: "any users, any data",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: a,
|
Contact: a,
|
||||||
ContactFolders: a,
|
ContactFolder: a,
|
||||||
Emails: a,
|
Email: a,
|
||||||
EmailFolders: a,
|
EmailFolder: a,
|
||||||
Events: a,
|
Event: a,
|
||||||
EventCalendars: a,
|
EventCalendar: a,
|
||||||
Users: a,
|
Users: a,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 3,
|
expectIncludeLen: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "any users, any folders",
|
name: "any users, any folders",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
ContactFolders: a,
|
ContactFolder: a,
|
||||||
EmailFolders: a,
|
EmailFolder: a,
|
||||||
EventCalendars: a,
|
EventCalendar: a,
|
||||||
Users: a,
|
Users: a,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 3,
|
expectIncludeLen: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single user, single of each data",
|
name: "single user, single of each data",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: stub,
|
Contact: stub,
|
||||||
ContactFolders: stub,
|
ContactFolder: stub,
|
||||||
Emails: stub,
|
Email: stub,
|
||||||
EmailFolders: stub,
|
EmailFolder: stub,
|
||||||
Events: stub,
|
Event: stub,
|
||||||
EventCalendars: stub,
|
EventCalendar: stub,
|
||||||
Users: stub,
|
Users: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 3,
|
expectIncludeLen: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single user, single of each folder",
|
name: "single user, single of each folder",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
ContactFolders: stub,
|
ContactFolder: stub,
|
||||||
EmailFolders: stub,
|
EmailFolder: stub,
|
||||||
EventCalendars: stub,
|
EventCalendar: stub,
|
||||||
Users: stub,
|
Users: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 3,
|
expectIncludeLen: 3,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "any users, contacts",
|
name: "any users, contacts",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: a,
|
Contact: a,
|
||||||
ContactFolders: stub,
|
ContactFolder: stub,
|
||||||
Users: a,
|
Users: a,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single user, contacts",
|
name: "single user, contacts",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: stub,
|
Contact: stub,
|
||||||
ContactFolders: stub,
|
ContactFolder: stub,
|
||||||
Users: stub,
|
Users: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "any users, emails",
|
name: "any users, emails",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Emails: a,
|
Email: a,
|
||||||
EmailFolders: stub,
|
EmailFolder: stub,
|
||||||
Users: a,
|
Users: a,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single user, emails",
|
name: "single user, emails",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Emails: stub,
|
Email: stub,
|
||||||
EmailFolders: stub,
|
EmailFolder: stub,
|
||||||
Users: stub,
|
Users: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "any users, events",
|
name: "any users, events",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Events: a,
|
Event: a,
|
||||||
EventCalendars: a,
|
EventCalendar: a,
|
||||||
Users: a,
|
Users: a,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single user, events",
|
name: "single user, events",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Events: stub,
|
Event: stub,
|
||||||
EventCalendars: stub,
|
EventCalendar: stub,
|
||||||
Users: stub,
|
Users: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "any users, contacts + email",
|
name: "any users, contacts + email",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: a,
|
Contact: a,
|
||||||
ContactFolders: a,
|
ContactFolder: a,
|
||||||
Emails: a,
|
Email: a,
|
||||||
EmailFolders: a,
|
EmailFolder: a,
|
||||||
Users: a,
|
Users: a,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 2,
|
expectIncludeLen: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single users, contacts + email",
|
name: "single users, contacts + email",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: stub,
|
Contact: stub,
|
||||||
ContactFolders: stub,
|
ContactFolder: stub,
|
||||||
Emails: stub,
|
Email: stub,
|
||||||
EmailFolders: stub,
|
EmailFolder: stub,
|
||||||
Users: stub,
|
Users: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 2,
|
expectIncludeLen: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "any users, email + event",
|
name: "any users, email + event",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Emails: a,
|
Email: a,
|
||||||
EmailFolders: a,
|
EmailFolder: a,
|
||||||
Events: a,
|
Event: a,
|
||||||
EventCalendars: a,
|
EventCalendar: a,
|
||||||
Users: a,
|
Users: a,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 2,
|
expectIncludeLen: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single users, email + event",
|
name: "single users, email + event",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Emails: stub,
|
Email: stub,
|
||||||
EmailFolders: stub,
|
EmailFolder: stub,
|
||||||
Events: stub,
|
Event: stub,
|
||||||
EventCalendars: stub,
|
EventCalendar: stub,
|
||||||
Users: stub,
|
Users: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 2,
|
expectIncludeLen: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "any users, event + contact",
|
name: "any users, event + contact",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: a,
|
Contact: a,
|
||||||
ContactFolders: a,
|
ContactFolder: a,
|
||||||
Events: a,
|
Event: a,
|
||||||
EventCalendars: a,
|
EventCalendar: a,
|
||||||
Users: a,
|
Users: a,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 2,
|
expectIncludeLen: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "single users, event + contact",
|
name: "single users, event + contact",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: stub,
|
Contact: stub,
|
||||||
ContactFolders: stub,
|
ContactFolder: stub,
|
||||||
Events: stub,
|
Event: stub,
|
||||||
EventCalendars: stub,
|
EventCalendar: stub,
|
||||||
Users: stub,
|
Users: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 2,
|
expectIncludeLen: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "many users, events",
|
name: "many users, events",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Events: many,
|
Event: many,
|
||||||
EventCalendars: many,
|
EventCalendar: many,
|
||||||
Users: many,
|
Users: many,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "many users, events + contacts",
|
name: "many users, events + contacts",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: many,
|
Contact: many,
|
||||||
ContactFolders: many,
|
ContactFolder: many,
|
||||||
Events: many,
|
Event: many,
|
||||||
EventCalendars: many,
|
EventCalendar: many,
|
||||||
Users: many,
|
Users: many,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 2,
|
expectIncludeLen: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mail, no folder or user",
|
name: "mail, no folder or user",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Emails: stub,
|
Email: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "contacts, no folder or user",
|
name: "contacts, no folder or user",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Contacts: stub,
|
Contact: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
expectIncludeLen: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "event, no folder or user",
|
name: "event, no folder or user",
|
||||||
opts: utils.ExchangeOpts{
|
opts: utils.ExchangeOpts{
|
||||||
Events: stub,
|
Event: stub,
|
||||||
},
|
},
|
||||||
expectIncludeLen: 1,
|
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"
|
"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 {
|
type OneDriveOpts struct {
|
||||||
Users []string
|
Users []string
|
||||||
Names []string
|
Names []string
|
||||||
Paths []string
|
Paths []string
|
||||||
CreatedAfter string
|
FileCreatedAfter string
|
||||||
CreatedBefore string
|
FileCreatedBefore string
|
||||||
ModifiedAfter string
|
FileModifiedAfter string
|
||||||
ModifiedBefore string
|
FileModifiedBefore string
|
||||||
|
|
||||||
|
Populated PopulatedFlags
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateOneDriveRestoreFlags checks common flags for correctness and interdependencies
|
// 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")
|
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")
|
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")
|
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")
|
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")
|
return errors.New("invalid time format for modified-before")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,8 +103,8 @@ func FilterOneDriveRestoreInfoSelectors(
|
|||||||
sel *selectors.OneDriveRestore,
|
sel *selectors.OneDriveRestore,
|
||||||
opts OneDriveOpts,
|
opts OneDriveOpts,
|
||||||
) {
|
) {
|
||||||
AddOneDriveFilter(sel, opts.CreatedAfter, sel.CreatedAfter)
|
AddOneDriveFilter(sel, opts.FileCreatedAfter, sel.CreatedAfter)
|
||||||
AddOneDriveFilter(sel, opts.CreatedBefore, sel.CreatedBefore)
|
AddOneDriveFilter(sel, opts.FileCreatedBefore, sel.CreatedBefore)
|
||||||
AddOneDriveFilter(sel, opts.ModifiedAfter, sel.ModifiedAfter)
|
AddOneDriveFilter(sel, opts.FileModifiedAfter, sel.ModifiedAfter)
|
||||||
AddOneDriveFilter(sel, opts.ModifiedBefore, sel.ModifiedBefore)
|
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",
|
Name: "BadEmailReceiveAfter",
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
EmailReceivedAfter: "foo",
|
EmailReceivedAfter: "foo",
|
||||||
|
Populated: utils.PopulatedFlags{
|
||||||
|
utils.EmailReceivedAfterFN: struct{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "EmptyEmailReceiveAfter",
|
||||||
|
Opts: utils.ExchangeOpts{
|
||||||
|
EmailReceivedAfter: "",
|
||||||
|
Populated: utils.PopulatedFlags{
|
||||||
|
utils.EmailReceivedAfterFN: struct{}{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "BadEmailReceiveBefore",
|
Name: "BadEmailReceiveBefore",
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
EmailReceivedBefore: "foo",
|
EmailReceivedBefore: "foo",
|
||||||
|
Populated: utils.PopulatedFlags{
|
||||||
|
utils.EmailReceivedBeforeFN: struct{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "EmptyEmailReceiveBefore",
|
||||||
|
Opts: utils.ExchangeOpts{
|
||||||
|
EmailReceivedBefore: "",
|
||||||
|
Populated: utils.PopulatedFlags{
|
||||||
|
utils.EmailReceivedBeforeFN: struct{}{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "BadEventRecurs",
|
Name: "BadEventRecurs",
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
EventRecurs: "foo",
|
EventRecurs: "foo",
|
||||||
|
Populated: utils.PopulatedFlags{
|
||||||
|
utils.EventRecursFN: struct{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "EmptyEventRecurs",
|
||||||
|
Opts: utils.ExchangeOpts{
|
||||||
|
EventRecurs: "",
|
||||||
|
Populated: utils.PopulatedFlags{
|
||||||
|
utils.EventRecursFN: struct{}{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "BadEventStartsAfter",
|
Name: "BadEventStartsAfter",
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
EventStartsAfter: "foo",
|
EventStartsAfter: "foo",
|
||||||
|
Populated: utils.PopulatedFlags{
|
||||||
|
utils.EventStartsAfterFN: struct{}{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "EmptyEventStartsAfter",
|
||||||
|
Opts: utils.ExchangeOpts{
|
||||||
|
EventStartsAfter: "",
|
||||||
|
Populated: utils.PopulatedFlags{
|
||||||
|
utils.EventStartsAfterFN: struct{}{},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "BadEventStartsBefore",
|
Name: "BadEventStartsBefore",
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
EventStartsBefore: "foo",
|
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",
|
Name: "Emails",
|
||||||
Expected: testdata.ExchangeEmailItems,
|
Expected: testdata.ExchangeEmailItems,
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
Emails: selectors.Any(),
|
Email: selectors.Any(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "EmailsFolderPrefixMatch",
|
Name: "EmailsFolderPrefixMatch",
|
||||||
Expected: testdata.ExchangeEmailItems,
|
Expected: testdata.ExchangeEmailItems,
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
EmailFolders: []string{testdata.ExchangeEmailInboxPath.Folder()},
|
EmailFolder: []string{testdata.ExchangeEmailInboxPath.Folder()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -109,21 +169,21 @@ var (
|
|||||||
Name: "MailID",
|
Name: "MailID",
|
||||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
Emails: []string{testdata.ExchangeEmailItemPath1.Item()},
|
Email: []string{testdata.ExchangeEmailItemPath1.Item()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "MailShortRef",
|
Name: "MailShortRef",
|
||||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
Emails: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
Email: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "MultipleMailShortRef",
|
Name: "MultipleMailShortRef",
|
||||||
Expected: testdata.ExchangeEmailItems,
|
Expected: testdata.ExchangeEmailItems,
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
Emails: []string{
|
Email: []string{
|
||||||
testdata.ExchangeEmailItemPath1.ShortRef(),
|
testdata.ExchangeEmailItemPath1.ShortRef(),
|
||||||
testdata.ExchangeEmailItemPath2.ShortRef(),
|
testdata.ExchangeEmailItemPath2.ShortRef(),
|
||||||
},
|
},
|
||||||
@ -134,7 +194,7 @@ var (
|
|||||||
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
Expected: []details.DetailsEntry{testdata.ExchangeEmailItems[0]},
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
EmailSubject: "foo",
|
EmailSubject: "foo",
|
||||||
Events: selectors.Any(),
|
Event: selectors.Any(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -152,8 +212,8 @@ var (
|
|||||||
testdata.ExchangeEventsItems[0],
|
testdata.ExchangeEventsItems[0],
|
||||||
},
|
},
|
||||||
Opts: utils.ExchangeOpts{
|
Opts: utils.ExchangeOpts{
|
||||||
Emails: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
Email: []string{testdata.ExchangeEmailItemPath1.ShortRef()},
|
||||||
Events: []string{testdata.ExchangeEventsItemPath1.ShortRef()},
|
Event: []string{testdata.ExchangeEventsItemPath1.ShortRef()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,15 +4,20 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
|
|
||||||
"github.com/alcionai/corso/src/internal/common"
|
|
||||||
"github.com/alcionai/corso/src/pkg/repository"
|
"github.com/alcionai/corso/src/pkg/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// common flag names
|
||||||
|
const (
|
||||||
|
BackupFN = "backup"
|
||||||
|
DataFN = "data"
|
||||||
|
UserFN = "user"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Wildcard = "*"
|
Wildcard = "*"
|
||||||
)
|
)
|
||||||
@ -59,30 +64,3 @@ func AddCommand(parent, c *cobra.Command) (*cobra.Command, *pflag.FlagSet) {
|
|||||||
|
|
||||||
return c, c.Flags()
|
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