func TestSyncS3BucketToEmptyFolder(t *testing.T) {
	t.Parallel()
	s3client, s5cmd, cleanup := setup(t)
	defer cleanup()
	bucket := s3BucketFromTestName(t)
	createBucket(t, s3client, bucket)
	S3Content := map[string]string{
		"testfile.txt":            "S: this is a test file",
		"readme.md":               "S: this is a readme file",
		"a/another_test_file.txt": "S: yet another txt file",
		"abc/def/test.py":         "S: file in nested folders",
	}
	for filename, content := range S3Content {
		putFile(t, s3client, bucket, filename, content)
	}
	workdir := fs.NewDir(t, "somedir")
	defer workdir.Remove()
	bucketPath := fmt.Sprintf("s3://%v", bucket)
	src := fmt.Sprintf("%v/*", bucketPath)
	dst := fmt.Sprintf("%v/", workdir.Path())
	dst = filepath.ToSlash(dst)
	cmd := s5cmd("sync", src, dst)
	result := icmd.RunCmd(cmd)
	result.Assert(t, icmd.Success)
	assertLines(t, result.Stdout(), map[int]compareFunc{
		0: equals(`cp %v/a/another_test_file.txt %va/another_test_file.txt`, bucketPath, dst),
		1: equals(`cp %v/abc/def/test.py %vabc/def/test.py`, bucketPath, dst),
		2: equals(`cp %v/readme.md %vreadme.md`, bucketPath, dst),
		3: equals(`cp %v/testfile.txt %vtestfile.txt`, bucketPath, dst),
	}, sortInput(true))
	expectedFolderLayout := []fs.PathOp{
		fs.WithFile("testfile.txt", "S: this is a test file"),
		fs.WithFile("readme.md", "S: this is a readme file"),
		fs.WithDir("a",
			fs.WithFile("another_test_file.txt", "S: yet another txt file"),
		),
		fs.WithDir("abc",
			fs.WithDir("def",
				fs.WithFile("test.py", "S: file in nested folders"),
			),
		),
	}
	expected := fs.Expected(t, expectedFolderLayout...)
	assert.Assert(t, fs.Equal(workdir.Path(), expected))
	for key, content := range S3Content {
		assert.Assert(t, ensureS3Object(s3client, bucket, key, content))
	}
}
sync  s3://bucket/* folder/
package e2e
import (
	"fmt"
	"path/filepath"
	"testing"
	"time"
	"gotest.tools/v3/assert"
	"gotest.tools/v3/fs"
	"gotest.tools/v3/icmd"
)
func TestSyncLocalToLocalNotPermitted(t *testing.T) {
	t.Parallel()
	_, s5cmd, cleanup := setup(t)
	defer cleanup()
	sourceWorkDir := fs.NewDir(t, "source")
	destWorkDir := fs.NewDir(t, "dest")
	srcpath := filepath.ToSlash(sourceWorkDir.Path())
	destpath := filepath.ToSlash(destWorkDir.Path())
	cmd := s5cmd("sync", srcpath, destpath)
	result := icmd.RunCmd(cmd)
	result.Assert(t, icmd.Expected{ExitCode: 1})
	assertLines(t, result.Stderr(), map[int]compareFunc{
		0: equals(`ERROR "sync %s %s": local->local sync operations are not permitted`, srcpath, destpath),
	})
}
func TestSyncLocalFileToS3NotPermitted(t *testing.T) {
	t.Parallel()
	s3client, s5cmd, cleanup := setup(t)
	defer cleanup()
	const bucket = "bucket"
	createBucket(t, s3client, bucket)
	sourceWorkDir := fs.NewFile(t, "source.go")
	srcpath := filepath.ToSlash(sourceWorkDir.Path())
	dstpath := fmt.Sprintf("s3://%s/", bucket)
	cmd := s5cmd("sync", srcpath, dstpath)
	result := icmd.RunCmd(cmd)
	result.Assert(t, icmd.Expected{ExitCode: 1})
	assertLines(t, result.Stderr(), map[int]compareFunc{
		0: equals(`ERROR "sync %s %s": local source must be a directory`, srcpath, dstpath),
	})
}
func TestSyncSingleS3ObjectToLocalNotPermitted(t *testing.T) {
	t.Parallel()
	s3client, s5cmd, cleanup := setup(t)
	defer cleanup()
	const (
		filename = "source.go"
		bucket   = "bucket"
	)
	createBucket(t, s3client, bucket)
	putFile(t, s3client, bucket, filename, "content")
	srcpath := fmt.Sprintf("s3://%s/%s", bucket, filename)
	cmd := s5cmd("sync", srcpath, ".")
	result := icmd.RunCmd(cmd)
	result.Assert(t, icmd.Expected{ExitCode: 1})
	assertLines(t, result.Stderr(), map[int]compareFunc{
		0: equals(`ERROR "sync %s .": remote source %q must be a bucket or a prefix`, srcpath, srcpath),
	})
}
func TestSyncLocalFolderToS3EmptyBucket(t *testing.T) {
	t.Parallel()
	s3client, s5cmd, cleanup := setup(t)
	defer cleanup()
	bucket := s3BucketFromTestName(t)
	createBucket(t, s3client, bucket)
	folderLayout := []fs.PathOp{
		fs.WithFile("testfile.txt", "S: this is a test file"),
		fs.WithFile("readme.md", "S: this is a readme file"),
		fs.WithDir("a",
			fs.WithFile("another_test_file.txt", "S: yet another txt file"),
		),
		fs.WithDir("b",
			fs.WithFile("filename-with-hypen.gz", "S: file has hyphen in its name"),
		),
	}
	workdir := fs.NewDir(t, "somedir", folderLayout...)
	defer workdir.Remove()
	src := fmt.Sprintf("%v/", workdir.Path())
	src = filepath.ToSlash(src)
	dst := fmt.Sprintf("s3://%v/", bucket)
	cmd := s5cmd("sync", src, dst)
	result := icmd.RunCmd(cmd)
	result.Assert(t, icmd.Success)
	assertLines(t, result.Stdout(), map[int]compareFunc{
		0: equals(`cp %va/another_test_file.txt %va/another_test_file.txt`, src, dst),
		1: equals(`cp %vb/filename-with-hypen.gz %vb/filename-with-hypen.gz`, src, dst),
		2: equals(`cp %vreadme.md %vreadme.md`, src, dst),
		3: equals(`cp %vtestfile.txt %vtestfile.txt`, src, dst),
	}, sortInput(true))
	expected := fs.Expected(t, folderLayout...)
	assert.Assert(t, fs.Equal(workdir.Path(), expected))
	expectedS3Content := map[string]string{
		"testfile.txt":             "S: this is a test file",
		"readme.md":                "S: this is a readme file",
		"b/filename-with-hypen.gz": "S: file has hyphen in its name",
		"a/another_test_file.txt":  "S: yet another txt file",
	}
	for key, content := range expectedS3Content {
		assert.Assert(t, ensureS3Object(s3client, bucket, key, content))
	}
}