1
0
mirror of https://github.com/rclone/rclone.git synced 2026-01-04 09:33:36 +00:00

implement rcat – fixes #230, fixes #1001

This commit is contained in:
Stefan Breunig
2017-08-03 21:42:35 +02:00
parent 3e3a59768e
commit 28a18303f3
32 changed files with 1223 additions and 916 deletions

View File

@@ -6,6 +6,7 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"mime"
"path"
@@ -13,6 +14,7 @@ import (
"strings"
"sync"
"sync/atomic"
"time"
"github.com/pkg/errors"
"github.com/spf13/pflag"
@@ -1510,6 +1512,60 @@ func Cat(f Fs, w io.Writer, offset, count int64) error {
})
}
// Rcat reads data from the Reader until EOF and uploads it to a file on remote
func Rcat(fdst Fs, dstFileName string, in0 io.ReadCloser, modTime time.Time) (err error) {
Stats.Transferring(dstFileName)
defer func() {
Stats.DoneTransferring(dstFileName, err == nil)
}()
fStreamTo := fdst
canStream := fdst.Features().PutStream != nil
if !canStream {
Debugf(fdst, "Target remote doesn't support streaming uploads, creating temporary local FS to spool file")
tmpLocalFs, err := temporaryLocalFs()
if err != nil {
return errors.Wrap(err, "Failed to create temporary local FS to spool file")
}
defer func() {
err := Purge(tmpLocalFs)
if err != nil {
Infof(tmpLocalFs, "Failed to cleanup temporary FS: %v", err)
}
}()
fStreamTo = tmpLocalFs
}
objInfo := NewStaticObjectInfo(dstFileName, modTime, -1, false, nil, nil)
// work out which hash to use - limit to 1 hash in common
var common HashSet
hashType := HashNone
if !Config.SizeOnly {
common = fStreamTo.Hashes().Overlap(SupportedHashes)
if common.Count() > 0 {
hashType = common.GetOne()
common = HashSet(hashType)
}
}
hashOption := &HashesOption{Hashes: common}
in := NewAccountSizeName(in0, -1, dstFileName).WithBuffer()
if Config.DryRun {
Logf("stdin", "Not copying as --dry-run")
// prevents "broken pipe" errors
_, err = io.Copy(ioutil.Discard, in)
return err
}
tmpObj, err := fStreamTo.Features().PutStream(in, objInfo, hashOption)
if err == nil && !canStream {
err = Copy(fdst, nil, dstFileName, tmpObj)
}
return err
}
// Rmdirs removes any empty directories (or directories only
// containing empty directories) under f, including f.
func Rmdirs(f Fs, dir string) error {