Compare commits

...

7 Commits
main ... 2786-2

Author SHA1 Message Date
ryanfkeepers
6f74337e75 fix exchange details website linting 2023-03-17 15:12:51 -06:00
Keepers
b668fbec4c make all sharepoint flags singular (#2839) 2023-03-17 15:00:27 -06:00
Keepers
61c64d610e --web-url to --site (#2838)
Changes ---web-url to --site, and changes --site
to --site-id.  Site-id is hidden to prevent confusion for end users.
2023-03-17 15:00:27 -06:00
Keepers
a54f8a02f4 centralize details, restore flags (#2821)
Centralizes details and restore flags for all 3
m365 services.
2023-03-17 15:00:26 -06:00
ryanfkeepers
b79e06cfb0 add drive name to queue count observe 2023-03-17 14:57:32 -06:00
ryanfkeepers
353a9682f4 spaces instead of tabs for sharepoint restore help 2023-03-17 14:56:22 -06:00
ryanfkeepers
f80c5575b4 update sharepoint cli examples
Updates the sharepoint cli examples to better
reflect the current support and utilities.
2023-03-17 14:56:21 -06:00
17 changed files with 495 additions and 658 deletions

View File

@ -26,28 +26,7 @@ import (
// exchange bucket info from flags // exchange bucket info from flags
var ( var (
backupID string
exchangeData []string exchangeData []string
user []string
contact []string
contactFolder []string
contactName string
email []string
emailFolder []string
emailReceivedAfter string
emailReceivedBefore string
emailSender string
emailSubject string
event []string
eventCalendar []string
eventOrganizer string
eventRecurs string
eventStartsAfter string
eventStartsBefore string
eventSubject string
) )
const ( const (
@ -81,15 +60,15 @@ corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --user a
# Explore Alice's emails with subject containing "Hello world" in folder "Inbox" from a specific backup # Explore Alice's emails with subject containing "Hello world" in folder "Inbox" from a specific backup
corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --email-subject "Hello world" --email-folder Inbox --user alice@example.com --email-subject "Hello world" --email-folder Inbox
# Explore Bobs's events occurring after start of 2022 from a specific backup # Explore Bobs's events occurring after start of 2022 from a specific backup
corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user bob@example.com --event-starts-after 2022-01-01T00:00:00 --user bob@example.com --event-starts-after 2022-01-01T00:00:00
# Explore Alice's contacts with name containing Andy from a specific backup # Explore Alice's contacts with name containing Andy from a specific backup
corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso backup details exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --contact-name Andy` --user alice@example.com --contact-name Andy`
) )
// called by backup.go to map subcommands to provider-specific handling. // called by backup.go to map subcommands to provider-specific handling.
@ -109,10 +88,8 @@ func addExchangeCommands(cmd *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.StringSliceVar( utils.AddUserFlag(c)
&user,
utils.UserFN, nil,
"Backup Exchange data by a user's email; accepts '"+utils.Wildcard+"' to select all users")
fs.StringSliceVar( fs.StringSliceVar(
&exchangeData, &exchangeData,
utils.DataFN, nil, utils.DataFN, nil,
@ -121,17 +98,15 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command {
case listCommand: case listCommand:
c, fs = utils.AddCommand(cmd, exchangeListCmd()) c, fs = utils.AddCommand(cmd, exchangeListCmd())
fs.SortFlags = false
fs.StringVar(&backupID, utils.AddBackupIDFlag(c, false)
"backup", "",
"Display a specific backup, including the items that failed or were skipped during processing.")
addFailedItemsFN(c) addFailedItemsFN(c)
addSkippedItemsFN(c) addSkippedItemsFN(c)
addRecoveredErrorsFN(c) addRecoveredErrorsFN(c)
case detailsCommand: case detailsCommand:
c, fs = utils.AddCommand(cmd, exchangeDetailsCmd()) c, _ = utils.AddCommand(cmd, exchangeDetailsCmd())
c.Use = c.Use + " " + exchangeServiceCommandDetailsUseSuffix c.Use = c.Use + " " + exchangeServiceCommandDetailsUseSuffix
c.Example = exchangeServiceCommandDetailsExamples c.Example = exchangeServiceCommandDetailsExamples
@ -140,95 +115,16 @@ func addExchangeCommands(cmd *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, utils.AddBackupIDFlag(c, true)
utils.BackupFN, "", utils.AddExchangeDetailsAndRestoreFlags(c)
"ID of the backup to explore. (required)")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
fs.StringSliceVar(
&user,
utils.UserFN, nil,
"Select backup details by user ID; accepts '"+utils.Wildcard+"' to select all users.")
// email flags
fs.StringSliceVar(
&email,
utils.EmailFN, nil,
"Select backup details for emails by email ID; accepts '"+utils.Wildcard+"' to select all emails.")
fs.StringSliceVar(
&emailFolder,
utils.EmailFolderFN, nil,
"Select backup details for emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
fs.StringVar(
&emailSubject,
utils.EmailSubjectFN, "",
"Select backup details for emails with a subject containing this value.")
fs.StringVar(
&emailSender,
utils.EmailSenderFN, "",
"Select backup details for emails from a specific sender.")
fs.StringVar(
&emailReceivedAfter,
utils.EmailReceivedAfterFN, "",
"Select backup details for emails received after this datetime.")
fs.StringVar(
&emailReceivedBefore,
utils.EmailReceivedBeforeFN, "",
"Select backup details for emails received before this datetime.")
// event flags
fs.StringSliceVar(
&event,
utils.EventFN, nil,
"Select backup details for events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
fs.StringSliceVar(
&eventCalendar,
utils.EventCalendarFN, nil,
"Select backup details for events under a calendar; accepts '"+utils.Wildcard+"' to select all events.")
fs.StringVar(
&eventSubject,
utils.EventSubjectFN, "",
"Select backup details for events with a subject containing this value.")
fs.StringVar(
&eventOrganizer,
utils.EventOrganizerFN, "",
"Select backup details for events from a specific organizer.")
fs.StringVar(
&eventRecurs,
utils.EventRecursFN, "",
"Select backup details for recurring events. Use `--event-recurs false` to select non-recurring events.")
fs.StringVar(
&eventStartsAfter,
utils.EventStartsAfterFN, "",
"Select backup details for events starting after this datetime.")
fs.StringVar(
&eventStartsBefore,
utils.EventStartsBeforeFN, "",
"Select backup details for events starting before this datetime.")
// contact flags
fs.StringSliceVar(
&contact,
utils.ContactFN, nil,
"Select backup details for contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
fs.StringSliceVar(
&contactFolder,
utils.ContactFolderFN, nil,
"Select backup details for contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
fs.StringVar(
&contactName,
utils.ContactNameFN, "",
"Select backup details for contacts whose contact name contains this value.")
case deleteCommand: case deleteCommand:
c, fs = utils.AddCommand(cmd, exchangeDeleteCmd()) c, _ = utils.AddCommand(cmd, exchangeDeleteCmd())
c.Use = c.Use + " " + exchangeServiceCommandDeleteUseSuffix c.Use = c.Use + " " + exchangeServiceCommandDeleteUseSuffix
c.Example = exchangeServiceCommandDeleteExamples c.Example = exchangeServiceCommandDeleteExamples
fs.StringVar(&backupID, utils.AddBackupIDFlag(c, true)
utils.BackupFN, "",
"ID of the backup to delete. (required)")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
} }
return c return c
@ -256,7 +152,7 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error {
return nil return nil
} }
if err := validateExchangeBackupCreateFlags(user, exchangeData); err != nil { if err := validateExchangeBackupCreateFlags(utils.User, exchangeData); err != nil {
return err return err
} }
@ -267,7 +163,7 @@ func createExchangeCmd(cmd *cobra.Command, args []string) error {
defer utils.CloseRepo(ctx, r) defer utils.CloseRepo(ctx, r)
sel := exchangeBackupCreateSelectors(user, exchangeData) sel := exchangeBackupCreateSelectors(utils.User, exchangeData)
// TODO: log/print recoverable errors // TODO: log/print recoverable errors
errs := fault.New(false) errs := fault.New(false)
@ -345,7 +241,7 @@ func exchangeListCmd() *cobra.Command {
// lists the history of backup operations // lists the history of backup operations
func listExchangeCmd(cmd *cobra.Command, args []string) error { func listExchangeCmd(cmd *cobra.Command, args []string) error {
return genericListCommand(cmd, backupID, path.ExchangeService, args) return genericListCommand(cmd, utils.BackupID, path.ExchangeService, args)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -371,23 +267,26 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
ctx := cmd.Context() ctx := cmd.Context()
opts := utils.ExchangeOpts{ opts := utils.ExchangeOpts{
Contact: contact, Users: utils.User,
ContactFolder: contactFolder,
Email: email, Contact: utils.Contact,
EmailFolder: emailFolder, ContactFolder: utils.ContactFolder,
Event: event, ContactName: utils.ContactName,
EventCalendar: eventCalendar,
Users: user, Email: utils.Email,
ContactName: contactName, EmailFolder: utils.EmailFolder,
EmailReceivedAfter: emailReceivedAfter, EmailReceivedAfter: utils.EmailReceivedAfter,
EmailReceivedBefore: emailReceivedBefore, EmailReceivedBefore: utils.EmailReceivedBefore,
EmailSender: emailSender, EmailSender: utils.EmailSender,
EmailSubject: emailSubject, EmailSubject: utils.EmailSubject,
EventOrganizer: eventOrganizer, EventOrganizer: utils.EventOrganizer,
EventRecurs: eventRecurs,
EventStartsAfter: eventStartsAfter, Event: utils.Event,
EventStartsBefore: eventStartsBefore, EventCalendar: utils.EventCalendar,
EventSubject: eventSubject, EventRecurs: utils.EventRecurs,
EventStartsAfter: utils.EventStartsAfter,
EventStartsBefore: utils.EventStartsBefore,
EventSubject: utils.EventSubject,
Populated: utils.GetPopulatedFlags(cmd), Populated: utils.GetPopulatedFlags(cmd),
} }
@ -401,7 +300,7 @@ func detailsExchangeCmd(cmd *cobra.Command, args []string) error {
ctrlOpts := options.Control() ctrlOpts := options.Control()
ds, err := runDetailsExchangeCmd(ctx, r, backupID, opts, ctrlOpts.SkipReduce) ds, err := runDetailsExchangeCmd(ctx, r, utils.BackupID, opts, ctrlOpts.SkipReduce)
if err != nil { if err != nil {
return Only(ctx, err) return Only(ctx, err)
} }
@ -467,5 +366,5 @@ func exchangeDeleteCmd() *cobra.Command {
// deletes an exchange service backup. // deletes an exchange service backup.
func deleteExchangeCmd(cmd *cobra.Command, args []string) error { func deleteExchangeCmd(cmd *cobra.Command, args []string) error {
return genericDeleteCommand(cmd, backupID, "Exchange", args) return genericDeleteCommand(cmd, utils.BackupID, "Exchange", args)
} }

View File

@ -49,11 +49,11 @@ corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd --user a
# Explore Alice or Bob's files with name containing "Fiscal 22" in folder "Reports" # Explore Alice or Bob's files with name containing "Fiscal 22" in folder "Reports"
corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com,bob@example.com --file-name "Fiscal 22" --folder "Reports" --user alice@example.com,bob@example.com --file-name "Fiscal 22" --folder "Reports"
# Explore Alice's files created before end of 2015 from a specific backup # Explore Alice's files created before end of 2015 from a specific backup
corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso backup details onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --file-created-before 2015-01-01T00:00:00` --user alice@example.com --file-created-before 2015-01-01T00:00:00`
) )
// called by backup.go to map subcommands to provider-specific handling. // called by backup.go to map subcommands to provider-specific handling.
@ -65,83 +65,41 @@ func addOneDriveCommands(cmd *cobra.Command) *cobra.Command {
switch cmd.Use { switch cmd.Use {
case createCommand: case createCommand:
c, fs = utils.AddCommand(cmd, oneDriveCreateCmd()) c, _ = utils.AddCommand(cmd, oneDriveCreateCmd())
options.AddFeatureToggle(cmd, options.EnablePermissionsBackup()) options.AddFeatureToggle(cmd, options.EnablePermissionsBackup())
c.Use = c.Use + " " + oneDriveServiceCommandCreateUseSuffix c.Use = c.Use + " " + oneDriveServiceCommandCreateUseSuffix
c.Example = oneDriveServiceCommandCreateExamples c.Example = oneDriveServiceCommandCreateExamples
fs.StringSliceVar(&user, utils.AddUserFlag(c)
utils.UserFN, nil,
"Backup OneDrive data by user's email address; accepts '"+utils.Wildcard+"' to select all users. (required)")
options.AddOperationFlags(c) options.AddOperationFlags(c)
case listCommand: case listCommand:
c, fs = utils.AddCommand(cmd, oneDriveListCmd()) c, fs = utils.AddCommand(cmd, oneDriveListCmd())
fs.SortFlags = false
fs.StringVar(&backupID, utils.AddBackupIDFlag(c, false)
"backup", "",
"Display a specific backup, including the items that failed or were skipped during processing.")
addFailedItemsFN(c) addFailedItemsFN(c)
addSkippedItemsFN(c) addSkippedItemsFN(c)
addRecoveredErrorsFN(c) addRecoveredErrorsFN(c)
case detailsCommand: case detailsCommand:
c, fs = utils.AddCommand(cmd, oneDriveDetailsCmd()) c, _ = utils.AddCommand(cmd, oneDriveDetailsCmd())
c.Use = c.Use + " " + oneDriveServiceCommandDetailsUseSuffix c.Use = c.Use + " " + oneDriveServiceCommandDetailsUseSuffix
c.Example = oneDriveServiceCommandDetailsExamples c.Example = oneDriveServiceCommandDetailsExamples
options.AddSkipReduceFlag(c) options.AddSkipReduceFlag(c)
utils.AddBackupIDFlag(c, true)
fs.StringVar(&backupID, utils.AddOneDriveDetailsAndRestoreFlags(c)
utils.BackupFN, "",
"ID of the backup to explore. (required)")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
// onedrive hierarchy flags
fs.StringSliceVar(
&utils.FolderPaths,
utils.FolderFN, nil,
"Select backup details by OneDrive folder; defaults to root.")
fs.StringSliceVar(
&utils.FileNames,
utils.FileFN, nil,
"Select backup details by file name.")
// onedrive info flags
fs.StringVar(
&utils.FileCreatedAfter,
utils.FileCreatedAfterFN, "",
"Select backup details for files created after this datetime.")
fs.StringVar(
&utils.FileCreatedBefore,
utils.FileCreatedBeforeFN, "",
"Select backup details for files created before this datetime.")
fs.StringVar(
&utils.FileModifiedAfter,
utils.FileModifiedAfterFN, "",
"Select backup details for files modified after this datetime.")
fs.StringVar(
&utils.FileModifiedBefore,
utils.FileModifiedBeforeFN, "",
"Select backup details for files modified before this datetime.")
case deleteCommand: case deleteCommand:
c, fs = utils.AddCommand(cmd, oneDriveDeleteCmd()) c, _ = utils.AddCommand(cmd, oneDriveDeleteCmd())
c.Use = c.Use + " " + oneDriveServiceCommandDeleteUseSuffix c.Use = c.Use + " " + oneDriveServiceCommandDeleteUseSuffix
c.Example = oneDriveServiceCommandDeleteExamples c.Example = oneDriveServiceCommandDeleteExamples
fs.StringVar(&backupID, utils.AddBackupIDFlag(c, true)
utils.BackupFN, "",
"ID of the backup to delete. (required)")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
} }
return c return c
@ -170,7 +128,7 @@ func createOneDriveCmd(cmd *cobra.Command, args []string) error {
return nil return nil
} }
if err := validateOneDriveBackupCreateFlags(user); err != nil { if err := validateOneDriveBackupCreateFlags(utils.User); err != nil {
return err return err
} }
@ -181,7 +139,7 @@ func createOneDriveCmd(cmd *cobra.Command, args []string) error {
defer utils.CloseRepo(ctx, r) defer utils.CloseRepo(ctx, r)
sel := oneDriveBackupCreateSelectors(user) sel := oneDriveBackupCreateSelectors(utils.User)
// TODO: log/print recoverable errors // TODO: log/print recoverable errors
errs := fault.New(false) errs := fault.New(false)
@ -236,7 +194,7 @@ func oneDriveListCmd() *cobra.Command {
// lists the history of backup operations // lists the history of backup operations
func listOneDriveCmd(cmd *cobra.Command, args []string) error { func listOneDriveCmd(cmd *cobra.Command, args []string) error {
return genericListCommand(cmd, backupID, path.OneDriveService, args) return genericListCommand(cmd, utils.BackupID, path.OneDriveService, args)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -262,9 +220,9 @@ func detailsOneDriveCmd(cmd *cobra.Command, args []string) error {
ctx := cmd.Context() ctx := cmd.Context()
opts := utils.OneDriveOpts{ opts := utils.OneDriveOpts{
Users: user, Users: utils.User,
FileNames: utils.FileNames, FileNames: utils.FileName,
FolderPaths: utils.FolderPaths, FolderPaths: utils.FolderPath,
FileCreatedAfter: utils.FileCreatedAfter, FileCreatedAfter: utils.FileCreatedAfter,
FileCreatedBefore: utils.FileCreatedBefore, FileCreatedBefore: utils.FileCreatedBefore,
FileModifiedAfter: utils.FileModifiedAfter, FileModifiedAfter: utils.FileModifiedAfter,
@ -282,7 +240,7 @@ func detailsOneDriveCmd(cmd *cobra.Command, args []string) error {
ctrlOpts := options.Control() ctrlOpts := options.Control()
ds, err := runDetailsOneDriveCmd(ctx, r, backupID, opts, ctrlOpts.SkipReduce) ds, err := runDetailsOneDriveCmd(ctx, r, utils.BackupID, opts, ctrlOpts.SkipReduce)
if err != nil { if err != nil {
return Only(ctx, err) return Only(ctx, err)
} }
@ -345,5 +303,5 @@ func oneDriveDeleteCmd() *cobra.Command {
// deletes a oneDrive service backup. // deletes a oneDrive service backup.
func deleteOneDriveCmd(cmd *cobra.Command, args []string) error { func deleteOneDriveCmd(cmd *cobra.Command, args []string) error {
return genericDeleteCommand(cmd, backupID, "OneDrive", args) return genericDeleteCommand(cmd, utils.BackupID, "OneDrive", args)
} }

View File

@ -26,12 +26,7 @@ import (
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// sharePoint bucket info from flags // sharePoint bucket info from flags
var ( var sharepointData []string
pageFolders []string
page []string
sharepointData []string
)
const ( const (
dataLibraries = "libraries" dataLibraries = "libraries"
@ -40,32 +35,34 @@ const (
const ( const (
sharePointServiceCommand = "sharepoint" sharePointServiceCommand = "sharepoint"
sharePointServiceCommandCreateUseSuffix = "--web-url <siteURL> | '" + utils.Wildcard + "'" sharePointServiceCommandCreateUseSuffix = "--site <siteURL> | '" + utils.Wildcard + "'"
sharePointServiceCommandDeleteUseSuffix = "--backup <backupId>" sharePointServiceCommandDeleteUseSuffix = "--backup <backupId>"
sharePointServiceCommandDetailsUseSuffix = "--backup <backupId>" sharePointServiceCommandDetailsUseSuffix = "--backup <backupId>"
) )
const ( const (
sharePointServiceCommandCreateExamples = `# Backup SharePoint data for a Site sharePointServiceCommandCreateExamples = `# Backup SharePoint data for a Site
corso backup create sharepoint --web-url <siteURL> corso backup create sharepoint --site <siteURL>
# Backup SharePoint for two sites: HR and Team # Backup SharePoint for two sites: HR and Team
corso backup create sharepoint --site https://example.com/hr,https://example.com/team corso backup create sharepoint --site https://example.com/hr,https://example.com/team
# Backup all SharePoint data for all Sites # Backup all SharePoint data for all Sites
corso backup create sharepoint --web-url '*'` corso backup create sharepoint --site '*'`
sharePointServiceCommandDeleteExamples = `# Delete SharePoint backup with ID 1234abcd-12ab-cd34-56de-1234abcd sharePointServiceCommandDeleteExamples = `# Delete SharePoint backup with ID 1234abcd-12ab-cd34-56de-1234abcd
corso backup delete sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd` corso backup delete sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd`
sharePointServiceCommandDetailsExamples = `# Explore a site's files from backup 1234abcd-12ab-cd34-56de-1234abcd sharePointServiceCommandDetailsExamples = `# Explore a site's files from backup 1234abcd-12ab-cd34-56de-1234abcd
corso backup details sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd
corso backup details sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd --web-url https://example.com # Find all files that were created before a certain date.
# Find all site files that were created before a certain date.
corso backup details sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso backup details sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd \
--web-url https://example.com --file-created-before 2015-01-01T00:00:00 --file-created-before 2015-01-01T00:00:00 --folder "Display Templates/Style Sheets"
# Find all files within a specific library.
corso backup details sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd \
--library documents --folder "Display Templates/Style Sheets"
` `
) )
@ -83,15 +80,8 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command {
c.Use = c.Use + " " + sharePointServiceCommandCreateUseSuffix c.Use = c.Use + " " + sharePointServiceCommandCreateUseSuffix
c.Example = sharePointServiceCommandCreateExamples c.Example = sharePointServiceCommandCreateExamples
fs.StringArrayVar( utils.AddSiteFlag(cmd)
&utils.Site, utils.AddSiteIDFlag(cmd)
utils.SiteFN, nil,
"Backup SharePoint data by site ID; accepts '"+utils.Wildcard+"' to select all sites.")
fs.StringSliceVar(
&utils.WebURL,
utils.WebURLFN, nil,
"Restore data by site web URL; accepts '"+utils.Wildcard+"' to select all sites.")
fs.StringSliceVar( fs.StringSliceVar(
&sharepointData, &sharepointData,
@ -103,98 +93,30 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command {
case listCommand: case listCommand:
c, fs = utils.AddCommand(cmd, sharePointListCmd()) c, fs = utils.AddCommand(cmd, sharePointListCmd())
fs.SortFlags = false
fs.StringVar(&backupID, utils.AddBackupIDFlag(c, false)
"backup", "",
"Display a specific backup, including the items that failed or were skipped during processing.")
addFailedItemsFN(c) addFailedItemsFN(c)
addSkippedItemsFN(c) addSkippedItemsFN(c)
addRecoveredErrorsFN(c) addRecoveredErrorsFN(c)
case detailsCommand: case detailsCommand:
c, fs = utils.AddCommand(cmd, sharePointDetailsCmd()) c, _ = utils.AddCommand(cmd, sharePointDetailsCmd())
c.Use = c.Use + " " + sharePointServiceCommandDetailsUseSuffix c.Use = c.Use + " " + sharePointServiceCommandDetailsUseSuffix
c.Example = sharePointServiceCommandDetailsExamples c.Example = sharePointServiceCommandDetailsExamples
options.AddSkipReduceFlag(c) options.AddSkipReduceFlag(c)
utils.AddBackupIDFlag(c, true)
fs.StringVar(&backupID, utils.AddSharePointDetailsAndRestoreFlags(c)
utils.BackupFN, "",
"ID of the backup to retrieve.")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
// sharepoint hierarchy flags
fs.StringVar(
&utils.Library,
utils.LibraryFN, "",
"Select backup details within a library. Defaults includes all libraries.")
fs.StringSliceVar(
&utils.FolderPaths,
utils.FolderFN, nil,
"Select backup details by folder; defaults to root.")
fs.StringSliceVar(
&utils.FileNames,
utils.FileFN, nil,
"Select backup details by file name.")
fs.StringArrayVar(
&utils.Site,
utils.SiteFN, nil,
"Select backup details by site ID; accepts '"+utils.Wildcard+"' to select all sites.")
fs.StringSliceVar(
&utils.WebURL,
utils.WebURLFN, nil,
"Select backup data by site webURL; accepts '"+utils.Wildcard+"' to select all sites.")
fs.StringSliceVar(
&pageFolders,
utils.PageFolderFN, nil,
"Select backup data by folder name; accepts '"+utils.Wildcard+"' to select all folders.")
cobra.CheckErr(fs.MarkHidden(utils.PageFolderFN))
fs.StringSliceVar(
&page,
utils.PagesFN, nil,
"Select backup data by file name; accepts '"+utils.Wildcard+"' to select all pages within the site.")
cobra.CheckErr(fs.MarkHidden(utils.PagesFN))
// sharepoint info flags
fs.StringVar(
&utils.FileCreatedAfter,
utils.FileCreatedAfterFN, "",
"Select backup details created after this datetime.")
fs.StringVar(
&utils.FileCreatedBefore,
utils.FileCreatedBeforeFN, "",
"Select backup details created before this datetime.")
fs.StringVar(
&utils.FileModifiedAfter,
utils.FileModifiedAfterFN, "",
"Select backup details modified after this datetime.")
fs.StringVar(
&utils.FileModifiedBefore,
utils.FileModifiedBeforeFN, "",
"Select backup details modified before this datetime.")
case deleteCommand: case deleteCommand:
c, fs = utils.AddCommand(cmd, sharePointDeleteCmd()) c, _ = utils.AddCommand(cmd, sharePointDeleteCmd())
c.Use = c.Use + " " + sharePointServiceCommandDeleteUseSuffix c.Use = c.Use + " " + sharePointServiceCommandDeleteUseSuffix
c.Example = sharePointServiceCommandDeleteExamples c.Example = sharePointServiceCommandDeleteExamples
fs.StringVar(&backupID, utils.AddBackupIDFlag(c, true)
utils.BackupFN, "",
"ID of the backup to delete. (required)")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
} }
return c return c
@ -223,7 +145,7 @@ func createSharePointCmd(cmd *cobra.Command, args []string) error {
return nil return nil
} }
if err := validateSharePointBackupCreateFlags(utils.Site, utils.WebURL, sharepointData); err != nil { if err := validateSharePointBackupCreateFlags(utils.SiteID, utils.WebURL, sharepointData); err != nil {
return err return err
} }
@ -242,9 +164,9 @@ func createSharePointCmd(cmd *cobra.Command, args []string) error {
return Only(ctx, errors.Wrap(err, "Failed to connect to Microsoft APIs")) return Only(ctx, errors.Wrap(err, "Failed to connect to Microsoft APIs"))
} }
sel, err := sharePointBackupCreateSelectors(ctx, utils.Site, utils.WebURL, sharepointData, gc) sel, err := sharePointBackupCreateSelectors(ctx, utils.SiteID, utils.WebURL, sharepointData, gc)
if err != nil { if err != nil {
return Only(ctx, errors.Wrap(err, "Retrieving up sharepoint sites by ID and Web URL")) return Only(ctx, errors.Wrap(err, "Retrieving up sharepoint sites by ID and URL"))
} }
selectorSet := []selectors.Selector{} selectorSet := []selectors.Selector{}
@ -265,8 +187,7 @@ func validateSharePointBackupCreateFlags(sites, weburls, cats []string) error {
if len(sites) == 0 && len(weburls) == 0 { if len(sites) == 0 && len(weburls) == 0 {
return errors.New( return errors.New(
"requires one or more --" + "requires one or more --" +
utils.SiteFN + " ids, --" + utils.SiteFN + " urls, or the wildcard --" +
utils.WebURLFN + " urls, or the wildcard --" +
utils.SiteFN + " *", utils.SiteFN + " *",
) )
} }
@ -359,7 +280,7 @@ func sharePointListCmd() *cobra.Command {
// lists the history of backup operations // lists the history of backup operations
func listSharePointCmd(cmd *cobra.Command, args []string) error { func listSharePointCmd(cmd *cobra.Command, args []string) error {
return genericListCommand(cmd, backupID, path.SharePointService, args) return genericListCommand(cmd, utils.BackupID, path.SharePointService, args)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -379,7 +300,7 @@ func sharePointDeleteCmd() *cobra.Command {
// deletes a sharePoint service backup. // deletes a sharePoint service backup.
func deleteSharePointCmd(cmd *cobra.Command, args []string) error { func deleteSharePointCmd(cmd *cobra.Command, args []string) error {
return genericDeleteCommand(cmd, backupID, "SharePoint", args) return genericDeleteCommand(cmd, utils.BackupID, "SharePoint", args)
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -405,11 +326,11 @@ func detailsSharePointCmd(cmd *cobra.Command, args []string) error {
ctx := cmd.Context() ctx := cmd.Context()
opts := utils.SharePointOpts{ opts := utils.SharePointOpts{
FolderPaths: utils.FolderPaths, FolderPath: utils.FolderPath,
FileNames: utils.FileNames, FileName: utils.FileName,
Library: utils.Library, Library: utils.Library,
Sites: utils.Site, SiteID: utils.SiteID,
WebURLs: utils.WebURL, WebURL: utils.WebURL,
FileCreatedAfter: fileCreatedAfter, FileCreatedAfter: fileCreatedAfter,
FileCreatedBefore: fileCreatedBefore, FileCreatedBefore: fileCreatedBefore,
FileModifiedAfter: fileModifiedAfter, FileModifiedAfter: fileModifiedAfter,
@ -427,7 +348,7 @@ func detailsSharePointCmd(cmd *cobra.Command, args []string) error {
ctrlOpts := options.Control() ctrlOpts := options.Control()
ds, err := runDetailsSharePointCmd(ctx, r, backupID, opts, ctrlOpts.SkipReduce) ds, err := runDetailsSharePointCmd(ctx, r, utils.BackupID, opts, ctrlOpts.SkipReduce)
if err != nil { if err != nil {
return Only(ctx, err) return Only(ctx, err)
} }

View File

@ -56,82 +56,10 @@ func addExchangeCommands(cmd *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, fs.SortFlags = false
utils.BackupFN, "",
"ID of the backup to restore. (required)")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
fs.StringSliceVar(&user, utils.AddBackupIDFlag(c, true)
utils.UserFN, nil, utils.AddExchangeDetailsAndRestoreFlags(c)
"Restore data by user's email address; accepts '"+utils.Wildcard+"' to select all users.")
// email flags
fs.StringSliceVar(&email,
utils.EmailFN, nil,
"Restore emails by ID; accepts '"+utils.Wildcard+"' to select all emails.")
fs.StringSliceVar(
&emailFolder,
utils.EmailFolderFN, nil,
"Restore emails within a folder; accepts '"+utils.Wildcard+"' to select all email folders.")
fs.StringVar(
&emailSubject,
utils.EmailSubjectFN, "",
"Restore emails with a subject containing this value.")
fs.StringVar(
&emailSender,
utils.EmailSenderFN, "",
"Restore emails from a specific sender.")
fs.StringVar(
&emailReceivedAfter,
utils.EmailReceivedAfterFN, "",
"Restore emails received after this datetime.")
fs.StringVar(
&emailReceivedBefore,
utils.EmailReceivedBeforeFN, "",
"Restore emails received before this datetime.")
// event flags
fs.StringSliceVar(&event,
utils.EventFN, nil,
"Restore events by event ID; accepts '"+utils.Wildcard+"' to select all events.")
fs.StringSliceVar(
&eventCalendar,
utils.EventCalendarFN, nil,
"Restore events under a calendar; accepts '"+utils.Wildcard+"' to select all event calendars.")
fs.StringVar(
&eventSubject,
utils.EventSubjectFN, "",
"Restore events with a subject containing this value.")
fs.StringVar(
&eventOrganizer,
utils.EventOrganizerFN, "",
"Restore events from a specific organizer.")
fs.StringVar(
&eventRecurs,
utils.EventRecursFN, "",
"Restore recurring events. Use `--event-recurs false` to restore non-recurring events.")
fs.StringVar(
&eventStartsAfter,
utils.EventStartsAfterFN, "",
"Restore events starting after this datetime.")
fs.StringVar(
&eventStartsBefore,
utils.EventStartsBeforeFN, "",
"Restore events starting before this datetime.")
// contacts flags
fs.StringSliceVar(
&contact,
utils.ContactFN, nil,
"Restore contacts by contact ID; accepts '"+utils.Wildcard+"' to select all contacts.")
fs.StringSliceVar(
&contactFolder,
utils.ContactFolderFN, nil,
"Restore contacts within a folder; accepts '"+utils.Wildcard+"' to select all contact folders.")
fs.StringVar(
&contactName,
utils.ContactNameFN, "",
"Restore contacts whose contact name contains this value.")
// others // others
options.AddOperationFlags(c) options.AddOperationFlags(c)
@ -149,11 +77,11 @@ corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --email 98765ab
# Restore Alice's emails with subject containing "Hello world" in "Inbox" from a specific backup # Restore Alice's emails with subject containing "Hello world" in "Inbox" from a specific backup
corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --email-subject "Hello world" --email-folder Inbox --user alice@example.com --email-subject "Hello world" --email-folder Inbox
# Restore Bobs's entire calendar from a specific backup # Restore Bobs's entire calendar from a specific backup
corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user bob@example.com --event-calendar Calendar --user bob@example.com --event-calendar Calendar
# Restore contact with ID abdef0101 from a specific backup # Restore contact with ID abdef0101 from a specific backup
corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --contact abdef0101` corso restore exchange --backup 1234abcd-12ab-cd34-56de-1234abcd --contact abdef0101`

View File

@ -15,16 +15,6 @@ import (
"github.com/alcionai/corso/src/pkg/repository" "github.com/alcionai/corso/src/pkg/repository"
) )
var (
folderPaths []string
fileNames []string
fileCreatedAfter string
fileCreatedBefore string
fileModifiedAfter string
fileModifiedBefore string
)
// called by restore.go to map subcommands to provider-specific handling. // called by restore.go to map subcommands to provider-specific handling.
func addOneDriveCommands(cmd *cobra.Command) *cobra.Command { func addOneDriveCommands(cmd *cobra.Command) *cobra.Command {
var ( var (
@ -42,49 +32,8 @@ func addOneDriveCommands(cmd *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, utils.AddBackupIDFlag(c, true)
utils.BackupFN, "", utils.AddOneDriveDetailsAndRestoreFlags(c)
"ID of the backup to restore. (required)")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
fs.StringSliceVar(&user,
utils.UserFN, nil,
"Restore data by user's email address; accepts '"+utils.Wildcard+"' to select all users.")
// onedrive hierarchy (path/name) flags
fs.StringSliceVar(
&folderPaths,
utils.FolderFN, nil,
"Restore items by OneDrive folder; defaults to root")
fs.StringSliceVar(
&fileNames,
utils.FileFN, nil,
"Restore items by file name or ID")
// permissions restore flag
options.AddRestorePermissionsFlag(c)
// onedrive info flags
fs.StringVar(
&fileCreatedAfter,
utils.FileCreatedAfterFN, "",
"Restore files created after this datetime")
fs.StringVar(
&fileCreatedBefore,
utils.FileCreatedBeforeFN, "",
"Restore files created before this datetime")
fs.StringVar(
&fileModifiedAfter,
utils.FileModifiedAfterFN, "",
"Restore files modified after this datetime")
fs.StringVar(
&fileModifiedBefore,
utils.FileModifiedBeforeFN, "",
"Restore files modified before this datetime")
// others // others
options.AddOperationFlags(c) options.AddOperationFlags(c)
@ -105,11 +54,11 @@ corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd --file 98765abc
# Restore Alice's file named "FY2021 Planning.xlsx in "Documents/Finance Reports" from a specific backup # Restore Alice's file named "FY2021 Planning.xlsx in "Documents/Finance Reports" from a specific backup
corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd \
--user alice@example.com --file "FY2021 Planning.xlsx" --folder "Documents/Finance Reports" --user alice@example.com --file "FY2021 Planning.xlsx" --folder "Documents/Finance Reports"
# Restore all files from Bob's folder that were created before 2020 when captured in a specific backup # Restore all files from Bob's folder that were created before 2020 when captured in a specific backup
corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd corso restore onedrive --backup 1234abcd-12ab-cd34-56de-1234abcd
--user bob@example.com --folder "Documents/Finance Reports" --file-created-before 2020-01-01T00:00:00` --user bob@example.com --folder "Documents/Finance Reports" --file-created-before 2020-01-01T00:00:00`
) )
// `corso restore onedrive [<flag>...]` // `corso restore onedrive [<flag>...]`
@ -133,8 +82,8 @@ func restoreOneDriveCmd(cmd *cobra.Command, args []string) error {
opts := utils.OneDriveOpts{ opts := utils.OneDriveOpts{
Users: user, Users: user,
FileNames: fileNames, FileNames: utils.FileName,
FolderPaths: folderPaths, FolderPaths: utils.FolderPath,
FileCreatedAfter: utils.FileCreatedAfter, FileCreatedAfter: utils.FileCreatedAfter,
FileCreatedBefore: utils.FileCreatedBefore, FileCreatedBefore: utils.FileCreatedBefore,
FileModifiedAfter: utils.FileModifiedAfter, FileModifiedAfter: utils.FileModifiedAfter,

View File

@ -39,83 +39,8 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command {
// More generic (ex: --site) and more frequently used flags take precedence. // More generic (ex: --site) and more frequently used flags take precedence.
fs.SortFlags = false fs.SortFlags = false
fs.StringVar( utils.AddBackupIDFlag(c, true)
&backupID, utils.AddSharePointDetailsAndRestoreFlags(c)
utils.BackupFN, "",
"ID of the backup to restore. (required)")
cobra.CheckErr(c.MarkFlagRequired(utils.BackupFN))
fs.StringSliceVar(
&utils.Site,
utils.SiteFN, nil,
"Restore data by site ID; accepts '"+utils.Wildcard+"' to select all sites.")
fs.StringSliceVar(
&utils.WebURL,
utils.WebURLFN, nil,
"Restore data by site webURL; accepts '"+utils.Wildcard+"' to select all sites.")
// sharepoint hierarchy (path/name) flags
fs.StringVar(
&utils.Library,
utils.LibraryFN, "",
"Restore files within a library. Default includes all libraries.")
fs.StringSliceVar(
&utils.FolderPaths,
utils.FolderFN, nil,
"Restore files by folder; defaults to root.")
fs.StringSliceVar(
&utils.FileNames,
utils.FileFN, nil,
"Restore files by name.")
fs.StringSliceVar(
&listPaths,
utils.ListFN, nil,
"Restore list items by SharePoint list ID")
cobra.CheckErr(fs.MarkHidden(utils.ListFN))
fs.StringSliceVar(
&listItems,
utils.ListItemFN, nil,
"Restore list items by ID")
cobra.CheckErr(fs.MarkHidden(utils.ListItemFN))
fs.StringSliceVar(
&pageFolders,
utils.PageFolderFN, nil,
"Restore Site pages by page folder name")
cobra.CheckErr(fs.MarkHidden(utils.PageFolderFN))
fs.StringSliceVar(
&pages,
utils.PagesFN, nil,
"Restore site pages by file name(s)")
cobra.CheckErr(fs.MarkHidden(utils.PagesFN))
// sharepoint info flags
fs.StringVar(
&utils.FileCreatedAfter,
utils.FileCreatedAfterFN, "",
"Restore files created after this datetime.")
fs.StringVar(
&utils.FileCreatedBefore,
utils.FileCreatedBeforeFN, "",
"Restore files created before this datetime.")
fs.StringVar(
&utils.FileModifiedAfter,
utils.FileModifiedAfterFN, "",
"Restore files modified after this datetime.")
fs.StringVar(
&utils.FileModifiedBefore,
utils.FileModifiedBeforeFN, "",
"Restore files modified before this datetime.")
// others // others
options.AddOperationFlags(c) options.AddOperationFlags(c)
@ -132,13 +57,17 @@ const (
sharePointServiceCommandRestoreExamples = `# Restore file with ID 98765abcdef sharePointServiceCommandRestoreExamples = `# Restore file with ID 98765abcdef
corso restore sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd --file 98765abcdef corso restore sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd --file 98765abcdef
# Restore a Site's file named "ServerRenderTemplate.xsl in "Display Templates/Style Sheets" from a specific backup # Restore a file named "ServerRenderTemplate.xsl in "Display Templates/Style Sheets".
corso restore sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd \ corso restore sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd \
--web-url https://example.com --file "ServerRenderTemplate.xsl" --folder "Display Templates/Style Sheets" --file "ServerRenderTemplate.xsl" --folder "Display Templates/Style Sheets"
# Restore all files from a Site that were created before 2020 when captured in a specific backup # Restore all files that were created before 2020.
corso restore sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd corso restore sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd
--web-url https://example.com --folder "Display Templates/Style Sheets" --file-created-before 2020-01-01T00:00:00` --file-created-before 2020-01-01T00:00:00 --folder "Display Templates/Style Sheets"
# Restore all files in a certain library.
corso restore sharepoint --backup 1234abcd-12ab-cd34-56de-1234abcd
--library documents --folder "Display Templates/Style Sheets" `
) )
// `corso restore sharepoint [<flag>...]` // `corso restore sharepoint [<flag>...]`
@ -161,15 +90,15 @@ func restoreSharePointCmd(cmd *cobra.Command, args []string) error {
} }
opts := utils.SharePointOpts{ opts := utils.SharePointOpts{
FileNames: utils.FileNames, FileName: utils.FileName,
FolderPaths: utils.FolderPaths, FolderPath: utils.FolderPath,
Library: utils.Library, Library: utils.Library,
ListItems: listItems, ListItem: listItems,
ListPaths: listPaths, ListPath: listPaths,
PageFolders: pageFolders, PageFolder: pageFolders,
Pages: pages, Page: pages,
Sites: utils.Site, SiteID: utils.SiteID,
WebURLs: utils.WebURL, WebURL: utils.WebURL,
FileCreatedAfter: utils.FileCreatedAfter, FileCreatedAfter: utils.FileCreatedAfter,
FileCreatedBefore: utils.FileCreatedBefore, FileCreatedBefore: utils.FileCreatedBefore,
FileModifiedAfter: utils.FileModifiedAfter, FileModifiedAfter: utils.FileModifiedAfter,

View File

@ -4,26 +4,51 @@ import (
"errors" "errors"
"github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/selectors"
"github.com/spf13/cobra"
) )
// flag names // flag names
const ( const (
ContactFN = "contact" ContactFN = "contact"
ContactFolderFN = "contact-folder" ContactFolderFN = "contact-folder"
ContactNameFN = "contact-name"
EmailFN = "email" EmailFN = "email"
EmailFolderFN = "email-folder" EmailFolderFN = "email-folder"
EventFN = "event"
EventCalendarFN = "event-calendar"
ContactNameFN = "contact-name"
EmailReceivedAfterFN = "email-received-after" EmailReceivedAfterFN = "email-received-after"
EmailReceivedBeforeFN = "email-received-before" EmailReceivedBeforeFN = "email-received-before"
EmailSenderFN = "email-sender" EmailSenderFN = "email-sender"
EmailSubjectFN = "email-subject" EmailSubjectFN = "email-subject"
EventOrganizerFN = "event-organizer"
EventRecursFN = "event-recurs" EventFN = "event"
EventStartsAfterFN = "event-starts-after" EventCalendarFN = "event-calendar"
EventStartsBeforeFN = "event-starts-before" EventOrganizerFN = "event-organizer"
EventSubjectFN = "event-subject" EventRecursFN = "event-recurs"
EventStartsAfterFN = "event-starts-after"
EventStartsBeforeFN = "event-starts-before"
EventSubjectFN = "event-subject"
)
// flag population values
var (
Contact []string
ContactFolder []string
ContactName string
Email []string
EmailFolder []string
EmailReceivedAfter string
EmailReceivedBefore string
EmailSender string
EmailSubject string
Event []string
EventCalendar []string
EventOrganizer string
EventRecurs string
EventStartsAfter string
EventStartsBefore string
EventSubject string
) )
type ExchangeOpts struct { type ExchangeOpts struct {
@ -48,6 +73,82 @@ type ExchangeOpts struct {
Populated PopulatedFlags Populated PopulatedFlags
} }
// AddExchangeDetailsAndRestoreFlags adds flags that are common to both the
// details and restore commands.
func AddExchangeDetailsAndRestoreFlags(cmd *cobra.Command) {
fs := cmd.Flags()
// email flags
fs.StringSliceVar(
&Email,
EmailFN, nil,
"Select emails by email ID; accepts '"+Wildcard+"' to select all emails.")
fs.StringSliceVar(
&EmailFolder,
EmailFolderFN, nil,
"Select emails within a folder; accepts '"+Wildcard+"' to select all email folders.")
fs.StringVar(
&EmailSubject,
EmailSubjectFN, "",
"Select emails with a subject containing this value.")
fs.StringVar(
&EmailSender,
EmailSenderFN, "",
"Select emails from a specific sender.")
fs.StringVar(
&EmailReceivedAfter,
EmailReceivedAfterFN, "",
"Select emails received after this datetime.")
fs.StringVar(
&EmailReceivedBefore,
EmailReceivedBeforeFN, "",
"Select emails received before this datetime.")
// event flags
fs.StringSliceVar(
&Event,
EventFN, nil,
"Select events by event ID; accepts '"+Wildcard+"' to select all events.")
fs.StringSliceVar(
&EventCalendar,
EventCalendarFN, nil,
"Select events under a calendar; accepts '"+Wildcard+"' to select all events.")
fs.StringVar(
&EventSubject,
EventSubjectFN, "",
"Select events with a subject containing this value.")
fs.StringVar(
&EventOrganizer,
EventOrganizerFN, "",
"Select events from a specific organizer.")
fs.StringVar(
&EventRecurs,
EventRecursFN, "",
"Select recurring events. Use `--event-recurs false` to select non-recurring events.")
fs.StringVar(
&EventStartsAfter,
EventStartsAfterFN, "",
"Select events starting after this datetime.")
fs.StringVar(
&EventStartsBefore,
EventStartsBeforeFN, "",
"Select events starting before this datetime.")
// contact flags
fs.StringSliceVar(
&Contact,
ContactFN, nil,
"Select contacts by contact ID; accepts '"+Wildcard+"' to select all contacts.")
fs.StringSliceVar(
&ContactFolder,
ContactFolderFN, nil,
"Select contacts within a folder; accepts '"+Wildcard+"' to select all contact folders.")
fs.StringVar(
&ContactName,
ContactNameFN, "",
"Select contacts whose contact name contains this value.")
}
// AddExchangeInclude adds the scope of the provided values to the selector's // AddExchangeInclude adds the scope of the provided values to the selector's
// inclusion set. Any unpopulated slice will be replaced with selectors.Any() // inclusion set. Any unpopulated slice will be replaced with selectors.Any()
// to act as a wildcard. // to act as a wildcard.

View File

@ -12,8 +12,10 @@ import (
// common flag vars // common flag vars
var ( var (
FolderPaths []string BackupID string
FileNames []string
FolderPath []string
FileName []string
FileCreatedAfter string FileCreatedAfter string
FileCreatedBefore string FileCreatedBefore string
@ -21,8 +23,10 @@ var (
FileModifiedBefore string FileModifiedBefore string
Library string Library string
Site []string SiteID []string
WebURL []string WebURL []string
User []string
) )
// common flag names // common flag names
@ -30,9 +34,9 @@ const (
BackupFN = "backup" BackupFN = "backup"
DataFN = "data" DataFN = "data"
LibraryFN = "library" LibraryFN = "library"
SiteFN = "site" SiteFN = "site" // site only accepts WebURL values
SiteIDFN = "site-id" // site-id accepts actual site ids
UserFN = "user" UserFN = "user"
WebURLFN = "web-url"
FileFN = "file" FileFN = "file"
FolderFN = "folder" FolderFN = "folder"
@ -43,6 +47,49 @@ const (
FileModifiedBeforeFN = "file-modified-before" FileModifiedBeforeFN = "file-modified-before"
) )
// AddBackupIDFlag adds the --backup flag.
func AddBackupIDFlag(cmd *cobra.Command, require bool) {
cmd.Flags().StringVar(&BackupID, BackupFN, "", "ID of the backup to retrieve.")
if require {
cobra.CheckErr(cmd.MarkFlagRequired(BackupFN))
}
}
// AddUserFlag adds the --user flag.
func AddUserFlag(cmd *cobra.Command) {
cmd.Flags().StringSliceVar(
&User,
UserFN, nil,
"Backup a specific user's data; accepts '"+Wildcard+"' to select all users.")
cobra.CheckErr(cmd.MarkFlagRequired(UserFN))
}
// AddSiteIDFlag adds the --site-id flag, which accepts site ID values.
// This flag is hidden, since we expect users to prefer the --site url
// and do not want to encourage confusion.
func AddSiteIDFlag(cmd *cobra.Command) {
fs := cmd.Flags()
// note string ARRAY var. IDs naturally contain commas, so we cannot accept
// duplicate values within a flag declaration. ie: --site-id a,b,c does not
// work. Users must call --site-id a --site-id b --site-id c.
fs.StringArrayVar(
&SiteID,
SiteIDFN, nil,
//nolint:lll
"Backup data by site ID; accepts '"+Wildcard+"' to select all sites. Args cannot be comma-delimited and must use multiple flags.")
cobra.CheckErr(fs.MarkHidden(SiteIDFN))
}
// AddSiteFlag adds the --site flag, which accepts webURL values.
func AddSiteFlag(cmd *cobra.Command) {
cmd.Flags().StringSliceVar(
&WebURL,
SiteFN, nil,
"Backup data by site URL; accepts '"+Wildcard+"' to select all sites.")
}
type PopulatedFlags map[string]struct{} type PopulatedFlags map[string]struct{}
func (fs PopulatedFlags) populate(pf *pflag.Flag) { func (fs PopulatedFlags) populate(pf *pflag.Flag) {

View File

@ -4,6 +4,7 @@ import (
"errors" "errors"
"github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/selectors"
"github.com/spf13/cobra"
) )
type OneDriveOpts struct { type OneDriveOpts struct {
@ -18,6 +19,41 @@ type OneDriveOpts struct {
Populated PopulatedFlags Populated PopulatedFlags
} }
// AddOneDriveDetailsAndRestoreFlags adds flags that are common to both the
// details and restore commands.
func AddOneDriveDetailsAndRestoreFlags(cmd *cobra.Command) {
fs := cmd.Flags()
fs.StringSliceVar(
&FolderPath,
FolderFN, nil,
"Select files by OneDrive folder; defaults to root.")
fs.StringSliceVar(
&FileName,
FileFN, nil,
"Select files by name.")
fs.StringVar(
&FileCreatedAfter,
FileCreatedAfterFN, "",
"Select files created after this datetime.")
fs.StringVar(
&FileCreatedBefore,
FileCreatedBeforeFN, "",
"Select files created before this datetime.")
fs.StringVar(
&FileModifiedAfter,
FileModifiedAfterFN, "",
"Select files modified after this datetime.")
fs.StringVar(
&FileModifiedBefore,
FileModifiedBeforeFN, "",
"Select files modified before this datetime.")
}
// ValidateOneDriveRestoreFlags checks common flags for correctness and interdependencies // ValidateOneDriveRestoreFlags checks common flags for correctness and interdependencies
func ValidateOneDriveRestoreFlags(backupID string, opts OneDriveOpts) error { func ValidateOneDriveRestoreFlags(backupID string, opts OneDriveOpts) error {
if len(backupID) == 0 { if len(backupID) == 0 {

View File

@ -2,28 +2,38 @@ package utils
import ( import (
"errors" "errors"
"fmt"
"github.com/alcionai/corso/src/pkg/selectors" "github.com/alcionai/corso/src/pkg/selectors"
"github.com/spf13/cobra"
) )
const ( const (
ListItemFN = "list-item" ListItemFN = "list-item"
ListFN = "list" ListFN = "list"
PageFolderFN = "page-folders" PageFolderFN = "page-folder"
PagesFN = "pages" PagesFN = "page"
)
// flag population variables
var (
PageFolder []string
Page []string
) )
type SharePointOpts struct { type SharePointOpts struct {
FileNames []string // for libraries, to duplicate onedrive interface Library string
FolderPaths []string // for libraries, to duplicate onedrive interface FileName []string // for libraries, to duplicate onedrive interface
Library string FolderPath []string // for libraries, to duplicate onedrive interface
ListItems []string
ListPaths []string ListItem []string
PageFolders []string ListPath []string
Pages []string
Sites []string PageFolder []string
WebURLs []string Page []string
SiteID []string
WebURL []string
FileCreatedAfter string FileCreatedAfter string
FileCreatedBefore string FileCreatedBefore string
FileModifiedAfter string FileModifiedAfter string
@ -32,6 +42,58 @@ type SharePointOpts struct {
Populated PopulatedFlags Populated PopulatedFlags
} }
// AddSharePointDetailsAndRestoreFlags adds flags that are common to both the
// details and restore commands.
func AddSharePointDetailsAndRestoreFlags(cmd *cobra.Command) {
fs := cmd.Flags()
fs.StringVar(
&Library,
LibraryFN, "",
"Select only this library. Default includes all libraries.")
fs.StringSliceVar(
&FolderPath,
FolderFN, nil,
"Select by folder; defaults to root.")
fs.StringSliceVar(
&FileName,
FileFN, nil,
"Select by file name.")
fs.StringSliceVar(
&PageFolder,
PageFolderFN, nil,
"Select pages by folder name; accepts '"+Wildcard+"' to select all folders.")
cobra.CheckErr(fs.MarkHidden(PageFolderFN))
fs.StringSliceVar(
&Page,
PagesFN, nil,
"Select pages by item name; accepts '"+Wildcard+"' to select all pages within the site.")
cobra.CheckErr(fs.MarkHidden(PagesFN))
fs.StringVar(
&FileCreatedAfter,
FileCreatedAfterFN, "",
"Select files created after this datetime.")
fs.StringVar(
&FileCreatedBefore,
FileCreatedBeforeFN, "",
"Select files created before this datetime.")
fs.StringVar(
&FileModifiedAfter,
FileModifiedAfterFN, "",
"Select files modified after this datetime.")
fs.StringVar(
&FileModifiedBefore,
FileModifiedBeforeFN, "",
"Select files modified before this datetime.")
}
// ValidateSharePointRestoreFlags checks common flags for correctness and interdependencies // ValidateSharePointRestoreFlags checks common flags for correctness and interdependencies
func ValidateSharePointRestoreFlags(backupID string, opts SharePointOpts) error { func ValidateSharePointRestoreFlags(backupID string, opts SharePointOpts) error {
if len(backupID) == 0 { if len(backupID) == 0 {
@ -39,7 +101,6 @@ func ValidateSharePointRestoreFlags(backupID string, opts SharePointOpts) error
} }
if _, ok := opts.Populated[FileCreatedAfterFN]; ok && !IsValidTimeFormat(opts.FileCreatedAfter) { if _, ok := opts.Populated[FileCreatedAfterFN]; ok && !IsValidTimeFormat(opts.FileCreatedAfter) {
fmt.Printf("What was I sent: %v\n", opts.FileCreatedAfter)
return errors.New("invalid time format for " + FileCreatedAfterFN) return errors.New("invalid time format for " + FileCreatedAfterFN)
} }
@ -75,12 +136,12 @@ func AddSharePointFilter(
// IncludeSharePointRestoreDataSelectors builds the common data-selector // IncludeSharePointRestoreDataSelectors builds the common data-selector
// inclusions for SharePoint commands. // inclusions for SharePoint commands.
func IncludeSharePointRestoreDataSelectors(opts SharePointOpts) *selectors.SharePointRestore { func IncludeSharePointRestoreDataSelectors(opts SharePointOpts) *selectors.SharePointRestore {
sites := opts.Sites sites := opts.SiteID
lfp, lfn := len(opts.FolderPaths), len(opts.FileNames) lfp, lfn := len(opts.FolderPath), len(opts.FileName)
ls, lwu := len(opts.Sites), len(opts.WebURLs) ls, lwu := len(opts.SiteID), len(opts.WebURL)
slp, sli := len(opts.ListPaths), len(opts.ListItems) slp, sli := len(opts.ListPath), len(opts.ListItem)
pf, pi := len(opts.PageFolders), len(opts.Pages) pf, pi := len(opts.PageFolder), len(opts.Page)
if ls == 0 { if ls == 0 {
sites = selectors.Any() sites = selectors.Any()
@ -95,58 +156,58 @@ func IncludeSharePointRestoreDataSelectors(opts SharePointOpts) *selectors.Share
if lfp+lfn > 0 { if lfp+lfn > 0 {
if lfn == 0 { if lfn == 0 {
opts.FileNames = selectors.Any() opts.FileName = selectors.Any()
} }
opts.FolderPaths = trimFolderSlash(opts.FolderPaths) opts.FolderPath = trimFolderSlash(opts.FolderPath)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.FolderPaths) containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.FolderPath)
if len(containsFolders) > 0 { if len(containsFolders) > 0 {
sel.Include(sel.LibraryItems(containsFolders, opts.FileNames)) sel.Include(sel.LibraryItems(containsFolders, opts.FileName))
} }
if len(prefixFolders) > 0 { if len(prefixFolders) > 0 {
sel.Include(sel.LibraryItems(prefixFolders, opts.FileNames, selectors.PrefixMatch())) sel.Include(sel.LibraryItems(prefixFolders, opts.FileName, selectors.PrefixMatch()))
} }
} }
if slp+sli > 0 { if slp+sli > 0 {
if sli == 0 { if sli == 0 {
opts.ListItems = selectors.Any() opts.ListItem = selectors.Any()
} }
opts.ListPaths = trimFolderSlash(opts.ListPaths) opts.ListPath = trimFolderSlash(opts.ListPath)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.ListPaths) containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.ListPath)
if len(containsFolders) > 0 { if len(containsFolders) > 0 {
sel.Include(sel.ListItems(containsFolders, opts.ListItems)) sel.Include(sel.ListItems(containsFolders, opts.ListItem))
} }
if len(prefixFolders) > 0 { if len(prefixFolders) > 0 {
sel.Include(sel.ListItems(prefixFolders, opts.ListItems, selectors.PrefixMatch())) sel.Include(sel.ListItems(prefixFolders, opts.ListItem, selectors.PrefixMatch()))
} }
} }
if pf+pi > 0 { if pf+pi > 0 {
if pi == 0 { if pi == 0 {
opts.Pages = selectors.Any() opts.Page = selectors.Any()
} }
opts.PageFolders = trimFolderSlash(opts.PageFolders) opts.PageFolder = trimFolderSlash(opts.PageFolder)
containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.PageFolders) containsFolders, prefixFolders := splitFoldersIntoContainsAndPrefix(opts.PageFolder)
if len(containsFolders) > 0 { if len(containsFolders) > 0 {
sel.Include(sel.PageItems(containsFolders, opts.Pages)) sel.Include(sel.PageItems(containsFolders, opts.Page))
} }
if len(prefixFolders) > 0 { if len(prefixFolders) > 0 {
sel.Include(sel.PageItems(prefixFolders, opts.Pages, selectors.PrefixMatch())) sel.Include(sel.PageItems(prefixFolders, opts.Page, selectors.PrefixMatch()))
} }
} }
if lwu > 0 { if lwu > 0 {
opts.WebURLs = trimFolderSlash(opts.WebURLs) opts.WebURL = trimFolderSlash(opts.WebURL)
containsURLs, suffixURLs := splitFoldersIntoContainsAndPrefix(opts.WebURLs) containsURLs, suffixURLs := splitFoldersIntoContainsAndPrefix(opts.WebURL)
if len(containsURLs) > 0 { if len(containsURLs) > 0 {
sel.Include(sel.WebURL(containsURLs)) sel.Include(sel.WebURL(containsURLs))

View File

@ -43,140 +43,140 @@ func (suite *SharePointUtilsSuite) TestIncludeSharePointRestoreDataSelectors() {
{ {
name: "single inputs", name: "single inputs",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: single, FileName: single,
FolderPaths: single, FolderPath: single,
Sites: single, SiteID: single,
WebURLs: single, WebURL: single,
}, },
expectIncludeLen: 4, expectIncludeLen: 4,
}, },
{ {
name: "single extended", name: "single extended",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: single, FileName: single,
FolderPaths: single, FolderPath: single,
ListItems: single, ListItem: single,
ListPaths: single, ListPath: single,
Sites: single, SiteID: single,
WebURLs: single, WebURL: single,
}, },
expectIncludeLen: 5, expectIncludeLen: 5,
}, },
{ {
name: "multi inputs", name: "multi inputs",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: multi, FileName: multi,
FolderPaths: multi, FolderPath: multi,
Sites: multi, SiteID: multi,
WebURLs: multi, WebURL: multi,
}, },
expectIncludeLen: 4, expectIncludeLen: 4,
}, },
{ {
name: "library folder contains", name: "library folder contains",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: empty, FileName: empty,
FolderPaths: containsOnly, FolderPath: containsOnly,
Sites: empty, SiteID: empty,
WebURLs: empty, WebURL: empty,
}, },
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "library folder prefixes", name: "library folder prefixes",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: empty, FileName: empty,
FolderPaths: prefixOnly, FolderPath: prefixOnly,
Sites: empty, SiteID: empty,
WebURLs: empty, WebURL: empty,
}, },
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "library folder prefixes and contains", name: "library folder prefixes and contains",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: empty, FileName: empty,
FolderPaths: containsAndPrefix, FolderPath: containsAndPrefix,
Sites: empty, SiteID: empty,
WebURLs: empty, WebURL: empty,
}, },
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "list contains", name: "list contains",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: empty, FileName: empty,
FolderPaths: empty, FolderPath: empty,
ListItems: empty, ListItem: empty,
ListPaths: containsOnly, ListPath: containsOnly,
Sites: empty, SiteID: empty,
WebURLs: empty, WebURL: empty,
}, },
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "list prefixes", name: "list prefixes",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
ListPaths: prefixOnly, ListPath: prefixOnly,
}, },
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "list prefixes and contains", name: "list prefixes and contains",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
ListPaths: containsAndPrefix, ListPath: containsAndPrefix,
}, },
expectIncludeLen: 2, expectIncludeLen: 2,
}, },
{ {
name: "weburl contains", name: "weburl contains",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: empty, FileName: empty,
FolderPaths: empty, FolderPath: empty,
Sites: empty, SiteID: empty,
WebURLs: containsOnly, WebURL: containsOnly,
}, },
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "library folder suffixes", name: "library folder suffixes",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: empty, FileName: empty,
FolderPaths: empty, FolderPath: empty,
Sites: empty, SiteID: empty,
WebURLs: prefixOnly, // prefix pattern matches suffix pattern WebURL: prefixOnly, // prefix pattern matches suffix pattern
}, },
expectIncludeLen: 3, expectIncludeLen: 3,
}, },
{ {
name: "library folder suffixes and contains", name: "library folder suffixes and contains",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
FileNames: empty, FileName: empty,
FolderPaths: empty, FolderPath: empty,
Sites: empty, SiteID: empty,
WebURLs: containsAndPrefix, // prefix pattern matches suffix pattern WebURL: containsAndPrefix, // prefix pattern matches suffix pattern
}, },
expectIncludeLen: 6, expectIncludeLen: 6,
}, },
{ {
name: "Page Folder", name: "Page Folder",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
PageFolders: single, PageFolder: single,
}, },
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "Site Page ", name: "Site Page ",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
Pages: single, Page: single,
}, },
expectIncludeLen: 1, expectIncludeLen: 1,
}, },
{ {
name: "Page & library Files", name: "Page & library Files",
opts: utils.SharePointOpts{ opts: utils.SharePointOpts{
PageFolders: single, PageFolder: single,
FileNames: multi, FileName: multi,
}, },
expectIncludeLen: 2, expectIncludeLen: 2,
}, },

View File

@ -470,28 +470,28 @@ var (
Name: "AllLibraryItems", Name: "AllLibraryItems",
Expected: testdata.SharePointLibraryItems, Expected: testdata.SharePointLibraryItems,
Opts: utils.SharePointOpts{ Opts: utils.SharePointOpts{
FolderPaths: selectors.Any(), FolderPath: selectors.Any(),
}, },
}, },
{ {
Name: "FolderPrefixMatch", Name: "FolderPrefixMatch",
Expected: testdata.SharePointLibraryItems, Expected: testdata.SharePointLibraryItems,
Opts: utils.SharePointOpts{ Opts: utils.SharePointOpts{
FolderPaths: []string{testdata.SharePointLibraryFolder}, FolderPath: []string{testdata.SharePointLibraryFolder},
}, },
}, },
{ {
Name: "FolderPrefixMatchTrailingSlash", Name: "FolderPrefixMatchTrailingSlash",
Expected: testdata.SharePointLibraryItems, Expected: testdata.SharePointLibraryItems,
Opts: utils.SharePointOpts{ Opts: utils.SharePointOpts{
FolderPaths: []string{testdata.SharePointLibraryFolder + "/"}, FolderPath: []string{testdata.SharePointLibraryFolder + "/"},
}, },
}, },
{ {
Name: "FolderPrefixMatchTrailingSlash", Name: "FolderPrefixMatchTrailingSlash",
Expected: testdata.SharePointLibraryItems, Expected: testdata.SharePointLibraryItems,
Opts: utils.SharePointOpts{ Opts: utils.SharePointOpts{
FolderPaths: []string{testdata.SharePointLibraryFolder + "/"}, FolderPath: []string{testdata.SharePointLibraryFolder + "/"},
}, },
}, },
{ {
@ -501,7 +501,7 @@ var (
testdata.SharePointLibraryItems[1], testdata.SharePointLibraryItems[1],
}, },
Opts: utils.SharePointOpts{ Opts: utils.SharePointOpts{
FileNames: []string{ FileName: []string{
testdata.SharePointLibraryItems[0].ShortRef, testdata.SharePointLibraryItems[0].ShortRef,
testdata.SharePointLibraryItems[1].ShortRef, testdata.SharePointLibraryItems[1].ShortRef,
}, },
@ -511,7 +511,7 @@ var (
Name: "SingleItem", Name: "SingleItem",
Expected: []details.DetailsEntry{testdata.SharePointLibraryItems[0]}, Expected: []details.DetailsEntry{testdata.SharePointLibraryItems[0]},
Opts: utils.SharePointOpts{ Opts: utils.SharePointOpts{
FileNames: []string{ FileName: []string{
testdata.SharePointLibraryItems[0].SharePoint.ItemName, testdata.SharePointLibraryItems[0].SharePoint.ItemName,
}, },
}, },
@ -523,7 +523,7 @@ var (
testdata.SharePointLibraryItems[1], testdata.SharePointLibraryItems[1],
}, },
Opts: utils.SharePointOpts{ Opts: utils.SharePointOpts{
FileNames: []string{ FileName: []string{
testdata.SharePointLibraryItems[0].SharePoint.ItemName, testdata.SharePointLibraryItems[0].SharePoint.ItemName,
testdata.SharePointLibraryItems[1].SharePoint.ItemName, testdata.SharePointLibraryItems[1].SharePoint.ItemName,
}, },
@ -533,7 +533,7 @@ var (
Name: "NoSelectRepoItemName", Name: "NoSelectRepoItemName",
Expected: []details.DetailsEntry{}, Expected: []details.DetailsEntry{},
Opts: utils.SharePointOpts{ Opts: utils.SharePointOpts{
FileNames: []string{ FileName: []string{
testdata.SharePointLibraryItemPath1.Item(), testdata.SharePointLibraryItemPath1.Item(),
}, },
}, },

View File

@ -259,10 +259,12 @@ func createCollections(
Credentials: creds, Credentials: creds,
} }
foldersComplete, closer := observe.MessageWithCompletion(ctx, observe.Bulletf( foldersComplete, closer := observe.MessageWithCompletion(
"%s - %s", ctx,
observe.Safe(qp.Category.String()), observe.Bulletf(
observe.PII(user))) "%s - %s",
observe.Safe(qp.Category.String()),
observe.PII(user)))
defer closer() defer closer()
defer close(foldersComplete) defer close(foldersComplete)

View File

@ -383,10 +383,15 @@ func (oc *Collection) populateItems(ctx context.Context, errs *fault.Bus) {
return return
} }
queuedPath := "/" + parentPathString
if oc.source == SharePointSource && len(oc.driveName) > 0 {
queuedPath = "/" + oc.driveName + queuedPath
}
folderProgress, colCloser := observe.ProgressWithCount( folderProgress, colCloser := observe.ProgressWithCount(
ctx, ctx,
observe.ItemQueueMsg, observe.ItemQueueMsg,
observe.PII("/"+parentPathString), observe.PII(queuedPath),
int64(len(oc.driveItems))) int64(len(oc.driveItems)))
defer colCloser() defer colCloser()
defer close(folderProgress) defer close(folderProgress)

View File

@ -154,9 +154,12 @@ func Message(ctx context.Context, msg cleanable) {
bar := progress.New( bar := progress.New(
-1, -1,
mpb.NopStyle(), mpb.NopStyle(),
mpb.PrependDecorators( mpb.PrependDecorators(decor.Name(
decor.Name(message, decor.WC{W: len(message) + 1, C: decor.DidentRight}), message,
), decor.WC{
W: len(message) + 1,
C: decor.DidentRight,
})),
) )
// Complete the bar immediately // Complete the bar immediately
@ -193,8 +196,7 @@ func MessageWithCompletion(
mpb.SpinnerStyle(frames...).PositionLeft(), mpb.SpinnerStyle(frames...).PositionLeft(),
mpb.PrependDecorators( mpb.PrependDecorators(
decor.Name(message+":"), decor.Name(message+":"),
decor.Elapsed(decor.ET_STYLE_GO, decor.WC{W: 8}), decor.Elapsed(decor.ET_STYLE_GO, decor.WC{W: 8})),
),
mpb.BarFillerOnComplete("done"), mpb.BarFillerOnComplete("done"),
) )
@ -248,8 +250,7 @@ func ItemProgress(
decor.Name(header, decor.WCSyncSpaceR), decor.Name(header, decor.WCSyncSpaceR),
decor.Name(iname.String(), decor.WCSyncSpaceR), decor.Name(iname.String(), decor.WCSyncSpaceR),
decor.CountersKibiByte(" %.1f/%.1f ", decor.WC{W: 8}), decor.CountersKibiByte(" %.1f/%.1f ", decor.WC{W: 8}),
decor.NewPercentage("%d ", decor.WC{W: 4}), decor.NewPercentage("%d ", decor.WC{W: 4})),
),
} }
if !cfg.keepBarsAfterComplete { if !cfg.keepBarsAfterComplete {
@ -295,8 +296,7 @@ func ProgressWithCount(
mpb.PrependDecorators( mpb.PrependDecorators(
decor.Name(header, decor.WCSyncSpaceR), decor.Name(header, decor.WCSyncSpaceR),
decor.Name(message.String()), decor.Name(message.String()),
decor.Counters(0, " %d/%d "), decor.Counters(0, " %d/%d ")),
),
} }
if !cfg.keepBarsAfterComplete { if !cfg.keepBarsAfterComplete {

View File

@ -652,7 +652,7 @@ type SharePointInfo struct {
// Headers returns the human-readable names of properties in a SharePointInfo // Headers returns the human-readable names of properties in a SharePointInfo
// for printing out to a terminal in a columnar display. // for printing out to a terminal in a columnar display.
func (i SharePointInfo) Headers() []string { func (i SharePointInfo) Headers() []string {
return []string{"ItemName", "Library", "ParentPath", "Size", "WebURL", "Created", "Modified"} return []string{"ItemName", "Library", "ParentPath", "Size", "Owner", "Created", "Modified"}
} }
// Values returns the values matching the Headers list for printing // Values returns the values matching the Headers list for printing
@ -663,7 +663,7 @@ func (i SharePointInfo) Values() []string {
i.DriveName, i.DriveName,
i.ParentPath, i.ParentPath,
humanize.Bytes(uint64(i.Size)), humanize.Bytes(uint64(i.Size)),
i.WebURL, i.Owner,
common.FormatTabularDisplayTime(i.Created), common.FormatTabularDisplayTime(i.Created),
common.FormatTabularDisplayTime(i.Modified), common.FormatTabularDisplayTime(i.Modified),
} }

View File

@ -119,19 +119,20 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
Size: 1000, Size: 1000,
WebURL: "https://not.a.real/url", WebURL: "https://not.a.real/url",
DriveName: "aLibrary", DriveName: "aLibrary",
Owner: "user@email.com",
Created: now, Created: now,
Modified: now, Modified: now,
}, },
}, },
}, },
expectHs: []string{"ID", "ItemName", "Library", "ParentPath", "Size", "WebURL", "Created", "Modified"}, expectHs: []string{"ID", "ItemName", "Library", "ParentPath", "Size", "Owner", "Created", "Modified"},
expectVs: []string{ expectVs: []string{
"deadbeef", "deadbeef",
"itemName", "itemName",
"aLibrary", "aLibrary",
"parentPath", "parentPath",
"1.0 kB", "1.0 kB",
"https://not.a.real/url", "user@email.com",
nowStr, nowStr,
nowStr, nowStr,
}, },