mirror of
https://github.com/rclone/rclone.git
synced 2024-12-23 07:29:35 +01:00
config: when using auto confirm make user interaction configurable
* drive: don't run teamdrive config if auto confirm set * onedrive: don't run extra config if auto confirm set * make Confirm results customisable by config Fixes #1010
This commit is contained in:
parent
8e107b9657
commit
a30e80564d
@ -718,12 +718,16 @@ func parseExtensions(extensionsIn ...string) (extensions, mimeTypes []string, er
|
||||
|
||||
// Figure out if the user wants to use a team drive
|
||||
func configTeamDrive(opt *Options, m configmap.Mapper, name string) error {
|
||||
// Stop if we are running non-interactive config
|
||||
if fs.Config.AutoConfirm {
|
||||
return nil
|
||||
}
|
||||
if opt.TeamDriveID == "" {
|
||||
fmt.Printf("Configure this as a team drive?\n")
|
||||
} else {
|
||||
fmt.Printf("Change current team drive ID %q?\n", opt.TeamDriveID)
|
||||
}
|
||||
if !config.ConfirmWithDefault(false) {
|
||||
if !config.Confirm() {
|
||||
return nil
|
||||
}
|
||||
client, err := createOAuthClient(opt, name, m)
|
||||
|
@ -75,9 +75,8 @@ func init() {
|
||||
return
|
||||
}
|
||||
|
||||
// Are we running headless?
|
||||
if automatic, _ := m.Get(config.ConfigAutomatic); automatic != "" {
|
||||
// Yes, okay we are done
|
||||
// Stop if we are running non-interactive config
|
||||
if fs.Config.AutoConfirm {
|
||||
return
|
||||
}
|
||||
|
||||
@ -199,7 +198,7 @@ func init() {
|
||||
|
||||
fmt.Printf("Found drive '%s' of type '%s', URL: %s\nIs that okay?\n", rootItem.Name, rootItem.ParentReference.DriveType, rootItem.WebURL)
|
||||
// This does not work, YET :)
|
||||
if !config.Confirm() {
|
||||
if !config.ConfirmWithConfig(m, "config_drive_ok", true) {
|
||||
log.Fatalf("Cancelled by user")
|
||||
}
|
||||
|
||||
|
@ -93,6 +93,15 @@ For example to make a swift remote of name myremote using auto config
|
||||
you would do:
|
||||
|
||||
rclone config create myremote swift env_auth true
|
||||
|
||||
Note that if the config process would normally ask a question the
|
||||
default is taken. Each time that happens rclone will print a message
|
||||
saying how to affect the value taken.
|
||||
|
||||
So for example if you wanted to configure a Google Drive remote but
|
||||
using remote authorization you would do this:
|
||||
|
||||
rclone config create mydrive drive config_is_local false
|
||||
`,
|
||||
RunE: func(command *cobra.Command, args []string) error {
|
||||
cmd.CheckArgs(2, 256, command, args)
|
||||
@ -119,6 +128,11 @@ in pairs of <key> <value>.
|
||||
For example to update the env_auth field of a remote of name myremote you would do:
|
||||
|
||||
rclone config update myremote swift env_auth true
|
||||
|
||||
If the remote uses oauth the token will be updated, if you don't
|
||||
require this add an extra parameter thus:
|
||||
|
||||
rclone config update myremote swift env_auth true config_refresh_token false
|
||||
`,
|
||||
RunE: func(command *cobra.Command, args []string) error {
|
||||
cmd.CheckArgs(3, 256, command, args)
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/Unknwon/goconfig"
|
||||
"github.com/ncw/rclone/fs"
|
||||
"github.com/ncw/rclone/fs/accounting"
|
||||
"github.com/ncw/rclone/fs/config/configmap"
|
||||
"github.com/ncw/rclone/fs/config/configstruct"
|
||||
"github.com/ncw/rclone/fs/config/obscure"
|
||||
"github.com/ncw/rclone/fs/driveletter"
|
||||
@ -57,8 +58,8 @@ const (
|
||||
// ConfigTokenURL is the config key used to store the token server endpoint
|
||||
ConfigTokenURL = "token_url"
|
||||
|
||||
// ConfigAutomatic indicates that we want non-interactive configuration
|
||||
ConfigAutomatic = "config_automatic"
|
||||
// ConfigAuthorize indicates that we just want "rclone authorize"
|
||||
ConfigAuthorize = "config_authorize"
|
||||
)
|
||||
|
||||
// Global
|
||||
@ -639,21 +640,38 @@ func Command(commands []string) byte {
|
||||
}
|
||||
}
|
||||
|
||||
// ConfirmWithDefault asks the user for Yes or No and returns true or false.
|
||||
//
|
||||
// If AutoConfirm is set, it will return the Default value passed in
|
||||
func ConfirmWithDefault(Default bool) bool {
|
||||
if fs.Config.AutoConfirm {
|
||||
return Default
|
||||
}
|
||||
return Command([]string{"yYes", "nNo"}) == 'y'
|
||||
}
|
||||
|
||||
// Confirm asks the user for Yes or No and returns true or false
|
||||
//
|
||||
// If AutoConfirm is set, it will return true
|
||||
func Confirm() bool {
|
||||
return ConfirmWithDefault(true)
|
||||
return Command([]string{"yYes", "nNo"}) == 'y'
|
||||
}
|
||||
|
||||
// ConfirmWithConfig asks the user for Yes or No and returns true or
|
||||
// false.
|
||||
//
|
||||
// If AutoConfirm is set, it will look up the value in m and return
|
||||
// that, but if it isn't set then it will return the Default value
|
||||
// passed in
|
||||
func ConfirmWithConfig(m configmap.Getter, configName string, Default bool) bool {
|
||||
if fs.Config.AutoConfirm {
|
||||
configString, ok := m.Get(configName)
|
||||
if ok {
|
||||
configValue, err := strconv.ParseBool(configString)
|
||||
if err != nil {
|
||||
fs.Errorf(nil, "Failed to parse config parameter %s=%q as boolean - using default %v: %v", configName, configString, Default, err)
|
||||
} else {
|
||||
Default = configValue
|
||||
}
|
||||
}
|
||||
answer := "No"
|
||||
if Default {
|
||||
answer = "Yes"
|
||||
}
|
||||
fmt.Printf("Auto confirm is set: answering %s, override by setting config parameter %s=%v\n", answer, configName, !Default)
|
||||
return Default
|
||||
}
|
||||
return Confirm()
|
||||
}
|
||||
|
||||
// Choose one of the defaults or type a new string if newOk is set
|
||||
@ -943,8 +961,6 @@ func CreateRemote(name string, provider string, keyValues rc.Params) error {
|
||||
getConfigData().DeleteSection(name)
|
||||
// Set the type
|
||||
getConfigData().SetValue(name, "type", provider)
|
||||
// Show this is automatically configured
|
||||
getConfigData().SetValue(name, ConfigAutomatic, "yes")
|
||||
// Set the remaining values
|
||||
return UpdateRemote(name, keyValues)
|
||||
}
|
||||
@ -1227,6 +1243,7 @@ func SetPassword() {
|
||||
// rclone authorize "fs name"
|
||||
// rclone authorize "fs name" "client id" "client secret"
|
||||
func Authorize(args []string) {
|
||||
defer suppressConfirm()()
|
||||
switch len(args) {
|
||||
case 1, 3:
|
||||
default:
|
||||
@ -1243,8 +1260,8 @@ func Authorize(args []string) {
|
||||
// Make sure we delete it
|
||||
defer DeleteRemote(name)
|
||||
|
||||
// Indicate that we want fully automatic configuration.
|
||||
getConfigData().SetValue(name, ConfigAutomatic, "yes")
|
||||
// Indicate that we are running rclone authorize
|
||||
getConfigData().SetValue(name, ConfigAuthorize, "true")
|
||||
if len(args) == 3 {
|
||||
getConfigData().SetValue(name, ConfigClientID, args[1])
|
||||
getConfigData().SetValue(name, ConfigClientSecret, args[2])
|
||||
|
@ -358,18 +358,26 @@ func ConfigErrorCheck(id, name string, m configmap.Mapper, errorHandler func(*ht
|
||||
|
||||
func doConfig(id, name string, m configmap.Mapper, errorHandler func(*http.Request) AuthError, oauthConfig *oauth2.Config, offline bool, opts []oauth2.AuthCodeOption) error {
|
||||
oauthConfig, changed := overrideCredentials(name, m, oauthConfig)
|
||||
auto, ok := m.Get(config.ConfigAutomatic)
|
||||
automatic := ok && auto != ""
|
||||
authorizeOnlyValue, ok := m.Get(config.ConfigAuthorize)
|
||||
authorizeOnly := ok && authorizeOnlyValue != "" // set if being run by "rclone authorize"
|
||||
|
||||
// See if already have a token
|
||||
tokenString, ok := m.Get("token")
|
||||
if ok && tokenString != "" {
|
||||
fmt.Printf("Already have a token - refresh?\n")
|
||||
if !config.Confirm() {
|
||||
if !config.ConfirmWithConfig(m, "config_refresh_token", true) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Ask the user whether they are using a local machine
|
||||
isLocal := func() bool {
|
||||
fmt.Printf("Use auto config?\n")
|
||||
fmt.Printf(" * Say Y if not sure\n")
|
||||
fmt.Printf(" * Say N if you are working on a remote or headless machine\n")
|
||||
return config.ConfirmWithConfig(m, "config_is_local", true)
|
||||
}
|
||||
|
||||
// Detect whether we should use internal web server
|
||||
useWebServer := false
|
||||
switch oauthConfig.RedirectURL {
|
||||
@ -378,14 +386,10 @@ func doConfig(id, name string, m configmap.Mapper, errorHandler func(*http.Reque
|
||||
fmt.Printf("Make sure your Redirect URL is set to %q in your custom config.\n", oauthConfig.RedirectURL)
|
||||
}
|
||||
useWebServer = true
|
||||
if automatic {
|
||||
if authorizeOnly {
|
||||
break
|
||||
}
|
||||
fmt.Printf("Use auto config?\n")
|
||||
fmt.Printf(" * Say Y if not sure\n")
|
||||
fmt.Printf(" * Say N if you are working on a remote or headless machine\n")
|
||||
auto := config.Confirm()
|
||||
if !auto {
|
||||
if !isLocal() {
|
||||
fmt.Printf("For this to work, you will need rclone available on a machine that has a web browser available.\n")
|
||||
fmt.Printf("Execute the following on your machine:\n")
|
||||
if changed {
|
||||
@ -407,12 +411,9 @@ func doConfig(id, name string, m configmap.Mapper, errorHandler func(*http.Reque
|
||||
return PutToken(name, m, token, true)
|
||||
}
|
||||
case TitleBarRedirectURL:
|
||||
useWebServer = automatic
|
||||
if !automatic {
|
||||
fmt.Printf("Use auto config?\n")
|
||||
fmt.Printf(" * Say Y if not sure\n")
|
||||
fmt.Printf(" * Say N if you are working on a remote or headless machine or Y didn't work\n")
|
||||
useWebServer = config.Confirm()
|
||||
useWebServer = authorizeOnly
|
||||
if !authorizeOnly {
|
||||
useWebServer = isLocal()
|
||||
}
|
||||
if useWebServer {
|
||||
// copy the config and set to use the internal webserver
|
||||
@ -479,12 +480,12 @@ func doConfig(id, name string, m configmap.Mapper, errorHandler func(*http.Reque
|
||||
}
|
||||
|
||||
// Print code if we do automatic retrieval
|
||||
if automatic {
|
||||
if authorizeOnly {
|
||||
result, err := json.Marshal(token)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to marshal token")
|
||||
}
|
||||
fmt.Printf("Paste the following into your remote machine --->\n%s\n<---End paste", result)
|
||||
fmt.Printf("Paste the following into your remote machine --->\n%s\n<---End paste\n", result)
|
||||
}
|
||||
return PutToken(name, m, token, true)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user