config: make listing of remotes more consistent

This commit is contained in:
albertony 2023-11-04 02:48:42 +01:00 committed by Nick Craig-Wood
parent 8d2907d8f5
commit e4749cf0d0
4 changed files with 66 additions and 17 deletions

View File

@ -850,8 +850,8 @@ func (r *run) encryptRemoteIfNeeded(t *testing.T, remote string) string {
func (r *run) newCacheFs(t *testing.T, remote, id string, needRemote, purge bool, flags map[string]string) (fs.Fs, *cache.Persistent) { func (r *run) newCacheFs(t *testing.T, remote, id string, needRemote, purge bool, flags map[string]string) (fs.Fs, *cache.Persistent) {
fstest.Initialise() fstest.Initialise()
remoteExists := false remoteExists := false
for _, s := range config.FileSections() { for _, s := range config.GetRemotes() {
if s == remote { if s.Name == remote {
remoteExists = true remoteExists = true
} }
} }

View File

@ -415,6 +415,16 @@ func getWithDefault(name, key, defaultValue string) string {
return value return value
} }
// GetRemoteNames returns the names of remotes defined in environment and config file.
func GetRemoteNames() []string {
remotes := GetRemotes()
var remoteNames []string
for _, remote := range remotes {
remoteNames = append(remoteNames, remote.Name)
}
return remoteNames
}
// UpdateRemoteOpt configures the remote update // UpdateRemoteOpt configures the remote update
type UpdateRemoteOpt struct { type UpdateRemoteOpt struct {
// Treat all passwords as plain that need obscuring // Treat all passwords as plain that need obscuring
@ -637,19 +647,58 @@ func FileDeleteKey(section, key string) bool {
return LoadedData().DeleteKey(section, key) return LoadedData().DeleteKey(section, key)
} }
var matchEnv = regexp.MustCompile(`^RCLONE_CONFIG_(.+?)_TYPE=.*$`)
// FileSections returns the sections in the config file // FileSections returns the sections in the config file
// including any defined by environment variables.
func FileSections() []string { func FileSections() []string {
sections := LoadedData().GetSectionList() return LoadedData().GetSectionList()
}
// Remote defines a remote with a name, type and source
type Remote struct {
Name string `json:"name"`
Type string `json:"type"`
Source string `json:"source"`
}
var remoteEnvRe = regexp.MustCompile(`^RCLONE_CONFIG_(.+?)_TYPE=(.+)$`)
// GetRemotes returns the list of remotes defined in environment and config file.
//
// Emulates the preference documented and normally used by rclone via configmap,
// which means environment variables before config file.
func GetRemotes() []Remote {
var remotes []Remote
for _, item := range os.Environ() { for _, item := range os.Environ() {
matches := matchEnv.FindStringSubmatch(item) matches := remoteEnvRe.FindStringSubmatch(item)
if len(matches) == 2 { if len(matches) == 3 {
sections = append(sections, strings.ToLower(matches[1])) remotes = append(remotes, Remote{
Name: strings.ToLower(matches[1]),
Type: strings.ToLower(matches[2]),
Source: "environment",
})
} }
} }
return sections remoteExists := func(name string) bool {
for _, remote := range remotes {
if name == remote.Name {
return true
}
}
return false
}
sections := LoadedData().GetSectionList()
for _, section := range sections {
if !remoteExists(section) {
typeValue, found := LoadedData().GetValue(section, "type")
if found {
remotes = append(remotes, Remote{
Name: section,
Type: typeValue,
Source: "file",
})
}
}
}
return remotes
} }
// DumpRcRemote dumps the config for a single remote // DumpRcRemote dumps the config for a single remote

View File

@ -74,9 +74,9 @@ See the [listremotes](/commands/rclone_listremotes/) command for more informatio
// Return the a list of remotes in the config file // Return the a list of remotes in the config file
// including any defined by environment variables. // including any defined by environment variables.
func rcListRemotes(ctx context.Context, in rc.Params) (out rc.Params, err error) { func rcListRemotes(ctx context.Context, in rc.Params) (out rc.Params, err error) {
remotes := FileSections() remoteNames := GetRemoteNames()
out = rc.Params{ out = rc.Params{
"remotes": remotes, "remotes": remoteNames,
} }
return out, nil return out, nil
} }

View File

@ -308,14 +308,14 @@ func (s *Server) handleOptions(w http.ResponseWriter, r *http.Request, path stri
} }
func (s *Server) serveRoot(w http.ResponseWriter, r *http.Request) { func (s *Server) serveRoot(w http.ResponseWriter, r *http.Request) {
remotes := config.FileSections() remoteNames := config.GetRemoteNames()
sort.Strings(remotes) sort.Strings(remoteNames)
directory := serve.NewDirectory("", s.server.HTMLTemplate()) directory := serve.NewDirectory("", s.server.HTMLTemplate())
directory.Name = "List of all rclone remotes." directory.Name = "List of all rclone remotes."
q := url.Values{} q := url.Values{}
for _, remote := range remotes { for _, remoteName := range remoteNames {
q.Set("fs", remote) q.Set("fs", remoteName)
directory.AddHTMLEntry("["+remote+":]", true, -1, time.Time{}) directory.AddHTMLEntry("["+remoteName+":]", true, -1, time.Time{})
} }
sortParm := r.URL.Query().Get("sort") sortParm := r.URL.Query().Get("sort")
orderParm := r.URL.Query().Get("order") orderParm := r.URL.Query().Get("order")