ronantakizawa/codereview-bench huggingface dataset:
Repository: rclone/rclone
File: backend/box/box.go (Go)

Code before:
		return nil, fs.ErrorCantCopy
	}
	err := srcObj.readMetaData(ctx)
	if err != nil {
		return nil, err
	}

	srcPath := srcObj.fs.rootSlash() + srcObj.remote
	dstPath := f.rootSlash() + remote
	if strings.EqualFold(srcPath, dstPath) {
		return nil, fmt.Errorf("can't copy %q -> %q as are same name when lowercase", srcPath, dstPath)
	}

	// Create temporary object
	dstObj, leaf, directoryID, err := f.createObject(ctx, remote, srcObj.modTime, srcObj.size)
	if err != nil {
		return nil, err
	}

	// check if dest already exists
	item, err := f.preUploadCheck(ctx, leaf, directoryID, src.Size())
	if err != nil {
		return nil, err
	}
	if item != nil { // dest already exists, fall back to manual copy
		return nil, fs.ErrorCantCopy
	}

	// Copy the object
	opts := rest.Opts{
		Method:     "POST",
		Path:       "/files/" + srcObj.id + "/copy",
		Parameters: fieldsValue(),
	}
	copyFile := api.CopyFile{
		Name: f.opt.Enc.FromStandardName(leaf),
		Parent: api.Parent{
			ID: directoryID,
		},
	}
	var resp *http.Response
	var info *api.Item
	err = f.pacer.Call(func() (bool, error) {
		resp, err = f.srv.CallJSON(ctx, &opts, &copyFile, &info)
		return shouldRetry(ctx, resp, err)
	})
	if err != nil {
		return nil, err
	}
	err = dstObj.setMetaData(info)
	if err != nil {

Review comment (suggestion):
Could we just delete the existing file here?

Or if paranoid
- rename existing file with random suffix
- do copy
- if successful delete existing file
- if unsucessful rename exsting file back

The success/unsuccess could be done in a `defer` function which looks at the result of `err`.

Code after:
		fs.Debugf(src, "Can't copy - not same remote type")
		return nil, fs.ErrorCantCopy
	}
	err := srcObj.readMetaData(ctx)
	if err != nil {
		return nil, err
	}

	srcPath := srcObj.fs.rootSlash() + srcObj.remote
	dstPath := f.rootSlash() + remote
	if strings.EqualFold(srcPath, dstPath) {
		return nil, fmt.Errorf("can't copy %q -> %q as are same name when lowercase", srcPath, dstPath)
	}

	// Create temporary object
	dstObj, leaf, directoryID, err := f.createObject(ctx, remote, srcObj.modTime, srcObj.size)
	if err != nil {
		return nil, err
	}

	// check if dest already exists
	item, err := f.preUploadCheck(ctx, leaf, directoryID, src.Size())
	if err != nil {
		return nil, err
	}
	if item != nil { // dest already exists, need to copy to temp name and then move
		tempSuffix := "-rclone-copy-" + random.String(8)
		fs.Debugf(remote, "dst already exists, copying to temp name %v", remote+tempSuffix)
		tempObj, err := f.Copy(ctx, src, remote+tempSuffix)
		if err != nil {
			return nil, err
		}
		fs.Debugf(remote+tempSuffix, "moving to real name %v", remote)
		err = f.deleteObject(ctx, item.ID)
		if err != nil {
			return nil, err
		}
		return f.Move(ctx, tempObj, remote)
	}

	// Copy the object
	opts := rest.Opts{
		Method:     "POST",
		Path:       "/files/" + srcObj.id + "/copy",
		Parameters: fieldsValue(),
	}
	copyFile := api.CopyFile{
		Name: f.opt.Enc.FromStandardName(leaf),
		Parent: api.Parent{
			ID: directoryID,
		},
Repository: rclone/rclone
File: backend/drive/drive.go (Go)

Code before:
				lines = append(lines, "")
				lines = append(lines, fmt.Sprintf("[%s]", name))
				lines = append(lines, "type = alias")
				lines = append(lines, fmt.Sprintf("remote = %s,team_drive=%s,root_folder_id=:", f.name, drive.Id))
				upstreams = append(upstreams, fmt.Sprintf(`"%s=%s:"`, name, name))
			}
			lines = append(lines, "")
			lines = append(lines, "[AllDrives]")
			lines = append(lines, "type = combine")
			lines = append(lines, fmt.Sprintf("upstreams = %s", strings.Join(upstreams, " ")))
			return lines, nil
		}
		return drives, nil
	case "untrash":
		dir := ""
		if len(arg) > 0 {
			dir = arg[0]
		}
		return f.unTrashDir(ctx, dir, true)
	case "copyid", "moveid":
		if len(arg)%2 == 0 {
			return nil, errors.New("need an odd number of arguments")
		}
		for len(arg) > 0 {
			id, dest := arg[0], arg[1]
			arg = arg[3:]
			err = f.copyOrMoveID(ctx, name, id, dest)
			if err != nil {
				return nil, fmt.Errorf("failed moving %q to %q: %w", id, dest, err)
			}
		}
		return nil, nil
	case "exportformats":
		return f.exportFormats(ctx), nil
	case "importformats":
		return f.importFormats(ctx), nil
	case "query":
		if len(arg) == 1 {
			query := arg[0]
			var results, err = f.query(ctx, query)
			if err != nil {
				return nil, fmt.Errorf("failed to execute query: %q, error: %w", query, err)
			}
			return results, nil
		} else {
			return nil, errors.New("need a query argument")
		}
	case "rescue":
		dirID := ""
		_, delete := opt["delete"]
		if len(arg) == 0 {

Review comment (suggestion):
This should say `arg = arg[2:]` to pop the used arguments off for the `for` loop

Code after:
					}
					name += fmt.Sprintf("-%d", i)
				}
				names[name] = struct{}{}
				lines = append(lines, "")
				lines = append(lines, fmt.Sprintf("[%s]", name))
				lines = append(lines, "type = alias")
				lines = append(lines, fmt.Sprintf("remote = %s,team_drive=%s,root_folder_id=:", f.name, drive.Id))
				upstreams = append(upstreams, fmt.Sprintf(`"%s=%s:"`, name, name))
			}
			lines = append(lines, "")
			lines = append(lines, "[AllDrives]")
			lines = append(lines, "type = combine")
			lines = append(lines, fmt.Sprintf("upstreams = %s", strings.Join(upstreams, " ")))
			return lines, nil
		}
		return drives, nil
	case "untrash":
		dir := ""
		if len(arg) > 0 {
			dir = arg[0]
		}
		return f.unTrashDir(ctx, dir, true)
	case "copyid", "moveid":
		if len(arg)%2 != 0 {
			return nil, errors.New("need an even number of arguments")
		}
		for len(arg) > 0 {
			id, dest := arg[0], arg[1]
			arg = arg[2:]
			err = f.copyOrMoveID(ctx, name, id, dest)
			if err != nil {
				return nil, fmt.Errorf("failed %s %q to %q: %w", name, id, dest, err)
			}
		}
		return nil, nil
	case "exportformats":
		return f.exportFormats(ctx), nil
	case "importformats":
		return f.importFormats(ctx), nil
	case "query":
		if len(arg) == 1 {
			query := arg[0]
			var results, err = f.query(ctx, query)
			if err != nil {
				return nil, fmt.Errorf("failed to execute query: %q, error: %w", query, err)
			}
			return results, nil
		} else {
			return nil, errors.New("need a query argument")
		}
Repository: rclone/rclone
File: backend/smb/connpool.go (Go)

Code before:
//
// Call removeSession() when done
func (f *Fs) addSession() {
	f.sessions.Add(1)
}

// Show the SMB session is no longer in use
func (f *Fs) removeSession() {
	f.sessions.Add(-1)
}

// getSessions shows whether there are any sessions in use
func (f *Fs) getSessions() int32 {
	return f.sessions.Load()
}

// Open a new connection to the SMB server.
//
// The context is only used for establishing the connection, not after.
func (f *Fs) newConnection(ctx context.Context, share string) (c *conn, err error) {
	c, err = f.dial(ctx, "tcp", f.opt.Host+":"+f.opt.Port)
	if err != nil {
		return nil, fmt.Errorf("couldn't connect SMB: %w", err)
	}
	if share != "" {
		// mount the specified share as well if user requested
		err = c.mountShare(share)
		if err != nil {
			_ = c.smbSession.Logoff()
			return nil, fmt.Errorf("couldn't initialize SMB: %w", err)
		}
	}
	return c, nil
}

// Ensure the specified share is mounted or the session is unmounted
func (c *conn) mountShare(share string) (err error) {
	if c.shareName == share {
		return nil
	}
	if c.smbShare != nil {
		err = c.smbShare.Umount()
		c.smbShare = nil
	}
	if err != nil {
		return
	}
	if share != "" {
		c.smbShare, err = c.smbSession.Mount(share)
		if err != nil {
			return

Review comment (suggestion):
This was not necessary and prevented the context from being used for connection _establishment_. The `go-smb2` library already uses a background context for all operations after the connection is established, unless `WithContext` is used.

Code after:

// Show that we are using a SMB session
//
// Call removeSession() when done
func (f *Fs) addSession() {
	f.sessions.Add(1)
}

// Show the SMB session is no longer in use
func (f *Fs) removeSession() {
	f.sessions.Add(-1)
}

// getSessions shows whether there are any sessions in use
func (f *Fs) getSessions() int32 {
	return f.sessions.Load()
}

// Open a new connection to the SMB server.
//
// The context is only used for establishing the connection, not after.
func (f *Fs) newConnection(ctx context.Context, share string) (c *conn, err error) {
	c, err = f.dial(ctx, "tcp", f.opt.Host+":"+f.opt.Port)
	if err != nil {
		return nil, fmt.Errorf("couldn't connect SMB: %w", err)
	}
	if share != "" {
		// mount the specified share as well if user requested
		err = c.mountShare(share)
		if err != nil {
			_ = c.smbSession.Logoff()
			return nil, fmt.Errorf("couldn't initialize SMB: %w", err)
		}
	}
	return c, nil
}

// Ensure the specified share is mounted or the session is unmounted
func (c *conn) mountShare(share string) (err error) {
	if c.shareName == share {
		return nil
	}
	if c.smbShare != nil {
		err = c.smbShare.Umount()
		c.smbShare = nil
	}
	if err != nil {
		return
	}
	if share != "" {
		c.smbShare, err = c.smbSession.Mount(share)
Repository: rclone/rclone
File: backend/smb/kerberos_test.go (Go)

Code before:
package smb

import (
	"os"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestResolveCcachePath(t *testing.T) {
	tmpDir := t.TempDir()

	// Setup: files for FILE and DIR modes
	fileCcache := filepath.Join(tmpDir, "file_ccache")
	_ = os.WriteFile(fileCcache, []byte{}, 0600)

	dirCcache := filepath.Join(tmpDir, "dir_ccache")
	_ = os.Mkdir(dirCcache, 0755)
	_ = os.WriteFile(filepath.Join(dirCcache, "primary"), []byte("ticket"), 0600)
	dirCcacheTicket := filepath.Join(dirCcache, "ticket")
	_ = os.WriteFile(dirCcacheTicket, []byte{}, 0600)

	tests := []struct {
		name          string
		ccachePath    string
		envKRB5CCNAME string
		expected      string
		expectError   bool
	}{
		{
			name:          "FILE: prefix from env",
			ccachePath:    "",
			envKRB5CCNAME: "FILE:" + fileCcache,
			expected:      fileCcache,
		},
		{
			name:          "DIR: prefix from env",
			ccachePath:    "",
			envKRB5CCNAME: "DIR:" + dirCcache,
			expected:      dirCcacheTicket,

Review comment (suggestion):
Instead of ignoring the error, use `require.NoError(t, os.WriteFile....` for all of these

Code after:
package smb

import (
	"os"
	"path/filepath"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestResolveCcachePath(t *testing.T) {
	tmpDir := t.TempDir()

	// Setup: files for FILE and DIR modes
	fileCcache := filepath.Join(tmpDir, "file_ccache")
	err := os.WriteFile(fileCcache, []byte{}, 0600)
	assert.NoError(t, err)

	dirCcache := filepath.Join(tmpDir, "dir_ccache")
	err = os.Mkdir(dirCcache, 0755)
	assert.NoError(t, err)
	err = os.WriteFile(filepath.Join(dirCcache, "primary"), []byte("ticket"), 0600)
	assert.NoError(t, err)
	dirCcacheTicket := filepath.Join(dirCcache, "ticket")
	err = os.WriteFile(dirCcacheTicket, []byte{}, 0600)
	assert.NoError(t, err)

	tests := []struct {
		name          string
		ccachePath    string
		envKRB5CCNAME string
		expected      string
		expectError   bool
	}{
		{
			name:          "FILE: prefix from env",
			ccachePath:    "",
			envKRB5CCNAME: "FILE:" + fileCcache,
			expected:      fileCcache,
		},
		{
Repository: rclone/rclone
File: cmd/copyurl/copyurl.go (Go)

Code before:
		return nil
	},
}

var copyURL = operations.CopyURL // for testing

// runURLS processes a .csv file of urls and filenames
func runURLS(args []string) error {
	if stdout {
		return errors.New("can't use --stdout with --urls")
	}
	if printFilename {
		return errors.New("can't use --print-filename with --urls")
	}
	dstFs := cmd.NewFsDir(args[1:])

	f, err := os.Open(args[0])
	if err != nil {
		return fmt.Errorf("failed to open .csv file: %w", err)
	}
	reader := csv.NewReader(f)
	reader.FieldsPerRecord = -1
	urlList, err := reader.ReadAll()
	if err != nil {
		return fmt.Errorf("failed reading .csv file: %w", err)
	}

	ec := errcount.New()
	g, gCtx := errgroup.WithContext(context.Background())
	ci := fs.GetConfig(gCtx)
	g.SetLimit(ci.Transfers)

	for _, urlEntry := range urlList {
		if len(urlEntry) == 0 {
			continue
		}
		g.Go(func() error {
			url := urlEntry[0]
			var filename string
			if len(urlEntry) > 1 {
				filename = urlEntry[1]
			}
			_, err := copyURL(gCtx, dstFs, filename, url, filename == "", headerFilename, noClobber)
			if err != nil {
				fs.Errorf(filename, "failed to copy url: %v", err)
				ec.Add(err)
			}
			return nil
		})
	}
	_ = g.Wait()

Review comment (suggestion):
This file needs to be closed.

The rclone way of doing this is to use `fs.CheckClose` which closes the file on function exit and updates the returned error if necessary.

    defer fs.CheckClose(f, &err)

You'll need to name the return variable, so

    func runURLS(args []string) error

becomes

    func runURLS(args []string) (err error)

Code after:
		cmd.Run(true, true, command, func() error {
			if !urls {
				return run(args)
			}
			return runURLS(args)
		})
		return nil
	},
}

var copyURL = operations.CopyURL // for testing

// runURLS processes a .csv file of urls and filenames
func runURLS(args []string) (err error) {
	if stdout {
		return errors.New("can't use --stdout with --urls")
	}
	if printFilename {
		return errors.New("can't use --print-filename with --urls")
	}
	dstFs := cmd.NewFsDir(args[1:])

	f, err := os.Open(args[0])
	if err != nil {
		return fmt.Errorf("failed to open .csv file: %w", err)
	}
	defer fs.CheckClose(f, &err)
	reader := csv.NewReader(f)
	reader.FieldsPerRecord = -1
	urlList, err := reader.ReadAll()
	if err != nil {
		return fmt.Errorf("failed reading .csv file: %w", err)
	}

	ec := errcount.New()
	g, gCtx := errgroup.WithContext(context.Background())
	ci := fs.GetConfig(gCtx)
	g.SetLimit(ci.Transfers)

	for _, urlEntry := range urlList {
		if len(urlEntry) == 0 {
			continue
		}
		g.Go(func() error {
			url := urlEntry[0]
			var filename string
			if len(urlEntry) > 1 {
				filename = urlEntry[1]
			}
			_, err := copyURL(gCtx, dstFs, filename, url, filename == "", headerFilename, noClobber)
			if err != nil {
Repository: rclone/rclone
File: cmd/copyurl/copyurl.go (Go)

Code before:
	}
	reader := csv.NewReader(f)
	reader.FieldsPerRecord = -1
	urlList, err := reader.ReadAll()
	if err != nil {
		return fmt.Errorf("failed reading .csv file: %w", err)
	}

	ec := errcount.New()
	g, gCtx := errgroup.WithContext(context.Background())
	ci := fs.GetConfig(gCtx)
	g.SetLimit(ci.Transfers)

	for _, urlEntry := range urlList {
		if len(urlEntry) == 0 {
			continue
		}
		g.Go(func() error {
			url := urlEntry[0]
			var filename string
			if len(urlEntry) > 1 {
				filename = urlEntry[1]
			}
			_, err := copyURL(gCtx, dstFs, filename, url, filename == "", headerFilename, noClobber)
			if err != nil {
				fs.Errorf(filename, "failed to copy url: %v", err)
				ec.Add(err)
			}
			return nil
		})
	}
	_ = g.Wait()
	return ec.Err("not all urls copied successfully")
}

// run runs the command for a single URL
func run(args []string) error {
	var err error
	var dstFileName string
	var fsdst fs.Fs
	if !stdout {
		if len(args) < 2 {
			return errors.New("need 2 arguments if not using --stdout")
		}
		if args[1] == "-" {
			stdout = true
		} else if autoFilename {
			fsdst = cmd.NewFsDir(args[1:])
		} else {
			fsdst, dstFileName = cmd.NewFsDstFile(args[1:])
		}

Review comment (bug):
Perhaps put the URL in the ERROR too?

    fs.Errorf(filename, "failed to copy URL %q: %v", url, err)



Code after:
	}
	dstFs := cmd.NewFsDir(args[1:])

	f, err := os.Open(args[0])
	if err != nil {
		return fmt.Errorf("failed to open .csv file: %w", err)
	}
	defer fs.CheckClose(f, &err)
	reader := csv.NewReader(f)
	reader.FieldsPerRecord = -1
	urlList, err := reader.ReadAll()
	if err != nil {
		return fmt.Errorf("failed reading .csv file: %w", err)
	}

	ec := errcount.New()
	g, gCtx := errgroup.WithContext(context.Background())
	ci := fs.GetConfig(gCtx)
	g.SetLimit(ci.Transfers)

	for _, urlEntry := range urlList {
		if len(urlEntry) == 0 {
			continue
		}
		g.Go(func() error {
			url := urlEntry[0]
			var filename string
			if len(urlEntry) > 1 {
				filename = urlEntry[1]
			}
			_, err := copyURL(gCtx, dstFs, filename, url, filename == "", headerFilename, noClobber)
			if err != nil {
				fs.Errorf(filename, "failed to copy URL %q: %v", url, err)
				ec.Add(err)
			}
			return nil
		})
	}
	ec.Add(g.Wait())
	return ec.Err("not all URLs copied successfully")
}

// run runs the command for a single URL
func run(args []string) error {
	var err error
	var dstFileName string
	var fsdst fs.Fs
	if !stdout {
		if len(args) < 2 {
			return errors.New("need 2 arguments if not using --stdout")
		}
Repository: rclone/rclone
File: cmd/copyurl/copyurl.go (Go)

Code before:
	}

	ec := errcount.New()
	g, gCtx := errgroup.WithContext(context.Background())
	ci := fs.GetConfig(gCtx)
	g.SetLimit(ci.Transfers)

	for _, urlEntry := range urlList {
		if len(urlEntry) == 0 {
			continue
		}
		g.Go(func() error {
			url := urlEntry[0]
			var filename string
			if len(urlEntry) > 1 {
				filename = urlEntry[1]
			}
			_, err := copyURL(gCtx, dstFs, filename, url, filename == "", headerFilename, noClobber)
			if err != nil {
				fs.Errorf(filename, "failed to copy url: %v", err)
				ec.Add(err)
			}
			return nil
		})
	}
	_ = g.Wait()
	return ec.Err("not all urls copied successfully")
}

// run runs the command for a single URL
func run(args []string) error {
	var err error
	var dstFileName string
	var fsdst fs.Fs
	if !stdout {
		if len(args) < 2 {
			return errors.New("need 2 arguments if not using --stdout")
		}
		if args[1] == "-" {
			stdout = true
		} else if autoFilename {
			fsdst = cmd.NewFsDir(args[1:])
		} else {
			fsdst, dstFileName = cmd.NewFsDstFile(args[1:])
		}
	}

	var dst fs.Object
	if stdout {
		err = operations.CopyURLToWriter(context.Background(), args[0], os.Stdout)
	} else {

Review comment (suggestion):
If you ever did return an error from `g.Go` then this could be

ec.Add(g.Wait())

You could do this for completeness if you wanted

Code after:
	}
	defer fs.CheckClose(f, &err)
	reader := csv.NewReader(f)
	reader.FieldsPerRecord = -1
	urlList, err := reader.ReadAll()
	if err != nil {
		return fmt.Errorf("failed reading .csv file: %w", err)
	}

	ec := errcount.New()
	g, gCtx := errgroup.WithContext(context.Background())
	ci := fs.GetConfig(gCtx)
	g.SetLimit(ci.Transfers)

	for _, urlEntry := range urlList {
		if len(urlEntry) == 0 {
			continue
		}
		g.Go(func() error {
			url := urlEntry[0]
			var filename string
			if len(urlEntry) > 1 {
				filename = urlEntry[1]
			}
			_, err := copyURL(gCtx, dstFs, filename, url, filename == "", headerFilename, noClobber)
			if err != nil {
				fs.Errorf(filename, "failed to copy URL %q: %v", url, err)
				ec.Add(err)
			}
			return nil
		})
	}
	ec.Add(g.Wait())
	return ec.Err("not all URLs copied successfully")
}

// run runs the command for a single URL
func run(args []string) error {
	var err error
	var dstFileName string
	var fsdst fs.Fs
	if !stdout {
		if len(args) < 2 {
			return errors.New("need 2 arguments if not using --stdout")
		}
		if args[1] == "-" {
			stdout = true
		} else if autoFilename {
			fsdst = cmd.NewFsDir(args[1:])
		} else {
			fsdst, dstFileName = cmd.NewFsDstFile(args[1:])
Repository: rclone/rclone
File: backend/smb/smb_test.go (Go)

Code before:
		expected bool
	}{
		// Empty path should be considered a directory
		{"", true},

		// Paths with trailing slash should be directories
		{"/", true},
		{"share/", true},
		{"share/dir/", true},
		{"share/dir/subdir/", true},

		// Paths without trailing slash should not be directories
		{"share", false},
		{"share/dir", false},
		{"share/dir/file", false},
		{"share/dir/subdir/file", false},

		// Edge cases
		{"share//", true},
		{"share///", true},
		{"share/dir//", true},
	}

	for _, tt := range tests {
		t.Run(tt.path, func(t *testing.T) {
			result := smb.IsPathDir(tt.path)
			if result != tt.expected {
				t.Errorf("isPathDir(%q) = %v, want %v", tt.path, result, tt.expected)
			}
		})
	}
}


Review comment (suggestion):
I think you should be able to use `isPathDir` directly here since they are in the same folder if you rename the package to just `smb` rather than `smb_test`.

Code after:
// Test smb filesystem interface
package smb_test

import (
	"path/filepath"
	"testing"

	"github.com/rclone/rclone/backend/smb"
	"github.com/rclone/rclone/fstest"
	"github.com/rclone/rclone/fstest/fstests"
)

// TestIntegration runs integration tests against the remote
func TestIntegration(t *testing.T) {
	fstests.Run(t, &fstests.Opt{
		RemoteName: "TestSMB:rclone",
		NilObject:  (*smb.Object)(nil),
	})
}

func TestIntegration2(t *testing.T) {
	if *fstest.RemoteName != "" {
		t.Skip("skipping as -remote is set")
	}
	krb5Dir := t.TempDir()
	t.Setenv("KRB5_CONFIG", filepath.Join(krb5Dir, "krb5.conf"))
	t.Setenv("KRB5CCNAME", filepath.Join(krb5Dir, "ccache"))
	fstests.Run(t, &fstests.Opt{
		RemoteName: "TestSMBKerberos:rclone",
		NilObject:  (*smb.Object)(nil),
	})
}

func TestIntegration3(t *testing.T) {
	if *fstest.RemoteName != "" {
		t.Skip("skipping as -remote is set")
	}

	krb5Dir := t.TempDir()
	t.Setenv("KRB5_CONFIG", filepath.Join(krb5Dir, "krb5.conf"))
	ccache := filepath.Join(krb5Dir, "ccache")
	t.Setenv("RCLONE_TEST_CUSTOM_CCACHE_LOCATION", ccache)

	name := "TestSMBKerberosCcache"

	fstests.Run(t, &fstests.Opt{
		RemoteName: name + ":rclone",
		NilObject:  (*smb.Object)(nil),
		ExtraConfig: []fstests.ExtraConfigItem{
			{Name: name, Key: "kerberos_ccache", Value: ccache},
		},
	})
}