fs: allow boolean features to be enabled with --disable !Feature

This commit is contained in:
Nick Craig-Wood 2023-03-14 15:59:44 +00:00
parent d808c3848a
commit bad8a01850
2 changed files with 32 additions and 3 deletions

View File

@ -1002,10 +1002,24 @@ To see a list of which features can be disabled use:
--disable help --disable help
The features a remote has can be seen in JSON format with:
rclone backend features remote:
See the overview [features](/overview/#features) and See the overview [features](/overview/#features) and
[optional features](/overview/#optional-features) to get an idea of [optional features](/overview/#optional-features) to get an idea of
which feature does what. which feature does what.
Note that some features can be set to `true` if they are `true`/`false`
feature flag features by prefixing them with `!`. For example the
`CaseInsensitive` feature can be forced to `false` with `--disable CaseInsensitive`
and forced to `true` with `--disable '!CaseInsensitive'`. In general
it isn't a good idea doing this but it may be useful in extremis.
(Note that `!` is a shell command which you will
need to escape with single quotes or a backslash on unix like
platforms.)
This flag can be useful for debugging and in exceptional circumstances This flag can be useful for debugging and in exceptional circumstances
(e.g. Google Drive limiting the total volume of Server Side Copies to (e.g. Google Drive limiting the total volume of Server Side Copies to
100 GiB/day). 100 GiB/day).

View File

@ -172,6 +172,12 @@ type Features struct {
// Disable nil's out the named feature. If it isn't found then it // Disable nil's out the named feature. If it isn't found then it
// will log a message. // will log a message.
func (ft *Features) Disable(name string) *Features { func (ft *Features) Disable(name string) *Features {
// Prefix boolean values with ! to set the feature
invert := false
if strings.HasPrefix(name, "!") {
name = name[1:]
invert = true
}
v := reflect.ValueOf(ft).Elem() v := reflect.ValueOf(ft).Elem()
vType := v.Type() vType := v.Type()
for i := 0; i < v.NumField(); i++ { for i := 0; i < v.NumField(); i++ {
@ -181,9 +187,18 @@ func (ft *Features) Disable(name string) *Features {
if !field.CanSet() { if !field.CanSet() {
Errorf(nil, "Can't set Feature %q", name) Errorf(nil, "Can't set Feature %q", name)
} else { } else {
zero := reflect.Zero(field.Type()) if invert {
field.Set(zero) if field.Type().Kind() == reflect.Bool {
Debugf(nil, "Reset feature %q", name) field.Set(reflect.ValueOf(true))
Debugf(nil, "Set feature %q", name)
} else {
Errorf(nil, "Can't set Feature %q to true", name)
}
} else {
zero := reflect.Zero(field.Type())
field.Set(zero)
Debugf(nil, "Reset feature %q", name)
}
} }
} }
} }