mirror of
https://github.com/rclone/rclone.git
synced 2025-08-19 09:52:05 +02:00
Remove filesystem flags and put in config file with editor
This commit is contained in:
260
fs/config.go
Normal file
260
fs/config.go
Normal file
@@ -0,0 +1,260 @@
|
||||
// Read and write the config file
|
||||
package fs
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/goconfig"
|
||||
)
|
||||
|
||||
const (
|
||||
configFileName = ".rclone.conf"
|
||||
)
|
||||
|
||||
// Global
|
||||
var (
|
||||
// Config file
|
||||
ConfigFile *goconfig.ConfigFile
|
||||
// Config file path
|
||||
ConfigPath string
|
||||
// Global config
|
||||
Config = &ConfigInfo{}
|
||||
// Home directory
|
||||
HomeDir string
|
||||
// Flags
|
||||
verbose = flag.Bool("verbose", false, "Print lots more stuff")
|
||||
quiet = flag.Bool("quiet", false, "Print as little stuff as possible")
|
||||
modifyWindow = flag.Duration("modify-window", time.Nanosecond, "Max time diff to be considered the same")
|
||||
checkers = flag.Int("checkers", 8, "Number of checkers to run in parallel.")
|
||||
transfers = flag.Int("transfers", 4, "Number of file transfers to run in parallel.")
|
||||
)
|
||||
|
||||
// Filesystem config options
|
||||
type ConfigInfo struct {
|
||||
Verbose bool
|
||||
Quiet bool
|
||||
ModifyWindow time.Duration
|
||||
Checkers int
|
||||
Transfers int
|
||||
}
|
||||
|
||||
// Loads the config file
|
||||
func LoadConfig() {
|
||||
// Read some flags if set
|
||||
//
|
||||
// FIXME read these from the config file too
|
||||
Config.Verbose = *verbose
|
||||
Config.Quiet = *quiet
|
||||
Config.ModifyWindow = *modifyWindow
|
||||
Config.Checkers = *checkers
|
||||
Config.Transfers = *transfers
|
||||
|
||||
// Find users home directory
|
||||
usr, err := user.Current()
|
||||
if err != nil {
|
||||
log.Printf("Couldn't find home directory: %v", err)
|
||||
return
|
||||
}
|
||||
HomeDir = usr.HomeDir
|
||||
ConfigPath = path.Join(HomeDir, configFileName)
|
||||
|
||||
// Load configuration file.
|
||||
ConfigFile, err = goconfig.LoadConfigFile(ConfigPath)
|
||||
if err != nil {
|
||||
log.Printf("Failed to load config file %v - using defaults", ConfigPath)
|
||||
}
|
||||
}
|
||||
|
||||
// Save configuration file.
|
||||
func SaveConfig() {
|
||||
err := goconfig.SaveConfigFile(ConfigFile, ConfigPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to save config file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Show an overview of the config file
|
||||
func ShowConfig() {
|
||||
remotes := ConfigFile.GetSectionList()
|
||||
sort.Strings(remotes)
|
||||
fmt.Printf("%-20s %s\n", "Name", "Type")
|
||||
fmt.Printf("%-20s %s\n", "====", "====")
|
||||
for _, remote := range remotes {
|
||||
fmt.Printf("%-20s %s\n", remote, ConfigFile.MustValue(remote, "type"))
|
||||
}
|
||||
}
|
||||
|
||||
// ChooseRemote chooses a remote name
|
||||
func ChooseRemote() string {
|
||||
remotes := ConfigFile.GetSectionList()
|
||||
sort.Strings(remotes)
|
||||
return Choose("remote", remotes, nil, false)
|
||||
}
|
||||
|
||||
// Read some input
|
||||
func ReadLine() string {
|
||||
buf := bufio.NewReader(os.Stdin)
|
||||
line, err := buf.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read line: %v", err)
|
||||
}
|
||||
return strings.TrimSpace(line)
|
||||
}
|
||||
|
||||
// Command - choose one
|
||||
func Command(commands []string) int {
|
||||
opts := []string{}
|
||||
for _, text := range commands {
|
||||
fmt.Printf("%c) %s\n", text[0], text[1:])
|
||||
opts = append(opts, text[:1])
|
||||
}
|
||||
optString := strings.Join(opts, "")
|
||||
optHelp := strings.Join(opts, "/")
|
||||
for {
|
||||
fmt.Printf("%s> ", optHelp)
|
||||
result := strings.ToLower(ReadLine())
|
||||
if len(result) != 1 {
|
||||
continue
|
||||
}
|
||||
i := strings.IndexByte(optString, result[0])
|
||||
if i >= 0 {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Choose one of the defaults or type a new string if newOk is set
|
||||
func Choose(what string, defaults, help []string, newOk bool) string {
|
||||
fmt.Printf("Choose a number from below")
|
||||
if newOk {
|
||||
fmt.Printf(", or type in your own value")
|
||||
}
|
||||
fmt.Println()
|
||||
for i, text := range defaults {
|
||||
if help != nil {
|
||||
parts := strings.Split(help[i], "\n")
|
||||
for _, part := range parts {
|
||||
fmt.Printf(" * %s\n", part)
|
||||
}
|
||||
}
|
||||
fmt.Printf("%2d) %s\n", i+1, text)
|
||||
}
|
||||
for {
|
||||
fmt.Printf("%s> ", what)
|
||||
result := ReadLine()
|
||||
i, err := strconv.Atoi(result)
|
||||
if err != nil {
|
||||
if newOk {
|
||||
return result
|
||||
}
|
||||
continue
|
||||
}
|
||||
if i >= 1 && i <= len(defaults) {
|
||||
return defaults[i-1]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show the contents of the remote
|
||||
func ShowRemote(name string) {
|
||||
fmt.Printf("--------------------\n")
|
||||
fmt.Printf("[%s]\n", name)
|
||||
for _, key := range ConfigFile.GetKeyList(name) {
|
||||
fmt.Printf("%s = %s\n", key, ConfigFile.MustValue(name, key))
|
||||
}
|
||||
fmt.Printf("--------------------\n")
|
||||
}
|
||||
|
||||
// Print the contents of the remote and ask if it is OK
|
||||
func OkRemote(name string) bool {
|
||||
ShowRemote(name)
|
||||
switch i := Command([]string{"yYes this is OK", "eEdit this remote", "dDelete this remote"}); i {
|
||||
case 0:
|
||||
return true
|
||||
case 1:
|
||||
return false
|
||||
case 2:
|
||||
ConfigFile.DeleteSection(name)
|
||||
return true
|
||||
default:
|
||||
log.Printf("Bad choice %d", i)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Make a new remote
|
||||
func NewRemote(name string) {
|
||||
fmt.Printf("What type of source is it?\n")
|
||||
types := []string{}
|
||||
for _, item := range fsRegistry {
|
||||
types = append(types, item.Name)
|
||||
}
|
||||
newType := Choose("type", types, nil, false)
|
||||
ConfigFile.SetValue(name, "type", newType)
|
||||
fs, err := Find(newType)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to find fs: %v", err)
|
||||
}
|
||||
for _, option := range fs.Options {
|
||||
ConfigFile.SetValue(name, option.Name, option.Choose())
|
||||
}
|
||||
if OkRemote(name) {
|
||||
SaveConfig()
|
||||
return
|
||||
}
|
||||
EditRemote(name)
|
||||
}
|
||||
|
||||
// Edit a remote
|
||||
func EditRemote(name string) {
|
||||
ShowRemote(name)
|
||||
fmt.Printf("Edit remote\n")
|
||||
for {
|
||||
for _, key := range ConfigFile.GetKeyList(name) {
|
||||
value := ConfigFile.MustValue(name, key)
|
||||
fmt.Printf("Press enter to accept current value, or type in a new one\n")
|
||||
fmt.Printf("%s = %s>", key, value)
|
||||
newValue := ReadLine()
|
||||
if newValue != "" {
|
||||
ConfigFile.SetValue(name, key, newValue)
|
||||
}
|
||||
}
|
||||
if OkRemote(name) {
|
||||
break
|
||||
}
|
||||
}
|
||||
SaveConfig()
|
||||
}
|
||||
|
||||
// Edit the config file interactively
|
||||
func EditConfig() {
|
||||
for {
|
||||
fmt.Printf("Current remotes:\n\n")
|
||||
ShowConfig()
|
||||
fmt.Printf("\n")
|
||||
switch i := Command([]string{"eEdit existing remote", "nNew remote", "dDelete remote", "qQuit config"}); i {
|
||||
case 0:
|
||||
name := ChooseRemote()
|
||||
EditRemote(name)
|
||||
case 1:
|
||||
fmt.Printf("name> ")
|
||||
name := ReadLine()
|
||||
NewRemote(name)
|
||||
case 2:
|
||||
name := ChooseRemote()
|
||||
ConfigFile.DeleteSection(name)
|
||||
case 3:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user