ronantakizawa/codereview-bench huggingface dataset:
Repository: rclone/rclone
File: fs/rc/rcserver/rcserver_test.go (Go)

Code before:

	tests := []testRun{{
		Name:     "modtime",
		Method:   "GET",
		URL:      remoteURL + "modtime/",
		Status:   http.StatusOK,
		Expected: "* dir/ - 2023-04-12T21:15:17Z\n* modtime.txt - 2021-01-18T05:02:28Z\n",
	}}
	testServer(t, tests, &opt)

	opt.ServeNoModTime = true
	tests = []testRun{{
		Name:     "no modtime",
		Method:   "GET",
		URL:      remoteURL + "modtime/",
		Status:   http.StatusOK,
		Expected: "* dir/ - 0001-01-01T00:00:00Z\n* modtime.txt - 0001-01-01T00:00:00Z\n",
	}}
	testServer(t, tests, &opt)
}

func TestContentTypeJSON(t *testing.T) {
	tests := []testRun{
		{
			Name:        "Check Content-Type for JSON response",
			URL:         "rc/noop", // Assuming rc/noop returns JSON
			Method:      "POST",
			Body:        `{}`, // Empty JSON body
			ContentType: "application/json",
			Status:      http.StatusOK,
			Expected:    "{}\n", // Expected JSON response
			Headers: map[string]string{
				"Content-Type": "application/json", // Adjusted to match actual behavior
			},
		},
	}
	opt := newTestOpt()
	testServer(t, tests, &opt)
}


Review comment (suggestion):
You should be able to test the error case with `rc/error` - I'd suggest another test for that.

Code after:
	}

	opt := newTestOpt()
	opt.Serve = true
	opt.Template.Path = "testdata/golden/testmodtime.html"

	tests := []testRun{{
		Name:     "modtime",
		Method:   "GET",
		URL:      remoteURL + "modtime/",
		Status:   http.StatusOK,
		Expected: "* dir/ - 2023-04-12T21:15:17Z\n* modtime.txt - 2021-01-18T05:02:28Z\n",
	}}
	testServer(t, tests, &opt)

	opt.ServeNoModTime = true
	tests = []testRun{{
		Name:     "no modtime",
		Method:   "GET",
		URL:      remoteURL + "modtime/",
		Status:   http.StatusOK,
		Expected: "* dir/ - 0001-01-01T00:00:00Z\n* modtime.txt - 0001-01-01T00:00:00Z\n",
	}}
	testServer(t, tests, &opt)
}

func TestContentTypeJSON(t *testing.T) {
	tests := []testRun{
		{
			Name:        "Check Content-Type for JSON response",
			URL:         "rc/noop",
			Method:      "POST",
			Body:        `{}`,
			ContentType: "application/json",
			Status:      http.StatusOK,
			Expected:    "{}\n",
			Headers: map[string]string{
				"Content-Type": "application/json",
			},
		},
		{
			Name:        "Check Content-Type for JSON error response",
			URL:         "rc/error",
			Method:      "POST",
			Body:        `{}`,
			ContentType: "application/json",
			Status:      http.StatusInternalServerError,
			Expected: `{
				"error": "arbitrary error on input map[]",
				"input": {},
				"path": "rc/error",
Repository: rclone/rclone
File: fs/rc/rcserver/rcserver_test.go (Go)

Code before:
		Status:   http.StatusOK,
		Expected: "* dir/ - 0001-01-01T00:00:00Z\n* modtime.txt - 0001-01-01T00:00:00Z\n",
	}}
	testServer(t, tests, &opt)
}

func TestContentTypeJSON(t *testing.T) {
	tests := []testRun{
		{
			Name:        "Check Content-Type for JSON response",
			URL:         "rc/noop",
			Method:      "POST",
			Body:        `{}`,
			ContentType: "application/json",
			Status:      http.StatusOK,
			Expected:    "{}\n",
			Headers: map[string]string{
				"Content-Type": "application/json",
			},
		},
	}
	opt := newTestOpt()
	testServer(t, tests, &opt)
}

func TestErrorContentTypeJSON(t *testing.T) {
	tests := []struct {
		Name           string
		URL            string
		Method         string
		Body           string
		ExpectedStatus int
		ExpectedJSON   string
	}{
		{
			Name:           "Check Content-Type for JSON error response",
			URL:            "rc/error",
			Method:         "POST",
			Body:           `{}`,
			ExpectedStatus: http.StatusInternalServerError,
			ExpectedJSON: `{
				"error": "arbitrary error on input map[]",
				"input": {},
				"path": "rc/error",
				"status": 500
			}`,
		},
	}

	for _, tc := range tests {
		t.Run(tc.Name, func(t *testing.T) {

Review comment (suggestion):
Couldn't this test just be another test case in ` TestContentTypeJSON`? I'm probably missing something as to why not...

If not I suggest you add a new feature to the testServer rather than duplicating it below. By that I mean add a new flag to `testRun`, set it in the test case, and use it to control the changes you need in `testServer`. That will make for much neater and more maintainable code.

Code after:
	tests = []testRun{{
		Name:     "no modtime",
		Method:   "GET",
		URL:      remoteURL + "modtime/",
		Status:   http.StatusOK,
		Expected: "* dir/ - 0001-01-01T00:00:00Z\n* modtime.txt - 0001-01-01T00:00:00Z\n",
	}}
	testServer(t, tests, &opt)
}

func TestContentTypeJSON(t *testing.T) {
	tests := []testRun{
		{
			Name:        "Check Content-Type for JSON response",
			URL:         "rc/noop",
			Method:      "POST",
			Body:        `{}`,
			ContentType: "application/json",
			Status:      http.StatusOK,
			Expected:    "{}\n",
			Headers: map[string]string{
				"Content-Type": "application/json",
			},
		},
		{
			Name:        "Check Content-Type for JSON error response",
			URL:         "rc/error",
			Method:      "POST",
			Body:        `{}`,
			ContentType: "application/json",
			Status:      http.StatusInternalServerError,
			Expected: `{
				"error": "arbitrary error on input map[]",
				"input": {},
				"path": "rc/error",
				"status": 500
			}
			`,
			Headers: map[string]string{
				"Content-Type": "application/json",
			},
		},
	}
	opt := newTestOpt()
	testServer(t, tests, &opt)
}

func normalizeJSON(t *testing.T, jsonStr string) string {
	var jsonObj map[string]interface{}
	err := json.Unmarshal([]byte(jsonStr), &jsonObj)
	require.NoError(t, err, "JSON unmarshalling failed")
Repository: rclone/rclone
File: backend/b2/upload.go (Go)

Code before:
		parts = int(size / int64(chunkSize))
		if size%int64(chunkSize) != 0 {
			parts++
		}
	}
	opts := rest.Opts{
		Method: "POST",
		Path:   "/b2_start_large_file",
	}
	bucket, bucketPath := o.split()
	bucketID, err := f.getBucketID(ctx, bucket)
	if err != nil {
		return nil, err
	}
	var request = api.StartLargeFileRequest{
		BucketID: bucketID,
		Name:     f.opt.Enc.FromStandardPath(bucketPath),
	}
	if newInfo == nil {
		modTime := src.ModTime(ctx)
		request.ContentType = fs.MimeType(ctx, src)
		request.Info = map[string]string{
			timeKey: timeString(modTime),
		}
		// Custom upload headers - remove header prefix since they are sent in the body
		for _, option := range options {
			k, v := option.Header()
			k = strings.ToLower(k)
			if strings.HasPrefix(k, headerPrefix) {
				request.Info[k[len(headerPrefix):]] = v
			}
		}
		// Set the SHA1 if known
		if !o.fs.opt.DisableCheckSum || doCopy {
			if calculatedSha1, err := src.Hash(ctx, hash.SHA1); err == nil && calculatedSha1 != "" {
				request.Info[sha1Key] = calculatedSha1
			}
		}
	} else {
		request.ContentType = newInfo.ContentType
		request.Info = newInfo.Info
	}
	var response api.StartLargeFileResponse
	err = f.pacer.Call(func() (bool, error) {
		resp, err := f.srv.CallJSON(ctx, &opts, &request, &response)
		return f.shouldRetry(ctx, resp, err)
	})
	if err != nil {
		return nil, err
	}
	up = &largeUpload{

Review comment (suggestion):
Can't put a comment in the right place, but this above

```go
opts: rest.Opts{
}
```

Should have

```
Options:    options,
```

This is how the non metadata options get set in the request.


Code after:
		parts = int(size / int64(chunkSize))
		if size%int64(chunkSize) != 0 {
			parts++
		}
	}
	bucket, bucketPath := o.split()
	bucketID, err := f.getBucketID(ctx, bucket)
	if err != nil {
		return nil, err
	}
	var request = api.StartLargeFileRequest{
		BucketID: bucketID,
		Name:     f.opt.Enc.FromStandardPath(bucketPath),
	}
	optionsToSend := make([]fs.OpenOption, 0, len(options))
	if newInfo == nil {
		modTime, err := o.getModTime(ctx, src, options)
		if err != nil {
			return nil, err
		}

		request.ContentType = fs.MimeType(ctx, src)
		request.Info = map[string]string{
			timeKey: timeString(modTime),
		}
		// Custom upload headers - remove header prefix since they are sent in the body
		for _, option := range options {
			k, v := option.Header()
			k = strings.ToLower(k)
			if strings.HasPrefix(k, headerPrefix) {
				request.Info[k[len(headerPrefix):]] = v
			} else {
				optionsToSend = append(optionsToSend, option)
			}
		}
		// Set the SHA1 if known
		if !o.fs.opt.DisableCheckSum || doCopy {
			if calculatedSha1, err := src.Hash(ctx, hash.SHA1); err == nil && calculatedSha1 != "" {
				request.Info[sha1Key] = calculatedSha1
			}
		}
	} else {
		request.ContentType = newInfo.ContentType
		request.Info = newInfo.Info
	}
	opts := rest.Opts{
		Method:  "POST",
		Path:    "/b2_start_large_file",
		Options: optionsToSend,
	}
	var response api.StartLargeFileResponse
Repository: rclone/rclone
File: backend/local/local.go (Go)

Code before:
	if err != nil {
		return err
	}
	return err
}

// SetMetadata sets metadata for an Object
//
// It should return fs.ErrorNotImplemented if it can't set metadata
func (o *Object) SetMetadata(ctx context.Context, metadata fs.Metadata) error {
	err := o.writeMetadata(metadata)
	if err != nil {
		return fmt.Errorf("SetMetadata failed on Object: %w", err)
	}
	// Re-read info now we have finished setting stuff
	return o.lstat()
}

func cleanRootPath(s string, noUNC bool, enc encoder.MultiEncoder) string {
	var vol string
	if runtime.GOOS == "windows" {
		vol = filepath.VolumeName(s)
		if vol == `\\?` && len(s) >= 6 {
			// `\\?\C:`
			vol = s[:6]
		}
		s = s[len(vol):]
	}
	// Don't use FromStandardPath. Make sure Dot (`.`, `..`) as name will not be reencoded
	if enc != encoder.Standard {
		s = filepath.ToSlash(s)
		parts := strings.Split(s, "/")
		encoded := make([]string, len(parts))
		changed := false
		for i, p := range parts {
			if (p == ".") || (p == "..") {
				encoded[i] = p
				continue
			}
			part := enc.FromStandardName(p)
			changed = changed || part != p
			encoded[i] = part
		}
		if changed {
			s = strings.Join(encoded, "/")
		}
		s = filepath.FromSlash(s)
	}
	if runtime.GOOS == "windows" {
		s = vol + s
	}

Review comment (suggestion):
Perhaps just mask out the `Dot` encoding from enc? That would make the code a lot simpler

something like this?

```
enc &= ^encoding.EncodeDot
```

If you can minimise this change I'm much more likely to  merge it!

Code after:

// SetMetadata sets metadata for an Object
//
// It should return fs.ErrorNotImplemented if it can't set metadata
func (o *Object) SetMetadata(ctx context.Context, metadata fs.Metadata) error {
	err := o.writeMetadata(metadata)
	if err != nil {
		return fmt.Errorf("SetMetadata failed on Object: %w", err)
	}
	// Re-read info now we have finished setting stuff
	return o.lstat()
}

func cleanRootPath(s string, noUNC bool, enc encoder.MultiEncoder) string {
	var vol string
	if runtime.GOOS == "windows" {
		vol = filepath.VolumeName(s)
		if vol == `\\?` && len(s) >= 6 {
			// `\\?\C:`
			vol = s[:6]
		}
		s = s[len(vol):]
	}
	// Don't use FromStandardPath. Make sure Dot (`.`, `..`) as name will not be reencoded
	// Take care of the case Standard: ./．/‛． (the first dot means current directory)
	if enc != encoder.Standard {
		s = filepath.ToSlash(s)
		parts := strings.Split(s, "/")
		encoded := make([]string, len(parts))
		changed := false
		for i, p := range parts {
			if (p == ".") || (p == "..") {
				encoded[i] = p
				continue
			}
			part := enc.FromStandardName(p)
			changed = changed || part != p
			encoded[i] = part
		}
		if changed {
			s = strings.Join(encoded, "/")
		}
		s = filepath.FromSlash(s)
	}
	if runtime.GOOS == "windows" {
		s = vol + s
	}
	s2, err := filepath.Abs(s)
	if err == nil {
		s = s2
	}
Repository: rclone/rclone
File: cmd/rcd/rcd.go (Go)

Code before:
		"versionIntroduced": "v1.45",
		"groups":            "RC",
	},
	Run: func(command *cobra.Command, args []string) {
		cmd.CheckArgs(0, 1, command, args)
		if rc.Opt.Enabled {
			log.Fatalf("Don't supply --rc flag when using rcd")
		}

		// Start the rc
		rc.Opt.Enabled = true
		if len(args) > 0 {
			rc.Opt.Files = args[0]
		}

		ctx := context.Background()

		s, err := rcserver.Start(ctx, &rc.Opt)
		if err != nil {
			log.Fatalf("Failed to start remote control: %v", err)
		}
		if s == nil {
			log.Fatal("rc server not configured")
		}

		go func() {
			_, err := rcserver.MetricsStart(ctx, &rc.Opt)
			if err != nil {
				log.Fatalf("Failed to start metrics server: %v", err)
			}
		}()

		// Notify stopping on exit
		defer systemd.Notify()()

		s.Wait()
	},
}


Review comment (suggestion):
This means that the metrics only run for `rclone rcd`. Currently the metrics run whenever you have the `--rc` flag.

Code after:
		"versionIntroduced": "v1.45",
		"groups":            "RC",
	},
	Run: func(command *cobra.Command, args []string) {
		cmd.CheckArgs(0, 1, command, args)
		if rc.Opt.Enabled {
			log.Fatalf("Don't supply --rc flag when using rcd")
		}

		// Start the rc
		rc.Opt.Enabled = true
		if len(args) > 0 {
			rc.Opt.Files = args[0]
		}

		s, err := rcserver.Start(context.Background(), &rc.Opt)
		if err != nil {
			log.Fatalf("Failed to start remote control: %v", err)
		}
		if s == nil {
			log.Fatal("rc server not configured")
		}

		// Notify stopping on exit
		defer systemd.Notify()()

		s.Wait()
	},
}
Repository: rclone/rclone
File: cmd/cmd.go (Go)

Code before:
		// Hide the console window
		terminal.HideConsole()
	} else {
		// Enable color support on stdout if possible.
		// This enables virtual terminal processing on Windows 10,
		// adding native support for ANSI/VT100 escape sequences.
		terminal.EnableColorsStdout()
	}

	// Write the args for debug purposes
	fs.Debugf("rclone", "Version %q starting with parameters %q", fs.Version, os.Args)

	// Inform user about systemd log support now that we have a logger
	if fslog.Opt.LogSystemdSupport {
		fs.Debugf("rclone", "systemd logging support activated")
	}

	// Start the remote control server if configured
	_, err = rcserver.Start(ctx, &rc.Opt)
	if err != nil {
		log.Fatalf("Failed to start remote control: %v", err)
	}

	// Start the metrics server if configured and has a different port from rcserver
	if !rcserver.SlicesEqual(rc.Opt.MetricsHTTP.ListenAddr, rc.Opt.HTTP.ListenAddr) {
		_, err = rcserver.MetricsStart(ctx, &rc.Opt)
		if err != nil {
			log.Fatalf("Failed to start metrics server: %v", err)
		}
	}

	// Setup CPU profiling if desired
	if *cpuProfile != "" {
		fs.Infof(nil, "Creating CPU profile %q\n", *cpuProfile)
		f, err := os.Create(*cpuProfile)
		if err != nil {
			err = fs.CountError(err)
			log.Fatal(err)
		}
		err = pprof.StartCPUProfile(f)
		if err != nil {
			err = fs.CountError(err)
			log.Fatal(err)
		}
		atexit.Register(func() {
			pprof.StopCPUProfile()
			err := f.Close()
			if err != nil {
				err = fs.CountError(err)
				log.Fatal(err)
			}

Review comment (suggestion):
I would leave `MetricsStart` to figure out if it needs to start or not and the condition for it starting or not should be if `--metrics-addr` is supplied or not, I think.


Code after:
		// Hide the console window
		terminal.HideConsole()
	} else {
		// Enable color support on stdout if possible.
		// This enables virtual terminal processing on Windows 10,
		// adding native support for ANSI/VT100 escape sequences.
		terminal.EnableColorsStdout()
	}

	// Write the args for debug purposes
	fs.Debugf("rclone", "Version %q starting with parameters %q", fs.Version, os.Args)

	// Inform user about systemd log support now that we have a logger
	if fslog.Opt.LogSystemdSupport {
		fs.Debugf("rclone", "systemd logging support activated")
	}

	// Start the remote control server if configured
	_, err = rcserver.Start(ctx, &rc.Opt)
	if err != nil {
		log.Fatalf("Failed to start remote control: %v", err)
	}

	// Start the metrics server if configured
	_, err = rcserver.MetricsStart(ctx, &rc.Opt)
	if err != nil {
		log.Fatalf("Failed to start metrics server: %v", err)

	}

	// Setup CPU profiling if desired
	if *cpuProfile != "" {
		fs.Infof(nil, "Creating CPU profile %q\n", *cpuProfile)
		f, err := os.Create(*cpuProfile)
		if err != nil {
			err = fs.CountError(err)
			log.Fatal(err)
		}
		err = pprof.StartCPUProfile(f)
		if err != nil {
			err = fs.CountError(err)
			log.Fatal(err)
		}
		atexit.Register(func() {
			pprof.StopCPUProfile()
			err := f.Close()
			if err != nil {
				err = fs.CountError(err)
				log.Fatal(err)
			}
		})
Repository: rclone/rclone
File: cmd/serve/docker/options.go (Go)

Code before:
	case "vfs-used-is-size":
		vfsOpt.UsedIsSize, err = opt.GetBool(key)

	// unprefixed vfs options
	case "no-modtime":
		vfsOpt.NoModTime, err = opt.GetBool(key)
	case "no-checksum":
		vfsOpt.NoChecksum, err = opt.GetBool(key)
	case "dir-cache-time":
		vfsOpt.DirCacheTime, err = opt.GetFsDuration(key)
	case "poll-interval":
		vfsOpt.PollInterval, err = opt.GetFsDuration(key)
	case "read-only":
		vfsOpt.ReadOnly, err = opt.GetBool(key)
	case "dir-perms":
		err = getFVarP(&vfsOpt.DirPerms, opt, key)
	case "file-perms":
		err = getFVarP(&vfsOpt.FilePerms, opt, key)

	// unprefixed unix-only vfs options
	case "umask":
		err = getFVarP(&vfsOpt.Umask, opt, key)
	case "uid":
		intVal, err = opt.GetInt64(key)
		if err == nil {
			if intVal > 0 && intVal <= math.MaxInt32 {
				vfsOpt.UID = uint32(intVal)
			} else {
				err = fmt.Errorf("key %q (%v) overflows uint32", key, intVal)
			}
		}
	case "gid":
		intVal, err = opt.GetInt64(key)
		if err == nil {
			if intVal > 0 && intVal <= math.MaxInt32 {
				vfsOpt.UID = uint32(intVal)
			} else {
				err = fmt.Errorf("key %q (%v) overflows uint32", key, intVal)
			}
		}

	// non-vfs options
	default:
		ok = false
	}
	return
}

func getFVarP(pvalue pflag.Value, opt rc.Params, key string) error {
	str, err := opt.GetString(key)
	if err != nil {

Review comment (suggestion):
I think the comparison should be
```
if intVal >= 0 && intVal <= math.MaxUint32
```

Code after:
	case "vfs-used-is-size":
		vfsOpt.UsedIsSize, err = opt.GetBool(key)

	// unprefixed vfs options
	case "no-modtime":
		vfsOpt.NoModTime, err = opt.GetBool(key)
	case "no-checksum":
		vfsOpt.NoChecksum, err = opt.GetBool(key)
	case "dir-cache-time":
		vfsOpt.DirCacheTime, err = opt.GetFsDuration(key)
	case "poll-interval":
		vfsOpt.PollInterval, err = opt.GetFsDuration(key)
	case "read-only":
		vfsOpt.ReadOnly, err = opt.GetBool(key)
	case "dir-perms":
		err = getFVarP(&vfsOpt.DirPerms, opt, key)
	case "file-perms":
		err = getFVarP(&vfsOpt.FilePerms, opt, key)

	// unprefixed unix-only vfs options
	case "umask":
		err = getFVarP(&vfsOpt.Umask, opt, key)
	case "uid":
		intVal, err = opt.GetInt64(key)
		if err == nil {
			if intVal >= 0 && intVal <= math.MaxUint32 {
				vfsOpt.UID = uint32(intVal)
			} else {
				err = fmt.Errorf("key %q (%v) overflows uint32", key, intVal)
			}
		}
	case "gid":
		intVal, err = opt.GetInt64(key)
		if err == nil {
			if intVal >= 0 && intVal <= math.MaxUint32 {
				vfsOpt.UID = uint32(intVal)
			} else {
				err = fmt.Errorf("key %q (%v) overflows uint32", key, intVal)
			}
		}

	// non-vfs options
	default:
		ok = false
	}
	return
}

func getFVarP(pvalue pflag.Value, opt rc.Params, key string) error {
	str, err := opt.GetString(key)
	if err != nil {
Repository: rclone/rclone
File: lib/encoder/encoder.go (Go)

Code before:
		return name
	}
	var out []string
	// Otherwise decompose bit by bit
	for bit := MultiEncoder(1); bit != 0; bit *= 2 {
		if (mask & bit) != 0 {
			if name, ok := encodingToName[bit]; ok {
				out = append(out, name)
			} else {
				out = append(out, fmt.Sprintf("0x%X", uint(bit)))
			}
		}
	}
	return strings.Join(out, ",")
}

// Set converts a string into a MultiEncoder
func (mask *MultiEncoder) Set(in string) error {
	var out MultiEncoder
	parts := strings.Split(in, ",")
	for _, part := range parts {
		part = strings.TrimSpace(part)
		if bits, ok := nameToEncoding[part]; ok {
			out |= bits
		} else {
			i, err := strconv.ParseUint(part, 0, 32)
			if err != nil {
				return fmt.Errorf("bad encoding %q: possible values are: %s", part, validStrings())
			}
			out |= MultiEncoder(i)
		}
	}
	*mask = out
	return nil
}

// Type returns a textual type of the MultiEncoder to satisfy the pflag.Value interface
func (mask MultiEncoder) Type() string {
	return "Encoding"
}

// Scan implements the fmt.Scanner interface
func (mask *MultiEncoder) Scan(s fmt.ScanState, ch rune) error {
	token, err := s.Token(true, nil)
	if err != nil {
		return err
	}
	return mask.Set(string(token))
}

// Encode takes a raw name and substitutes any reserved characters and

Review comment (bug):
This is another 32 vs 64 bit problem with uint

Not sure what the correct solution here is as there is no `strconf.Atou`

Rlone will go wrong on 32 bit platforms if there are more than 32 options though so we could make MultiEncoder a `uint32` or `uint64` though I expect that might be quite a distruptive change!

Code after:
		return name
	}
	var out []string
	// Otherwise decompose bit by bit
	for bit := MultiEncoder(1); bit != 0; bit *= 2 {
		if (mask & bit) != 0 {
			if name, ok := encodingToName[bit]; ok {
				out = append(out, name)
			} else {
				out = append(out, fmt.Sprintf("0x%X", uint(bit)))
			}
		}
	}
	return strings.Join(out, ",")
}

// Set converts a string into a MultiEncoder
func (mask *MultiEncoder) Set(in string) error {
	var out MultiEncoder
	parts := strings.Split(in, ",")
	for _, part := range parts {
		part = strings.TrimSpace(part)
		if bits, ok := nameToEncoding[part]; ok {
			out |= bits
		} else {
			i, err := strconv.ParseUint(part, 0, 0)
			if err != nil {
				return fmt.Errorf("bad encoding %q: possible values are: %s", part, validStrings())
			}
			out |= MultiEncoder(i)
		}
	}
	*mask = out
	return nil
}

// Type returns a textual type of the MultiEncoder to satisfy the pflag.Value interface
func (mask MultiEncoder) Type() string {
	return "Encoding"
}

// Scan implements the fmt.Scanner interface
func (mask *MultiEncoder) Scan(s fmt.ScanState, ch rune) error {
	token, err := s.Token(true, nil)
	if err != nil {
		return err
	}
	return mask.Set(string(token))
}

// Encode takes a raw name and substitutes any reserved characters and
Repository: rclone/rclone
File: backend/local/metadata.go (Go)

Code before:
				outErr = fmt.Errorf("failed to set birth (creation) time: %w", err)
			}
		}
	}
	uid, hasUID := o.parseMetadataInt(m, "uid", 10)
	gid, hasGID := o.parseMetadataInt(m, "gid", 10)
	if hasUID {
		// FIXME should read UID and GID of current user and only attempt to set it if different
		if !hasGID {
			gid = uid
		}
		if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
			fs.Debugf(o, "Ignoring request to set ownership %o.%o on this OS", gid, uid)
		} else {
			err = os.Chown(o.path, uid, gid)
			if err != nil {
				outErr = fmt.Errorf("failed to change ownership: %w", err)
			}
		}
	}
	mode, hasMode := o.parseMetadataInt(m, "mode", 8)
	if hasMode {
		if mode >= 0 && uint(mode) <= math.MaxUint32 {
			err = os.Chmod(o.path, os.FileMode(mode))
			if err != nil {
				outErr = fmt.Errorf("failed to change permissions: %w", err)
			}
		}
	}
	// FIXME not parsing rdev yet
	return outErr
}


Review comment (suggestion):
It's complaining about the o.path not the FileMode here. That data is supplied by the user, but the Paths in the show Paths are nuts!

So I think this new alert is a false positive 

Code after:
				outErr = fmt.Errorf("failed to set birth (creation) time: %w", err)
			}
		}
	}
	uid, hasUID := o.parseMetadataInt(m, "uid", 10)
	gid, hasGID := o.parseMetadataInt(m, "gid", 10)
	if hasUID {
		// FIXME should read UID and GID of current user and only attempt to set it if different
		if !hasGID {
			gid = uid
		}
		if runtime.GOOS == "windows" || runtime.GOOS == "plan9" {
			fs.Debugf(o, "Ignoring request to set ownership %o.%o on this OS", gid, uid)
		} else {
			err = os.Chown(o.path, uid, gid)
			if err != nil {
				outErr = fmt.Errorf("failed to change ownership: %w", err)
			}
		}
	}
	mode, hasMode := o.parseMetadataInt(m, "mode", 8)
	if hasMode {
		if mode >= 0 {
			umode := uint(mode)
			if umode <= math.MaxUint32 {
				err = os.Chmod(o.path, os.FileMode(umode))
				if err != nil {
					outErr = fmt.Errorf("failed to change permissions: %w", err)
				}
			}
		}
	}
	// FIXME not parsing rdev yet
	return outErr
}