Compare commits
4 Commits
main
...
hk-autocom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6e7b74cb6d | ||
|
|
78f2dbdccb | ||
|
|
84f4400635 | ||
|
|
bfea3dea34 |
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
- Added export support for emails in exchange backups as `.eml` files
|
- Added export support for emails in exchange backups as `.eml` files
|
||||||
- More colorful and informational cli output
|
- More colorful and informational cli output
|
||||||
|
- CLI completions for corso commands and flags (bash, zsh, fish, powershell)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Change file extension of messages export to json to match the content
|
- Change file extension of messages export to json to match the content
|
||||||
@ -19,6 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Automatically re-run a full delta query on incremental if the prior backup is found to have malformed prior-state information.
|
- Automatically re-run a full delta query on incremental if the prior backup is found to have malformed prior-state information.
|
||||||
- Retry drive item permission downloads during long-running backups after the jwt token expires and refreshes.
|
- Retry drive item permission downloads during long-running backups after the jwt token expires and refreshes.
|
||||||
|
|
||||||
|
### Known issues
|
||||||
|
- CLI completions cannot autocomplete multiple values for flags
|
||||||
|
|
||||||
## [v0.15.0] (beta) - 2023-10-31
|
## [v0.15.0] (beta) - 2023-10-31
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@ -75,7 +75,7 @@ func backupCmd() *cobra.Command {
|
|||||||
Short: "Backup your service data",
|
Short: "Backup your service data",
|
||||||
Long: `Backup the data stored in one of your M365 services.`,
|
Long: `Backup the data stored in one of your M365 services.`,
|
||||||
RunE: handleBackupCmd,
|
RunE: handleBackupCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ func createCmd() *cobra.Command {
|
|||||||
Use: createCommand,
|
Use: createCommand,
|
||||||
Short: "Backup an M365 Service",
|
Short: "Backup an M365 Service",
|
||||||
RunE: handleCreateCmd,
|
RunE: handleCreateCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ func listCmd() *cobra.Command {
|
|||||||
Use: listCommand,
|
Use: listCommand,
|
||||||
Short: "List the history of backups",
|
Short: "List the history of backups",
|
||||||
RunE: handleListCmd,
|
RunE: handleListCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ func detailsCmd() *cobra.Command {
|
|||||||
Use: detailsCommand,
|
Use: detailsCommand,
|
||||||
Short: "Shows the details of a backup",
|
Short: "Shows the details of a backup",
|
||||||
RunE: handleDetailsCmd,
|
RunE: handleDetailsCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ func deleteCmd() *cobra.Command {
|
|||||||
Use: deleteCommand,
|
Use: deleteCommand,
|
||||||
Short: "Deletes a backup",
|
Short: "Deletes a backup",
|
||||||
RunE: handleDeleteCmd,
|
RunE: handleDeleteCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -77,7 +77,7 @@ 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.
|
||||||
flags.AddMailBoxFlag(c)
|
flags.AddMailBoxFlag(c, utils.MailboxCompletionFunc(path.ExchangeService))
|
||||||
flags.AddDataFlag(c, []string{dataEmail, dataContacts, dataEvents}, false)
|
flags.AddDataFlag(c, []string{dataEmail, dataContacts, dataEvents}, false)
|
||||||
flags.AddFetchParallelismFlag(c)
|
flags.AddFetchParallelismFlag(c)
|
||||||
flags.AddDisableDeltaFlag(c)
|
flags.AddDisableDeltaFlag(c)
|
||||||
@ -90,7 +90,7 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c, fs = utils.AddCommand(cmd, exchangeListCmd())
|
c, fs = utils.AddCommand(cmd, exchangeListCmd())
|
||||||
fs.SortFlags = false
|
fs.SortFlags = false
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, false)
|
flags.AddBackupIDFlag(c, false, utils.BackupIDCompletionFunc(path.ExchangeService))
|
||||||
flags.AddAllBackupListFlags(c)
|
flags.AddAllBackupListFlags(c)
|
||||||
|
|
||||||
case detailsCommand:
|
case detailsCommand:
|
||||||
@ -104,7 +104,7 @@ 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.
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.ExchangeService))
|
||||||
flags.AddExchangeDetailsAndRestoreFlags(c, false)
|
flags.AddExchangeDetailsAndRestoreFlags(c, false)
|
||||||
|
|
||||||
case deleteCommand:
|
case deleteCommand:
|
||||||
@ -115,7 +115,7 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Example = exchangeServiceCommandDeleteExamples
|
c.Example = exchangeServiceCommandDeleteExamples
|
||||||
|
|
||||||
flags.AddMultipleBackupIDsFlag(c, false)
|
flags.AddMultipleBackupIDsFlag(c, false)
|
||||||
flags.AddBackupIDFlag(c, false)
|
flags.AddBackupIDFlag(c, false, utils.BackupIDCompletionFunc(path.ExchangeService))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
@ -70,7 +70,7 @@ func addGroupsCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Example = groupsServiceCommandCreateExamples
|
c.Example = groupsServiceCommandCreateExamples
|
||||||
|
|
||||||
// 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:
|
||||||
flags.AddGroupFlag(c)
|
flags.AddGroupFlag(c, utils.GroupsCompletionFunc())
|
||||||
flags.AddDataFlag(c, []string{flags.DataLibraries, flags.DataMessages}, false)
|
flags.AddDataFlag(c, []string{flags.DataLibraries, flags.DataMessages}, false)
|
||||||
flags.AddFetchParallelismFlag(c)
|
flags.AddFetchParallelismFlag(c)
|
||||||
flags.AddDisableDeltaFlag(c)
|
flags.AddDisableDeltaFlag(c)
|
||||||
@ -80,7 +80,7 @@ func addGroupsCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c, fs = utils.AddCommand(cmd, groupsListCmd(), utils.MarkPreviewCommand())
|
c, fs = utils.AddCommand(cmd, groupsListCmd(), utils.MarkPreviewCommand())
|
||||||
fs.SortFlags = false
|
fs.SortFlags = false
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, false)
|
flags.AddBackupIDFlag(c, false, utils.BackupIDCompletionFunc(path.GroupsService))
|
||||||
flags.AddAllBackupListFlags(c)
|
flags.AddAllBackupListFlags(c)
|
||||||
|
|
||||||
case detailsCommand:
|
case detailsCommand:
|
||||||
@ -94,7 +94,7 @@ func addGroupsCommands(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.
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.GroupsService))
|
||||||
flags.AddGroupDetailsAndRestoreFlags(c)
|
flags.AddGroupDetailsAndRestoreFlags(c)
|
||||||
flags.AddSharePointDetailsAndRestoreFlags(c)
|
flags.AddSharePointDetailsAndRestoreFlags(c)
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ func addGroupsCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Example = groupsServiceCommandDeleteExamples
|
c.Example = groupsServiceCommandDeleteExamples
|
||||||
|
|
||||||
flags.AddMultipleBackupIDsFlag(c, false)
|
flags.AddMultipleBackupIDsFlag(c, false)
|
||||||
flags.AddBackupIDFlag(c, false)
|
flags.AddBackupIDFlag(c, false, utils.BackupIDCompletionFunc(path.GroupsService))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
@ -65,14 +65,14 @@ func addOneDriveCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Use = c.Use + " " + oneDriveServiceCommandCreateUseSuffix
|
c.Use = c.Use + " " + oneDriveServiceCommandCreateUseSuffix
|
||||||
c.Example = oneDriveServiceCommandCreateExamples
|
c.Example = oneDriveServiceCommandCreateExamples
|
||||||
|
|
||||||
flags.AddUserFlag(c)
|
flags.AddUserFlag(c, utils.UsersCompletionFunc(path.OneDriveService))
|
||||||
flags.AddGenericBackupFlags(c)
|
flags.AddGenericBackupFlags(c)
|
||||||
|
|
||||||
case listCommand:
|
case listCommand:
|
||||||
c, fs = utils.AddCommand(cmd, oneDriveListCmd())
|
c, fs = utils.AddCommand(cmd, oneDriveListCmd())
|
||||||
fs.SortFlags = false
|
fs.SortFlags = false
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, false)
|
flags.AddBackupIDFlag(c, false, utils.BackupIDCompletionFunc(path.OneDriveService))
|
||||||
flags.AddAllBackupListFlags(c)
|
flags.AddAllBackupListFlags(c)
|
||||||
|
|
||||||
case detailsCommand:
|
case detailsCommand:
|
||||||
@ -83,7 +83,7 @@ func addOneDriveCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Example = oneDriveServiceCommandDetailsExamples
|
c.Example = oneDriveServiceCommandDetailsExamples
|
||||||
|
|
||||||
flags.AddSkipReduceFlag(c)
|
flags.AddSkipReduceFlag(c)
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.OneDriveService))
|
||||||
flags.AddOneDriveDetailsAndRestoreFlags(c)
|
flags.AddOneDriveDetailsAndRestoreFlags(c)
|
||||||
|
|
||||||
case deleteCommand:
|
case deleteCommand:
|
||||||
@ -94,7 +94,7 @@ func addOneDriveCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Example = oneDriveServiceCommandDeleteExamples
|
c.Example = oneDriveServiceCommandDeleteExamples
|
||||||
|
|
||||||
flags.AddMultipleBackupIDsFlag(c, false)
|
flags.AddMultipleBackupIDsFlag(c, false)
|
||||||
flags.AddBackupIDFlag(c, false)
|
flags.AddBackupIDFlag(c, false, utils.BackupIDCompletionFunc(path.OneDriveService))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
@ -76,7 +76,7 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Use = c.Use + " " + sharePointServiceCommandCreateUseSuffix
|
c.Use = c.Use + " " + sharePointServiceCommandCreateUseSuffix
|
||||||
c.Example = sharePointServiceCommandCreateExamples
|
c.Example = sharePointServiceCommandCreateExamples
|
||||||
|
|
||||||
flags.AddSiteFlag(c, true)
|
flags.AddSiteFlag(c, true, utils.SitesCompletionFunc())
|
||||||
flags.AddSiteIDFlag(c, true)
|
flags.AddSiteIDFlag(c, true)
|
||||||
flags.AddDataFlag(c, []string{flags.DataLibraries}, true)
|
flags.AddDataFlag(c, []string{flags.DataLibraries}, true)
|
||||||
flags.AddGenericBackupFlags(c)
|
flags.AddGenericBackupFlags(c)
|
||||||
@ -85,7 +85,7 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c, fs = utils.AddCommand(cmd, sharePointListCmd())
|
c, fs = utils.AddCommand(cmd, sharePointListCmd())
|
||||||
fs.SortFlags = false
|
fs.SortFlags = false
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, false)
|
flags.AddBackupIDFlag(c, false, utils.BackupIDCompletionFunc(path.SharePointService))
|
||||||
flags.AddAllBackupListFlags(c)
|
flags.AddAllBackupListFlags(c)
|
||||||
|
|
||||||
case detailsCommand:
|
case detailsCommand:
|
||||||
@ -96,7 +96,7 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Example = sharePointServiceCommandDetailsExamples
|
c.Example = sharePointServiceCommandDetailsExamples
|
||||||
|
|
||||||
flags.AddSkipReduceFlag(c)
|
flags.AddSkipReduceFlag(c)
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.SharePointService))
|
||||||
flags.AddSharePointDetailsAndRestoreFlags(c)
|
flags.AddSharePointDetailsAndRestoreFlags(c)
|
||||||
|
|
||||||
case deleteCommand:
|
case deleteCommand:
|
||||||
@ -107,7 +107,7 @@ func addSharePointCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
c.Example = sharePointServiceCommandDeleteExamples
|
c.Example = sharePointServiceCommandDeleteExamples
|
||||||
|
|
||||||
flags.AddMultipleBackupIDsFlag(c, false)
|
flags.AddMultipleBackupIDsFlag(c, false)
|
||||||
flags.AddBackupIDFlag(c, false)
|
flags.AddBackupIDFlag(c, false, utils.BackupIDCompletionFunc(path.SharePointService))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package cli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
@ -54,7 +55,19 @@ func preRun(cc *cobra.Command, args []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
avoidTheseCommands := []string{
|
avoidTheseCommands := []string{
|
||||||
"corso", "env", "help", "backup", "details", "list", "restore", "export", "delete", "repo", "init", "connect",
|
"corso",
|
||||||
|
"env",
|
||||||
|
"help",
|
||||||
|
"backup",
|
||||||
|
"details",
|
||||||
|
"list",
|
||||||
|
"restore",
|
||||||
|
"export",
|
||||||
|
"delete",
|
||||||
|
"repo",
|
||||||
|
"init",
|
||||||
|
"connect",
|
||||||
|
"completion [bash|zsh|fish|powershell]",
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(logger.ResolvedLogFile) > 0 && !slices.Contains(avoidTheseCommands, cc.Use) {
|
if len(logger.ResolvedLogFile) > 0 && !slices.Contains(avoidTheseCommands, cc.Use) {
|
||||||
@ -121,6 +134,7 @@ func BuildCommandTree(cmd *cobra.Command) {
|
|||||||
cmd.SetUsageTemplate(indentExamplesTemplate(corsoCmd.UsageTemplate()))
|
cmd.SetUsageTemplate(indentExamplesTemplate(corsoCmd.UsageTemplate()))
|
||||||
|
|
||||||
cmd.CompletionOptions.DisableDefaultCmd = true
|
cmd.CompletionOptions.DisableDefaultCmd = true
|
||||||
|
cmd.SuggestionsMinimumDistance = 2 // default
|
||||||
|
|
||||||
repo.AddCommands(cmd)
|
repo.AddCommands(cmd)
|
||||||
backup.AddCommands(cmd)
|
backup.AddCommands(cmd)
|
||||||
@ -128,6 +142,53 @@ func BuildCommandTree(cmd *cobra.Command) {
|
|||||||
export.AddCommands(cmd)
|
export.AddCommands(cmd)
|
||||||
debug.AddCommands(cmd)
|
debug.AddCommands(cmd)
|
||||||
help.AddCommands(cmd)
|
help.AddCommands(cmd)
|
||||||
|
AddCompletion(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are not using the default completion command as it will be
|
||||||
|
// harder to control it, for example skipping printing "Logging to file"
|
||||||
|
// message
|
||||||
|
func AddCompletion(cmd *cobra.Command) {
|
||||||
|
longMessage := `Generate shell completion script for Corso.
|
||||||
|
|
||||||
|
These need to be hooked into your shell to enable completions for Corso.
|
||||||
|
|
||||||
|
For bash, add the following line to your ` + "`~/.bashrc` \n" + // two spaces for markdown and \n for go
|
||||||
|
"`eval \"$(corso completion bash)\"` \n" + `
|
||||||
|
|
||||||
|
For zsh, add the following line to your ` + "`~/.zshrc` \n" +
|
||||||
|
"`eval \"$(corso completion zsh)\"` \n" + `
|
||||||
|
|
||||||
|
For fish, add the following line to your ` + "`~/.config/fish/config.fish` \n" +
|
||||||
|
"`corso completion fish | source` \n" + `
|
||||||
|
|
||||||
|
For powershell, add the following to your ` + "`$PROFILE` \n" +
|
||||||
|
"`Invoke-Expression \"$(corso completion powershell)\"`"
|
||||||
|
completion := &cobra.Command{
|
||||||
|
Use: "completion [bash|zsh|fish|powershell]",
|
||||||
|
Short: "Generate completion script",
|
||||||
|
Long: longMessage,
|
||||||
|
DisableFlagsInUseLine: true,
|
||||||
|
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
|
||||||
|
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
|
||||||
|
Hidden: true,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
switch args[0] {
|
||||||
|
case "bash":
|
||||||
|
return cmd.Root().GenBashCompletion(os.Stdout)
|
||||||
|
case "zsh":
|
||||||
|
return cmd.Root().GenZshCompletion(os.Stdout)
|
||||||
|
case "fish":
|
||||||
|
return cmd.Root().GenFishCompletion(os.Stdout, true)
|
||||||
|
case "powershell":
|
||||||
|
return cmd.Root().GenPowerShellCompletionWithDesc(os.Stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("unknown shell type %q", args[0])
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ func addExchangeCommands(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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.ExchangeService))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ func addGroupsCommands(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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.GroupsService))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ 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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.OneDriveService))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
"github.com/alcionai/corso/src/pkg/selectors"
|
"github.com/alcionai/corso/src/pkg/selectors"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ func addSharePointCommands(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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.SharePointService))
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called by export.go to map subcommands to provider-specific handling.
|
// called by export.go to map subcommands to provider-specific handling.
|
||||||
@ -26,7 +27,7 @@ func addExchangeCommands(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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.ExchangeService))
|
||||||
flags.AddExchangeDetailsAndRestoreFlags(c, true)
|
flags.AddExchangeDetailsAndRestoreFlags(c, true)
|
||||||
flags.AddExportConfigFlags(c)
|
flags.AddExportConfigFlags(c)
|
||||||
flags.AddFailFastFlag(c)
|
flags.AddFailFastFlag(c)
|
||||||
|
|||||||
@ -49,7 +49,7 @@ func exportCmd() *cobra.Command {
|
|||||||
Short: "Export your service data",
|
Short: "Export your service data",
|
||||||
Long: `Export the data stored in one of your M365 services.`,
|
Long: `Export the data stored in one of your M365 services.`,
|
||||||
RunE: handleExportCmd,
|
RunE: handleExportCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
"github.com/alcionai/corso/src/pkg/control"
|
"github.com/alcionai/corso/src/pkg/control"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called by export.go to map subcommands to provider-specific handling.
|
// called by export.go to map subcommands to provider-specific handling.
|
||||||
@ -27,8 +28,8 @@ func addGroupsCommands(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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.GroupsService))
|
||||||
flags.AddSiteFlag(c, false)
|
flags.AddSiteFlag(c, false, utils.SitesCompletionFunc())
|
||||||
flags.AddSiteIDFlag(c, false)
|
flags.AddSiteIDFlag(c, false)
|
||||||
flags.AddSharePointDetailsAndRestoreFlags(c)
|
flags.AddSharePointDetailsAndRestoreFlags(c)
|
||||||
flags.AddGroupDetailsAndRestoreFlags(c)
|
flags.AddGroupDetailsAndRestoreFlags(c)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called by export.go to map subcommands to provider-specific handling.
|
// called by export.go to map subcommands to provider-specific handling.
|
||||||
@ -26,7 +27,7 @@ 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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.OneDriveService))
|
||||||
flags.AddOneDriveDetailsAndRestoreFlags(c)
|
flags.AddOneDriveDetailsAndRestoreFlags(c)
|
||||||
flags.AddExportConfigFlags(c)
|
flags.AddExportConfigFlags(c)
|
||||||
flags.AddFailFastFlag(c)
|
flags.AddFailFastFlag(c)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called by export.go to map subcommands to provider-specific handling.
|
// called by export.go to map subcommands to provider-specific handling.
|
||||||
@ -26,7 +27,7 @@ func addSharePointCommands(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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.SharePointService))
|
||||||
flags.AddSharePointDetailsAndRestoreFlags(c)
|
flags.AddSharePointDetailsAndRestoreFlags(c)
|
||||||
flags.AddExportConfigFlags(c)
|
flags.AddExportConfigFlags(c)
|
||||||
flags.AddFailFastFlag(c)
|
flags.AddFailFastFlag(c)
|
||||||
|
|||||||
@ -68,9 +68,14 @@ func AddGroupDetailsAndRestoreFlags(cmd *cobra.Command) {
|
|||||||
// Mail is most accurate, MailNickame is accurate and shorter, but the end user
|
// Mail is most accurate, MailNickame is accurate and shorter, but the end user
|
||||||
// may not see either one visibly.
|
// may not see either one visibly.
|
||||||
// https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0&tabs=http
|
// https://learn.microsoft.com/en-us/graph/api/group-list?view=graph-rest-1.0&tabs=http
|
||||||
func AddGroupFlag(cmd *cobra.Command) {
|
func AddGroupFlag(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
completionFunc func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective),
|
||||||
|
) {
|
||||||
cmd.Flags().StringSliceVar(
|
cmd.Flags().StringSliceVar(
|
||||||
&GroupFV,
|
&GroupFV,
|
||||||
GroupFN, nil,
|
GroupFN, nil,
|
||||||
"Backup data by group; accepts '"+Wildcard+"' to select all groups.")
|
"Backup data by group; accepts '"+Wildcard+"' to select all groups.")
|
||||||
|
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(GroupFN, completionFunc))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
var CategoryDataFV []string
|
var CategoryDataFV []string
|
||||||
@ -39,4 +40,36 @@ func AddDataFlag(cmd *cobra.Command, allowed []string, hide bool) {
|
|||||||
if hide {
|
if hide {
|
||||||
cobra.CheckErr(fs.MarkHidden(CategoryDataFN))
|
cobra.CheckErr(fs.MarkHidden(CategoryDataFN))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(meain): This is a hacky way to get it to autocomplete multiple items
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(
|
||||||
|
CategoryDataFN,
|
||||||
|
func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
added := strings.Split(toComplete, ",")
|
||||||
|
last := added[len(added)-1]
|
||||||
|
added = added[:len(added)-1]
|
||||||
|
|
||||||
|
if slices.Contains(added, last) {
|
||||||
|
added = append(added, last)
|
||||||
|
last = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
pending := make([]string, 0, len(allowed)-len(added))
|
||||||
|
for _, a := range allowed {
|
||||||
|
if !slices.Contains(added, a) && strings.HasPrefix(a, last) {
|
||||||
|
pending = append(pending, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completions := []string{}
|
||||||
|
for _, p := range pending {
|
||||||
|
completions = append(completions, strings.Join(append(added, p), ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
return completions, cobra.ShellCompDirectiveNoSpace
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,16 +22,24 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddUserFlag adds the --user flag.
|
// AddUserFlag adds the --user flag.
|
||||||
func AddUserFlag(cmd *cobra.Command) {
|
func AddUserFlag(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
completionFunc func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective),
|
||||||
|
) {
|
||||||
cmd.Flags().StringSliceVar(
|
cmd.Flags().StringSliceVar(
|
||||||
&UserFV,
|
&UserFV,
|
||||||
UserFN, nil,
|
UserFN, nil,
|
||||||
"Backup a specific user's data; accepts '"+Wildcard+"' to select all users.")
|
"Backup a specific user's data; accepts '"+Wildcard+"' to select all users.")
|
||||||
cobra.CheckErr(cmd.MarkFlagRequired(UserFN))
|
cobra.CheckErr(cmd.MarkFlagRequired(UserFN))
|
||||||
|
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(UserFN, completionFunc))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddMailBoxFlag adds the --user and --mailbox flag.
|
// AddMailBoxFlag adds the --user and --mailbox flag.
|
||||||
func AddMailBoxFlag(cmd *cobra.Command) {
|
func AddMailBoxFlag(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
completionFunc func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective),
|
||||||
|
) {
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
|
||||||
flags.StringSliceVar(
|
flags.StringSliceVar(
|
||||||
@ -41,10 +49,22 @@ func AddMailBoxFlag(cmd *cobra.Command) {
|
|||||||
|
|
||||||
cobra.CheckErr(flags.MarkDeprecated(UserFN, fmt.Sprintf("use --%s instead", MailBoxFN)))
|
cobra.CheckErr(flags.MarkDeprecated(UserFN, fmt.Sprintf("use --%s instead", MailBoxFN)))
|
||||||
|
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(UserFN,
|
||||||
|
func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
message := fmt.Sprintf("This flag is deprecated, Use --%s instead", MailBoxFN)
|
||||||
|
return cobra.AppendActiveHelp(nil, message), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}))
|
||||||
|
|
||||||
flags.StringSliceVar(
|
flags.StringSliceVar(
|
||||||
&UserFV,
|
&UserFV,
|
||||||
MailBoxFN, nil,
|
MailBoxFN, nil,
|
||||||
"Backup a specific mailbox's data; accepts '"+Wildcard+"' to select all mailbox.")
|
"Backup a specific mailbox's data; accepts '"+Wildcard+"' to select all mailbox.")
|
||||||
|
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(MailBoxFN, completionFunc))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddAzureCredsFlags adds M365 cred flags
|
// AddAzureCredsFlags adds M365 cred flags
|
||||||
|
|||||||
@ -41,8 +41,13 @@ func AddMultipleBackupIDsFlag(cmd *cobra.Command, require bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddBackupIDFlag adds the --backup flag.
|
// AddBackupIDFlag adds the --backup flag.
|
||||||
func AddBackupIDFlag(cmd *cobra.Command, require bool) {
|
func AddBackupIDFlag(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
require bool,
|
||||||
|
completionFunc func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective),
|
||||||
|
) {
|
||||||
cmd.Flags().StringVar(&BackupIDFV, BackupFN, "", "ID of the backup to retrieve.")
|
cmd.Flags().StringVar(&BackupIDFV, BackupFN, "", "ID of the backup to retrieve.")
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(BackupFN, completionFunc))
|
||||||
|
|
||||||
if require {
|
if require {
|
||||||
cobra.CheckErr(cmd.MarkFlagRequired(BackupFN))
|
cobra.CheckErr(cmd.MarkFlagRequired(BackupFN))
|
||||||
|
|||||||
@ -95,6 +95,7 @@ func AddSharePointDetailsAndRestoreFlags(cmd *cobra.Command) {
|
|||||||
// AddSiteIDFlag adds the --site-id flag, which accepts site ID values.
|
// AddSiteIDFlag adds the --site-id flag, which accepts site ID values.
|
||||||
// This flag is hidden, since we expect users to prefer the --site url
|
// This flag is hidden, since we expect users to prefer the --site url
|
||||||
// and do not want to encourage confusion.
|
// and do not want to encourage confusion.
|
||||||
|
// TODO(meain): --site is the primary one, but it would be useful to have comepletion for this as well
|
||||||
func AddSiteIDFlag(cmd *cobra.Command, multiple bool) {
|
func AddSiteIDFlag(cmd *cobra.Command, multiple bool) {
|
||||||
fs := cmd.Flags()
|
fs := cmd.Flags()
|
||||||
|
|
||||||
@ -112,11 +113,17 @@ func AddSiteIDFlag(cmd *cobra.Command, multiple bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AddSiteFlag adds the --site flag, which accepts webURL values.
|
// AddSiteFlag adds the --site flag, which accepts webURL values.
|
||||||
func AddSiteFlag(cmd *cobra.Command, multiple bool) {
|
func AddSiteFlag(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
multiple bool,
|
||||||
|
completionFunc func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective),
|
||||||
|
) {
|
||||||
message := "Web URL of the site to operate on"
|
message := "Web URL of the site to operate on"
|
||||||
if multiple {
|
if multiple {
|
||||||
message += "; accepts '" + Wildcard + "' to select all sites."
|
message += "; accepts '" + Wildcard + "' to select all sites."
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringSliceVar(&WebURLFV, SiteFN, nil, message)
|
cmd.Flags().StringSliceVar(&WebURLFV, SiteFN, nil, message)
|
||||||
|
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(SiteFN, completionFunc))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
. "github.com/alcionai/corso/src/cli/print"
|
. "github.com/alcionai/corso/src/cli/print"
|
||||||
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddCommands attaches all `corso env * *` commands to the parent.
|
// AddCommands attaches all `corso env * *` commands to the parent.
|
||||||
@ -19,7 +20,7 @@ func envCmd() *cobra.Command {
|
|||||||
Short: "env var guide",
|
Short: "env var guide",
|
||||||
Long: `A guide to using environment variables in Corso.`,
|
Long: `A guide to using environment variables in Corso.`,
|
||||||
RunE: handleEnvCmd,
|
RunE: handleEnvCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
envCmd.SetHelpFunc(envGuide)
|
envCmd.SetHelpFunc(envGuide)
|
||||||
|
|
||||||
|
|||||||
@ -77,7 +77,7 @@ func repoCmd() *cobra.Command {
|
|||||||
Short: "Manage your repositories",
|
Short: "Manage your repositories",
|
||||||
Long: `Initialize, configure, connect and update to your account backup repositories`,
|
Long: `Initialize, configure, connect and update to your account backup repositories`,
|
||||||
RunE: handleRepoCmd,
|
RunE: handleRepoCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ func initCmd() *cobra.Command {
|
|||||||
Short: "Initialize a repository.",
|
Short: "Initialize a repository.",
|
||||||
Long: `Create a new repository to store your backups.`,
|
Long: `Create a new repository to store your backups.`,
|
||||||
RunE: handleInitCmd,
|
RunE: handleInitCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ func connectCmd() *cobra.Command {
|
|||||||
Short: "Connect to a repository.",
|
Short: "Connect to a repository.",
|
||||||
Long: `Connect to an existing repository.`,
|
Long: `Connect to an existing repository.`,
|
||||||
RunE: handleConnectCmd,
|
RunE: handleConnectCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ func maintenanceCmd() *cobra.Command {
|
|||||||
Short: "Run maintenance on an existing repository",
|
Short: "Run maintenance on an existing repository",
|
||||||
Long: `Run maintenance on an existing repository to optimize performance and storage use`,
|
Long: `Run maintenance on an existing repository to optimize performance and storage use`,
|
||||||
RunE: handleMaintenanceCmd,
|
RunE: handleMaintenanceCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called by restore.go to map subcommands to provider-specific handling.
|
// called by restore.go to map subcommands to provider-specific handling.
|
||||||
@ -26,7 +27,7 @@ func addExchangeCommands(cmd *cobra.Command) *cobra.Command {
|
|||||||
// general flags
|
// general flags
|
||||||
fs.SortFlags = false
|
fs.SortFlags = false
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.ExchangeService))
|
||||||
flags.AddExchangeDetailsAndRestoreFlags(c, false)
|
flags.AddExchangeDetailsAndRestoreFlags(c, false)
|
||||||
flags.AddRestoreConfigFlags(c, true)
|
flags.AddRestoreConfigFlags(c, true)
|
||||||
flags.AddFailFastFlag(c)
|
flags.AddFailFastFlag(c)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
"github.com/alcionai/corso/src/internal/common/dttm"
|
"github.com/alcionai/corso/src/internal/common/dttm"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called by restore.go to map subcommands to provider-specific handling.
|
// called by restore.go to map subcommands to provider-specific handling.
|
||||||
@ -26,8 +27,8 @@ func addGroupsCommands(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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.GroupsService))
|
||||||
flags.AddSiteFlag(c, false)
|
flags.AddSiteFlag(c, false, utils.SitesCompletionFunc())
|
||||||
flags.AddSiteIDFlag(c, false)
|
flags.AddSiteIDFlag(c, false)
|
||||||
flags.AddNoPermissionsFlag(c)
|
flags.AddNoPermissionsFlag(c)
|
||||||
flags.AddSharePointDetailsAndRestoreFlags(c)
|
flags.AddSharePointDetailsAndRestoreFlags(c)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
"github.com/alcionai/corso/src/internal/common/dttm"
|
"github.com/alcionai/corso/src/internal/common/dttm"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called by restore.go to map subcommands to provider-specific handling.
|
// called by restore.go to map subcommands to provider-specific handling.
|
||||||
@ -26,7 +27,7 @@ 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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.OneDriveService))
|
||||||
flags.AddOneDriveDetailsAndRestoreFlags(c)
|
flags.AddOneDriveDetailsAndRestoreFlags(c)
|
||||||
flags.AddNoPermissionsFlag(c)
|
flags.AddNoPermissionsFlag(c)
|
||||||
flags.AddRestoreConfigFlags(c, true)
|
flags.AddRestoreConfigFlags(c, true)
|
||||||
|
|||||||
@ -74,7 +74,7 @@ func restoreCmd() *cobra.Command {
|
|||||||
Short: "Restore your service data",
|
Short: "Restore your service data",
|
||||||
Long: `Restore the data stored in one of your M365 services.`,
|
Long: `Restore the data stored in one of your M365 services.`,
|
||||||
RunE: handleRestoreCmd,
|
RunE: handleRestoreCmd,
|
||||||
Args: cobra.NoArgs,
|
Args: utils.SubcommandsRequiredWithSuggestions,
|
||||||
Example: restoreCommandExamples,
|
Example: restoreCommandExamples,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/alcionai/corso/src/cli/flags"
|
"github.com/alcionai/corso/src/cli/flags"
|
||||||
"github.com/alcionai/corso/src/cli/utils"
|
"github.com/alcionai/corso/src/cli/utils"
|
||||||
"github.com/alcionai/corso/src/internal/common/dttm"
|
"github.com/alcionai/corso/src/internal/common/dttm"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
)
|
)
|
||||||
|
|
||||||
// called by restore.go to map subcommands to provider-specific handling.
|
// called by restore.go to map subcommands to provider-specific handling.
|
||||||
@ -26,7 +27,7 @@ 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
|
||||||
|
|
||||||
flags.AddBackupIDFlag(c, true)
|
flags.AddBackupIDFlag(c, true, utils.BackupIDCompletionFunc(path.SharePointService))
|
||||||
flags.AddSharePointDetailsAndRestoreFlags(c)
|
flags.AddSharePointDetailsAndRestoreFlags(c)
|
||||||
flags.AddNoPermissionsFlag(c)
|
flags.AddNoPermissionsFlag(c)
|
||||||
flags.AddRestoreConfigFlags(c, true)
|
flags.AddRestoreConfigFlags(c, true)
|
||||||
|
|||||||
194
src/cli/utils/completions.go
Normal file
194
src/cli/utils/completions.go
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/alcionai/corso/src/pkg/backup"
|
||||||
|
"github.com/alcionai/corso/src/pkg/fault"
|
||||||
|
"github.com/alcionai/corso/src/pkg/path"
|
||||||
|
"github.com/alcionai/corso/src/pkg/services/m365"
|
||||||
|
"github.com/alcionai/corso/src/pkg/store"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetBackups(ctx context.Context, cmd *cobra.Command, service path.ServiceType) ([]*backup.Backup, error) {
|
||||||
|
r, _, err := GetAccountAndConnect(ctx, cmd, service)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer CloseRepo(ctx, r)
|
||||||
|
|
||||||
|
return r.BackupsByTag(ctx, store.Service(service))
|
||||||
|
}
|
||||||
|
|
||||||
|
type completionFunc func(*cobra.Command, []string, string) ([]string, cobra.ShellCompDirective)
|
||||||
|
|
||||||
|
func BackupIDCompletionFunc(service path.ServiceType) completionFunc {
|
||||||
|
return func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
bs, err := GetBackups(cmd.Context(), cmd, service)
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(
|
||||||
|
nil,
|
||||||
|
fmt.Sprintf("Unable to fetch %s backups", service)), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(bs) == 0 {
|
||||||
|
return cobra.AppendActiveHelp(
|
||||||
|
nil,
|
||||||
|
fmt.Sprintf("No %s backups found", service)), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
backups := make([]string, len(bs))
|
||||||
|
for _, b := range bs {
|
||||||
|
backups = append(backups, fmt.Sprintf("%s\tCreated at %s", b.GetID(), b.CreationTime))
|
||||||
|
}
|
||||||
|
|
||||||
|
return cobra.AppendActiveHelp(backups, "Choose backup ID to use"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func UsersCompletionFunc(service path.ServiceType) completionFunc {
|
||||||
|
return func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
r, acct, err := AccountConnectAndWriteRepoConfig(ctx, cmd, service)
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(
|
||||||
|
nil,
|
||||||
|
fmt.Sprintf("Unable to fetch %s users", service)), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
ins, err := UsersMap(ctx, *acct, Control(), r.Counter(), fault.New(true))
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(
|
||||||
|
nil,
|
||||||
|
fmt.Sprintf("Unable to fetch %s users", service)), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ins.IDs()) == 0 {
|
||||||
|
return cobra.AppendActiveHelp(
|
||||||
|
nil,
|
||||||
|
fmt.Sprintf("No %s users found", service)), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
backups := make([]string, len(ins.IDs()))
|
||||||
|
|
||||||
|
for _, u := range ins.IDs() {
|
||||||
|
name, _ := ins.NameOf(u)
|
||||||
|
backups = append(backups, fmt.Sprintf("%s\t%s", u, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
return cobra.AppendActiveHelp(backups, "Choose user ID to use"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func MailboxCompletionFunc(service path.ServiceType) completionFunc {
|
||||||
|
return func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
r, acct, err := AccountConnectAndWriteRepoConfig(ctx, cmd, service)
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(
|
||||||
|
nil,
|
||||||
|
fmt.Sprintf("Unable to fetch %s mailboxes", service)), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
ins, err := UsersMap(ctx, *acct, Control(), r.Counter(), fault.New(true))
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(
|
||||||
|
nil,
|
||||||
|
fmt.Sprintf("Unable to fetch %s mailboxes", service)), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ins.IDs()) == 0 {
|
||||||
|
return cobra.AppendActiveHelp(
|
||||||
|
nil,
|
||||||
|
fmt.Sprintf("No %s mailboxes found", service)), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
backups := ins.Names()
|
||||||
|
|
||||||
|
return cobra.AppendActiveHelp(backups, "Choose mailbox to use"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GroupsCompletionFunc() completionFunc {
|
||||||
|
return func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
_, acct, err := AccountConnectAndWriteRepoConfig(ctx, cmd, path.GroupsService)
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(nil, "Unable to fetch Groups"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
ins, err := m365.GroupsMap(ctx, *acct, fault.New(true))
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(nil, "Unable to fetch Groups"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ins.IDs()) == 0 {
|
||||||
|
return cobra.AppendActiveHelp(nil, "No Groups found"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
backups := make([]string, len(ins.IDs()))
|
||||||
|
|
||||||
|
for _, u := range ins.IDs() {
|
||||||
|
name, _ := ins.NameOf(u)
|
||||||
|
backups = append(backups, fmt.Sprintf("%s\t%s", u, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
return cobra.AppendActiveHelp(backups, "Choose Group to use"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func SitesCompletionFunc() completionFunc {
|
||||||
|
return func(
|
||||||
|
cmd *cobra.Command,
|
||||||
|
args []string,
|
||||||
|
toComplete string,
|
||||||
|
) ([]string, cobra.ShellCompDirective) {
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
_, acct, err := AccountConnectAndWriteRepoConfig(ctx, cmd, path.SharePointService)
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(nil, "Unable to fetch Sites"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
ins, err := m365.SitesMap(ctx, *acct, fault.New(true))
|
||||||
|
if err != nil {
|
||||||
|
return cobra.AppendActiveHelp(nil, "Unable to fetch Sites"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ins.IDs()) == 0 {
|
||||||
|
return cobra.AppendActiveHelp(nil, "No Sites found"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
|
||||||
|
backups := make([]string, len(ins.IDs()))
|
||||||
|
|
||||||
|
for _, u := range ins.IDs() {
|
||||||
|
name, _ := ins.NameOf(u)
|
||||||
|
backups = append(backups, fmt.Sprintf("%s\t%s", u, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
return cobra.AppendActiveHelp(backups, "Choose Site to use"), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
}
|
||||||
115
src/cli/utils/suggestions.go
Normal file
115
src/cli/utils/suggestions.go
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
// The code in this file is mostly lifted out of cobra itself. It as
|
||||||
|
// of now has some issue with how it handles completions for
|
||||||
|
// subcommands and only autocompletes for top level commands.
|
||||||
|
// https://github.com/spf13/cobra/issues/981#issuecomment-547003669
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SubcommandsRequiredWithSuggestions will ensure we have a subcommand provided by the user and augments it with
|
||||||
|
// suggestion for commands, alias and help on root command.
|
||||||
|
func SubcommandsRequiredWithSuggestions(cmd *cobra.Command, args []string) error {
|
||||||
|
requireMsg := "%s requires a valid subcommand"
|
||||||
|
// This will be triggered if cobra didn't find any subcommands.
|
||||||
|
// Find some suggestions.
|
||||||
|
var suggestions []string
|
||||||
|
|
||||||
|
if len(args) != 0 && !cmd.DisableSuggestions {
|
||||||
|
typedName := args[0]
|
||||||
|
|
||||||
|
if cmd.SuggestionsMinimumDistance <= 0 {
|
||||||
|
cmd.SuggestionsMinimumDistance = 2
|
||||||
|
}
|
||||||
|
// subcommand suggestions
|
||||||
|
suggestions = cmd.SuggestionsFor(args[0])
|
||||||
|
|
||||||
|
// subcommand alias suggestions (with distance, not exact)
|
||||||
|
for _, c := range cmd.Commands() {
|
||||||
|
if c.IsAvailableCommand() {
|
||||||
|
for _, alias := range c.Aliases {
|
||||||
|
levenshteinDistance := levenshteinDistance(typedName, alias, true)
|
||||||
|
suggestByLevenshtein := levenshteinDistance <= cmd.SuggestionsMinimumDistance
|
||||||
|
suggestByPrefix := strings.HasPrefix(strings.ToLower(alias), strings.ToLower(typedName))
|
||||||
|
|
||||||
|
if suggestByLevenshtein || suggestByPrefix {
|
||||||
|
suggestions = append(suggestions, alias)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// help for root command
|
||||||
|
if !cmd.HasParent() {
|
||||||
|
help := "help"
|
||||||
|
levenshteinDistance := levenshteinDistance(typedName, help, true)
|
||||||
|
suggestByLevenshtein := levenshteinDistance <= cmd.SuggestionsMinimumDistance
|
||||||
|
suggestByPrefix := strings.HasPrefix(strings.ToLower(help), strings.ToLower(typedName))
|
||||||
|
|
||||||
|
if suggestByLevenshtein || suggestByPrefix {
|
||||||
|
suggestions = append(suggestions, help)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var suggestionsMsg string
|
||||||
|
if len(suggestions) > 0 {
|
||||||
|
suggestionsMsg += "\n\nDid you mean this?\n"
|
||||||
|
for _, s := range suggestions {
|
||||||
|
suggestionsMsg += fmt.Sprintf("\t%v\n", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(suggestionsMsg) > 0 {
|
||||||
|
requireMsg = fmt.Sprintf("%s. %s", requireMsg, suggestionsMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf(requireMsg, cmd.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
// levenshteinDistance compares two strings and returns the levenshtein distance between them.
|
||||||
|
func levenshteinDistance(s, t string, ignoreCase bool) int {
|
||||||
|
if ignoreCase {
|
||||||
|
s = strings.ToLower(s)
|
||||||
|
t = strings.ToLower(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
d := make([][]int, len(s)+1)
|
||||||
|
for i := range d {
|
||||||
|
d[i] = make([]int, len(t)+1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range d {
|
||||||
|
d[i][0] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := range d[0] {
|
||||||
|
d[0][j] = j
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := 1; j <= len(t); j++ {
|
||||||
|
for i := 1; i <= len(s); i++ {
|
||||||
|
if s[i-1] == t[j-1] {
|
||||||
|
d[i][j] = d[i-1][j-1]
|
||||||
|
} else {
|
||||||
|
min := d[i-1][j]
|
||||||
|
if d[i][j-1] < min {
|
||||||
|
min = d[i][j-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
if d[i-1][j-1] < min {
|
||||||
|
min = d[i-1][j-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
d[i][j] = min + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return d[len(s)][len(t)]
|
||||||
|
}
|
||||||
@ -89,7 +89,8 @@ func fatal(err error) {
|
|||||||
// Adapted from https://github.com/spf13/cobra/blob/main/doc/md_docs.go for Corso specific formatting
|
// Adapted from https://github.com/spf13/cobra/blob/main/doc/md_docs.go for Corso specific formatting
|
||||||
func genMarkdownCorso(cmd *cobra.Command, dir string) error {
|
func genMarkdownCorso(cmd *cobra.Command, dir string) error {
|
||||||
for _, c := range cmd.Commands() {
|
for _, c := range cmd.Commands() {
|
||||||
if !isAvailableCommand(c) || c.IsAdditionalHelpTopicCommand() {
|
if c.Use != "completion [bash|zsh|fish|powershell]" &&
|
||||||
|
(!isAvailableCommand(c) || c.IsAdditionalHelpTopicCommand()) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -101,6 +101,16 @@ func AddLoggingFlags(cmd *cobra.Command) {
|
|||||||
|
|
||||||
addFlags(fs, "corso-<timestamp>.log")
|
addFlags(fs, "corso-<timestamp>.log")
|
||||||
|
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(LogLevelFN, cobra.FixedCompletions(
|
||||||
|
[]string{string(LLDebug), string(LLInfo), string(LLWarn), string(LLError), string(LLDisabled)},
|
||||||
|
cobra.ShellCompDirectiveNoFileComp)))
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(LogFormatFN, cobra.FixedCompletions(
|
||||||
|
[]string{string(LFText), string(LFJSON)},
|
||||||
|
cobra.ShellCompDirectiveNoFileComp)))
|
||||||
|
cobra.CheckErr(cmd.RegisterFlagCompletionFunc(MaskSensitiveDataFN, cobra.FixedCompletions(
|
||||||
|
[]string{string(PIIPlainText), string(PIIMask), string(PIIHash)},
|
||||||
|
cobra.ShellCompDirectiveNoFileComp)))
|
||||||
|
|
||||||
//nolint:errcheck
|
//nolint:errcheck
|
||||||
fs.MarkHidden(ReadableLogsFN)
|
fs.MarkHidden(ReadableLogsFN)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,8 +55,8 @@ _validatemdgen: # in case we have a different architecture
|
|||||||
|
|
||||||
${MDGEN_BINARY}: $(shell find ${CORSO_LOCAL_PATH}/src -type f -name *.go) $(shell find ${CORSO_LOCAL_PATH}/src -type d )
|
${MDGEN_BINARY}: $(shell find ${CORSO_LOCAL_PATH}/src -type f -name *.go) $(shell find ${CORSO_LOCAL_PATH}/src -type d )
|
||||||
@echo 'Re-building Corso CLI docs auto-gen tooling...'
|
@echo 'Re-building Corso CLI docs auto-gen tooling...'
|
||||||
$(GOC) go mod download
|
$(GOC) go mod download
|
||||||
$(GOC) go build -o ${MDGEN_BINARY} ${MDGEN_SRC}
|
$(GOC) go build -o ${MDGEN_BINARY} ${MDGEN_SRC}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(WEBC) rm -rf docs/cli build node_modules
|
$(WEBC) rm -rf docs/cli build node_modules
|
||||||
|
|||||||
@ -35,3 +35,5 @@ Below is a list of known Corso issues and limitations:
|
|||||||
* Groups and Teams support is available in an early-access status, and may be subject to breaking changes.
|
* Groups and Teams support is available in an early-access status, and may be subject to breaking changes.
|
||||||
|
|
||||||
* Restoring the data into a different Group from the one it was backed up from isn't currently supported
|
* Restoring the data into a different Group from the one it was backed up from isn't currently supported
|
||||||
|
|
||||||
|
* CLI completions can't autocomplete multiple values for flags
|
||||||
|
|||||||
@ -54,7 +54,8 @@ const sidebars = {
|
|||||||
'cli/corso-repo-connect-filesystem',
|
'cli/corso-repo-connect-filesystem',
|
||||||
'cli/corso-repo-maintenance',
|
'cli/corso-repo-maintenance',
|
||||||
'cli/corso-repo-update-passphrase',
|
'cli/corso-repo-update-passphrase',
|
||||||
'cli/corso-env']
|
'cli/corso-env',
|
||||||
|
'cli/corso-completion']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
|
|||||||
@ -60,3 +60,4 @@ subtrees
|
|||||||
anonymized
|
anonymized
|
||||||
unreferenced
|
unreferenced
|
||||||
hostname
|
hostname
|
||||||
|
zsh
|
||||||
Loading…
x
Reference in New Issue
Block a user