Repository: rclone/rclone
Pull request #7125 (2023-07-09 23:13:01)

Add more guidance for the user to check the config.
#### What is the purpose of this change?

Make it more clear that the user has to change the configuration. The current message sounds more like a code bug that it calculated the wrong url.


#### Was the change discussed in an issue or in the forum before?

https://github.com/rclone/rclone/issues/7103#issuecomment-1627773153
<!--
Link issues and relevant forum posts here.
-->

#### Checklist

- [x] I have read the [contribution guidelines](https://github.com/rclone/rclone/blob/master/CONTRIBUTING.md#submitting-a-new-feature-or-bug-fix).
- [ ] I have added tests for all changes in this PR if appropriate.
- [ ] I have added documentation for the changes if appropriate.
- [ ] All commit messages are in [house style](https://github.com/rclone/rclone/blob/master/CONTRIBUTING.md#commit-messages).
- [x] I'm done, this Pull Request is ready for review :-)


ncw: I think this is a duplicate of #7126 so I'll close this one
ncw: Sorry, see what you did there, one patch for master and one for stable branch!

Will merge this one and close the other as I'll do the backport seperately - thanks :-)

Patch:
diff --git a/backend/webdav/chunking.go b/backend/webdav/chunking.go
index 4660e9493..471678acc 100644
--- a/backend/webdav/chunking.go
+++ b/backend/webdav/chunking.go
@@ -53,7 +53,7 @@ func (o *Object) getChunksUploadDir() (string, error) {
 func (f *Fs) getChunksUploadURL() (string, error) {
 	submatch := nextCloudURLRegex.FindStringSubmatch(f.endpointURL)
 	if submatch == nil {
-		return "", errors.New("the remote url looks incorrect. Note that nextcloud chunked uploads require you to use the /dav/files/USER endpoint instead of /webdav")
+		return "", errors.New("the remote url looks incorrect. Note that nextcloud chunked uploads require you to use the /dav/files/USER endpoint instead of /webdav. Please check 'rclone config show remotename' to verify that the url field ends in /dav/files/USERNAME")
 	}
 
 	baseURL, user := submatch[1], submatch[2]
diff --git a/fs/operations/operations.go b/fs/operations/operations.go
index 3c89bbc97..2c8463b3c 100644
--- a/fs/operations/operations.go
+++ b/fs/operations/operations.go
@@ -358,7 +358,7 @@ func Copy(ctx context.Context, f fs.Fs, dst fs.Object, remote string, src fs.Obj
 		inplace       = true
 		remotePartial = remote
 	)
-	if !ci.Inplace && f.Features().Move != nil && f.Features().PartialUploads {
+	if !ci.Inplace && f.Features().Move != nil && f.Features().PartialUploads && !strings.HasSuffix(remote, ".rclonelink") {
 		// Avoid making the leaf name longer if it's already lengthy to avoid
 		// trouble with file name length limits.
 		suffix := "." + random.String(8) + ".partial"


Test patch:
diff --git a/backend/local/local_internal_test.go b/backend/local/local_internal_test.go
index 2e2cfbca6..06e47bed2 100644
--- a/backend/local/local_internal_test.go
+++ b/backend/local/local_internal_test.go
@@ -19,6 +19,7 @@ import (
 	"github.com/rclone/rclone/fs/filter"
 	"github.com/rclone/rclone/fs/hash"
 	"github.com/rclone/rclone/fs/object"
+	"github.com/rclone/rclone/fs/operations"
 	"github.com/rclone/rclone/fstest"
 	"github.com/rclone/rclone/lib/file"
 	"github.com/rclone/rclone/lib/readers"
@@ -514,3 +515,43 @@ func TestFilterSymlinkCopyLinks(t *testing.T) {
 func TestFilterSymlinkLinks(t *testing.T) {
 	testFilterSymlink(t, false)
 }
+
+func TestCopySymlink(t *testing.T) {
+	ctx := context.Background()
+	r := fstest.NewRun(t)
+	defer r.Finalise()
+	when := time.Now()
+	f := r.Flocal.(*Fs)
+
+	// Create a file and a symlink to it
+	r.WriteFile("src/file.txt", "hello world", when)
+	require.NoError(t, os.Symlink("file.txt", filepath.Join(r.LocalName, "src", "link.txt")))
+	defer func() {
+		// Reset -L/-l mode
+		f.opt.FollowSymlinks = false
+		f.opt.TranslateSymlinks = false
+		f.lstat = os.Lstat
+	}()
+
+	// Set fs into "-l/--links" mode
+	f.opt.FollowSymlinks = false
+	f.opt.TranslateSymlinks = true
+	f.lstat = os.Lstat
+
+	// Create dst
+	require.NoError(t, f.Mkdir(ctx, "dst"))
+
+	// Do copy from src into dst
+	src, err := f.NewObject(ctx, "src/link.txt.rclonelink")
+	require.NoError(t, err)
+	require.NotNil(t, src)
+	dst, err := operations.Copy(ctx, f, nil, "dst/link.txt.rclonelink", src)
+	require.NoError(t, err)
+	require.NotNil(t, dst)
+
+	// Test that we made a symlink and it has the right contents
+	dstPath := filepath.Join(r.LocalName, "dst", "link.txt")
+	linkContents, err := os.Readlink(dstPath)
+	require.NoError(t, err)
+	assert.Equal(t, "file.txt", linkContents)
+}