mirror of
https://github.com/rclone/rclone.git
synced 2025-12-22 03:03:20 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48d259da68 | ||
|
|
f86fa6a062 | ||
|
|
93cb0a47e4 | ||
|
|
a12760c038 | ||
|
|
fdcd6a3a4c | ||
|
|
cb7891f4ff | ||
|
|
8f2684fa70 | ||
|
|
7ebf48ef42 | ||
|
|
1d67b014cb |
11
.travis.yml
Normal file
11
.travis.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.1.2
|
||||||
|
- 1.2.2
|
||||||
|
- 1.3
|
||||||
|
- tip
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go get ./...
|
||||||
|
- go test -v ./...
|
||||||
7
Makefile
7
Makefile
@@ -1,6 +1,6 @@
|
|||||||
TAG := $(shell git describe --tags)
|
TAG := $(shell git describe --tags)
|
||||||
LAST_TAG := $(shell git describe --tags --abbrev=0)
|
LAST_TAG := $(shell git describe --tags --abbrev=0)
|
||||||
NEW_TAG := $(shell echo $(LAST_TAG) | perl -lpe 's/v//; $$_ += 0.01; $$_ = "v" . $$_')
|
NEW_TAG := $(shell echo $(LAST_TAG) | perl -lpe 's/v//; $$_ += 0.01; $$_ = sprintf("v%.2f", $$_)')
|
||||||
|
|
||||||
rclone: *.go */*.go
|
rclone: *.go */*.go
|
||||||
@go version
|
@go version
|
||||||
@@ -50,12 +50,11 @@ tag:
|
|||||||
perl -lpe 's/VERSION/${NEW_TAG}/g; s/DATE/'`date -I`'/g;' docs/content/downloads.md.in > docs/content/downloads.md
|
perl -lpe 's/VERSION/${NEW_TAG}/g; s/DATE/'`date -I`'/g;' docs/content/downloads.md.in > docs/content/downloads.md
|
||||||
git tag $(NEW_TAG)
|
git tag $(NEW_TAG)
|
||||||
@echo "Add this to changelog in README.md"
|
@echo "Add this to changelog in README.md"
|
||||||
@echo " * $(NEW_TAG) - " `date -I`
|
@echo " * $(NEW_TAG) -" `date -I`
|
||||||
@git log $(LAST_TAG)..$(NEW_TAG) --oneline
|
@git log $(LAST_TAG)..$(NEW_TAG) --oneline
|
||||||
@echo "Then commit the changes"
|
@echo "Then commit the changes"
|
||||||
@echo git commit -m "Version $(NEW_TAG)" -a -v
|
@echo git commit -m "Version $(NEW_TAG)" -a -v
|
||||||
@echo "And finally run make retag before make cross etc"
|
@echo "And finally run make retag before make cross etc"
|
||||||
|
|
||||||
retag:
|
retag:
|
||||||
echo git tag -f $(LAST_TAG)
|
git tag -f $(LAST_TAG)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
% rclone(1) User Manual
|
% rclone(1) User Manual
|
||||||
% Nick Craig-Wood
|
% Nick Craig-Wood
|
||||||
% Apr 24, 2014
|
% Jul 7, 2014
|
||||||
|
|
||||||
Rclone
|
Rclone
|
||||||
======
|
======
|
||||||
@@ -214,7 +214,11 @@ Bugs
|
|||||||
|
|
||||||
Changelog
|
Changelog
|
||||||
---------
|
---------
|
||||||
|
* v1.00 - 2014-07-03
|
||||||
|
* drive: fix whole second dates - fixes #4
|
||||||
|
* v0.99 - 2014-06-26
|
||||||
|
* Fix --dry-run not working
|
||||||
|
* Make compatible with go 1.1
|
||||||
* v0.98 - 2014-05-30
|
* v0.98 - 2014-05-30
|
||||||
* s3: Treat missing Content-Length as 0 for some ceph installations
|
* s3: Treat missing Content-Length as 0 for some ceph installations
|
||||||
* rclonetest: add file with a space in
|
* rclonetest: add file with a space in
|
||||||
|
|||||||
@@ -2,34 +2,34 @@
|
|||||||
title: "Rclone downloads"
|
title: "Rclone downloads"
|
||||||
description: "Download rclone binaries for your OS."
|
description: "Download rclone binaries for your OS."
|
||||||
type: page
|
type: page
|
||||||
date: "2014-05-30"
|
date: "2014-07-03"
|
||||||
---
|
---
|
||||||
|
|
||||||
Rclone Download v0.98
|
Rclone Download v1.00
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
* Windows
|
* Windows
|
||||||
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v0.98-windows-386.zip)
|
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v1.00-windows-386.zip)
|
||||||
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v0.98-windows-amd64.zip)
|
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v1.00-windows-amd64.zip)
|
||||||
* OSX
|
* OSX
|
||||||
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v0.98-osx-386.zip)
|
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v1.00-osx-386.zip)
|
||||||
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v0.98-osx-amd64.zip)
|
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v1.00-osx-amd64.zip)
|
||||||
* Linux
|
* Linux
|
||||||
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v0.98-linux-386.zip)
|
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v1.00-linux-386.zip)
|
||||||
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v0.98-linux-amd64.zip)
|
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v1.00-linux-amd64.zip)
|
||||||
* [ARM - 32 Bit](http://downloads.rclone.org/rclone-v0.98-linux-arm.zip)
|
* [ARM - 32 Bit](http://downloads.rclone.org/rclone-v1.00-linux-arm.zip)
|
||||||
* FreeBSD
|
* FreeBSD
|
||||||
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v0.98-freebsd-386.zip)
|
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v1.00-freebsd-386.zip)
|
||||||
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v0.98-freebsd-amd64.zip)
|
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v1.00-freebsd-amd64.zip)
|
||||||
* [ARM - 32 Bit](http://downloads.rclone.org/rclone-v0.98-freebsd-arm.zip)
|
* [ARM - 32 Bit](http://downloads.rclone.org/rclone-v1.00-freebsd-arm.zip)
|
||||||
* NetBSD
|
* NetBSD
|
||||||
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v0.98-netbsd-386.zip)
|
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v1.00-netbsd-386.zip)
|
||||||
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v0.98-netbsd-amd64.zip)
|
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v1.00-netbsd-amd64.zip)
|
||||||
* [ARM - 32 Bit](http://downloads.rclone.org/rclone-v0.98-netbsd-arm.zip)
|
* [ARM - 32 Bit](http://downloads.rclone.org/rclone-v1.00-netbsd-arm.zip)
|
||||||
* OpenBSD
|
* OpenBSD
|
||||||
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v0.98-openbsd-386.zip)
|
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v1.00-openbsd-386.zip)
|
||||||
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v0.98-openbsd-amd64.zip)
|
* [AMD64 - 64 Bit](http://downloads.rclone.org/rclone-v1.00-openbsd-amd64.zip)
|
||||||
* Plan 9
|
* Plan 9
|
||||||
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v0.98-plan9-386.zip)
|
* [386 - 32 Bit](http://downloads.rclone.org/rclone-v1.00-plan9-386.zip)
|
||||||
|
|
||||||
Older downloads can be found [here](http://downloads.rclone.org/)
|
Older downloads can be found [here](http://downloads.rclone.org/)
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ const (
|
|||||||
rcloneClientId = "202264815644.apps.googleusercontent.com"
|
rcloneClientId = "202264815644.apps.googleusercontent.com"
|
||||||
rcloneClientSecret = "X4Z3ca8xfWDb1Voo-F9a7ZxJ"
|
rcloneClientSecret = "X4Z3ca8xfWDb1Voo-F9a7ZxJ"
|
||||||
driveFolderType = "application/vnd.google-apps.folder"
|
driveFolderType = "application/vnd.google-apps.folder"
|
||||||
|
RFC3339In = time.RFC3339
|
||||||
|
RFC3339Out = "2006-01-02T15:04:05.000000000Z07:00"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Globals
|
// Globals
|
||||||
@@ -674,7 +676,7 @@ func (f *FsDrive) ListDir() fs.DirChan {
|
|||||||
Bytes: -1,
|
Bytes: -1,
|
||||||
Count: -1,
|
Count: -1,
|
||||||
}
|
}
|
||||||
dir.When, _ = time.Parse(time.RFC3339, item.ModifiedDate)
|
dir.When, _ = time.Parse(RFC3339In, item.ModifiedDate)
|
||||||
out <- dir
|
out <- dir
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
@@ -711,7 +713,7 @@ func (f *FsDrive) Put(in io.Reader, remote string, modTime time.Time, size int64
|
|||||||
if mimeType == "" {
|
if mimeType == "" {
|
||||||
mimeType = "application/octet-stream"
|
mimeType = "application/octet-stream"
|
||||||
}
|
}
|
||||||
modifiedDate := modTime.Format(time.RFC3339Nano)
|
modifiedDate := modTime.Format(RFC3339Out)
|
||||||
|
|
||||||
// Define the metadata for the file we are going to create.
|
// Define the metadata for the file we are going to create.
|
||||||
info := &drive.File{
|
info := &drive.File{
|
||||||
@@ -864,7 +866,7 @@ func (o *FsObjectDrive) ModTime() time.Time {
|
|||||||
fs.Log(o, "Failed to read metadata: %s", err)
|
fs.Log(o, "Failed to read metadata: %s", err)
|
||||||
return time.Now()
|
return time.Now()
|
||||||
}
|
}
|
||||||
modTime, err := time.Parse(time.RFC3339, o.modifiedDate)
|
modTime, err := time.Parse(RFC3339In, o.modifiedDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fs.Log(o, "Failed to read mtime from object: %s", err)
|
fs.Log(o, "Failed to read mtime from object: %s", err)
|
||||||
return time.Now()
|
return time.Now()
|
||||||
@@ -882,7 +884,7 @@ func (o *FsObjectDrive) SetModTime(modTime time.Time) {
|
|||||||
}
|
}
|
||||||
// New metadata
|
// New metadata
|
||||||
info := &drive.File{
|
info := &drive.File{
|
||||||
ModifiedDate: modTime.Format(time.RFC3339Nano),
|
ModifiedDate: modTime.Format(RFC3339Out),
|
||||||
}
|
}
|
||||||
// Set modified date
|
// Set modified date
|
||||||
_, err = o.drive.svc.Files.Update(o.id, info).SetModifiedDate(true).Do()
|
_, err = o.drive.svc.Files.Update(o.id, info).SetModifiedDate(true).Do()
|
||||||
@@ -920,7 +922,7 @@ func (o *FsObjectDrive) Open() (in io.ReadCloser, err error) {
|
|||||||
func (o *FsObjectDrive) Update(in io.Reader, modTime time.Time, size int64) error {
|
func (o *FsObjectDrive) Update(in io.Reader, modTime time.Time, size int64) error {
|
||||||
info := &drive.File{
|
info := &drive.File{
|
||||||
Id: o.id,
|
Id: o.id,
|
||||||
ModifiedDate: modTime.Format(time.RFC3339Nano),
|
ModifiedDate: modTime.Format(RFC3339Out),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the API request to upload metadata and file data.
|
// Make the API request to upload metadata and file data.
|
||||||
|
|||||||
@@ -70,10 +70,10 @@ func LoadConfig() {
|
|||||||
// FIXME read these from the config file too
|
// FIXME read these from the config file too
|
||||||
Config.Verbose = *verbose
|
Config.Verbose = *verbose
|
||||||
Config.Quiet = *quiet
|
Config.Quiet = *quiet
|
||||||
Config.Quiet = *dryRun
|
|
||||||
Config.ModifyWindow = *modifyWindow
|
Config.ModifyWindow = *modifyWindow
|
||||||
Config.Checkers = *checkers
|
Config.Checkers = *checkers
|
||||||
Config.Transfers = *transfers
|
Config.Transfers = *transfers
|
||||||
|
Config.DryRun = *dryRun
|
||||||
|
|
||||||
ConfigPath = *configFile
|
ConfigPath = *configFile
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ func Command(commands []string) byte {
|
|||||||
if len(result) != 1 {
|
if len(result) != 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
i := strings.IndexByte(optString, result[0])
|
i := strings.Index(optString, string(result[0]))
|
||||||
if i >= 0 {
|
if i >= 0 {
|
||||||
return result[0]
|
return result[0]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,11 @@ func Copier(in ObjectPairChan, fdst Fs, wg *sync.WaitGroup) {
|
|||||||
for pair := range in {
|
for pair := range in {
|
||||||
src := pair.src
|
src := pair.src
|
||||||
Stats.Transferring(src)
|
Stats.Transferring(src)
|
||||||
|
if Config.DryRun {
|
||||||
|
Debug(src, "Not copying as --dry-run")
|
||||||
|
} else {
|
||||||
Copy(fdst, pair.dst, src)
|
Copy(fdst, pair.dst, src)
|
||||||
|
}
|
||||||
Stats.DoneTransferring(src)
|
Stats.DoneTransferring(src)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,13 +145,18 @@ func TestMkdir(flocal, fremote fs.Fs) {
|
|||||||
CheckListing(fremote, items)
|
CheckListing(fremote, items)
|
||||||
}
|
}
|
||||||
|
|
||||||
var t1 = Time("2001-02-03T04:05:06.999999999Z")
|
var t1 = Time("2001-02-03T04:05:06.499999999Z")
|
||||||
var t2 = Time("2011-12-25T12:59:59.123456789Z")
|
var t2 = Time("2011-12-25T12:59:59.123456789Z")
|
||||||
|
var t3 = Time("2011-12-30T12:59:59.000000000Z")
|
||||||
|
|
||||||
func TestCopy(flocal, fremote fs.Fs) {
|
func TestCopy(flocal, fremote fs.Fs) {
|
||||||
WriteFile("empty space", "", t1)
|
WriteFile("empty space", "", t1)
|
||||||
|
|
||||||
|
// Check dry run is working
|
||||||
|
log.Printf("Copy with --dry-run")
|
||||||
|
fs.Config.DryRun = true
|
||||||
err := fs.Sync(fremote, flocal, false)
|
err := fs.Sync(fremote, flocal, false)
|
||||||
|
fs.Config.DryRun = false
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Copy failed: %v", err)
|
log.Fatalf("Copy failed: %v", err)
|
||||||
}
|
}
|
||||||
@@ -159,6 +164,18 @@ func TestCopy(flocal, fremote fs.Fs) {
|
|||||||
items := []Item{
|
items := []Item{
|
||||||
{Path: "empty space", Size: 0, ModTime: t1, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
{Path: "empty space", Size: 0, ModTime: t1, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckListing(flocal, items)
|
||||||
|
CheckListing(fremote, []Item{})
|
||||||
|
|
||||||
|
// Now without dry run
|
||||||
|
|
||||||
|
log.Printf("Copy")
|
||||||
|
err = fs.Sync(fremote, flocal, false)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Copy failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
CheckListing(flocal, items)
|
CheckListing(flocal, items)
|
||||||
CheckListing(fremote, items)
|
CheckListing(fremote, items)
|
||||||
}
|
}
|
||||||
@@ -182,14 +199,14 @@ func TestSync(flocal, fremote fs.Fs) {
|
|||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
log.Printf("Sync after adding a file")
|
log.Printf("Sync after adding a file")
|
||||||
WriteFile("potato", "------------------------------------------------------------", t1)
|
WriteFile("potato", "------------------------------------------------------------", t3)
|
||||||
err = fs.Sync(fremote, flocal, true)
|
err = fs.Sync(fremote, flocal, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Sync failed: %v", err)
|
log.Fatalf("Sync failed: %v", err)
|
||||||
}
|
}
|
||||||
items = []Item{
|
items = []Item{
|
||||||
{Path: "empty space", Size: 0, ModTime: t2, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
{Path: "empty space", Size: 0, ModTime: t2, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
||||||
{Path: "potato", Size: 60, ModTime: t1, Md5sum: "d6548b156ea68a4e003e786df99eee76"},
|
{Path: "potato", Size: 60, ModTime: t3, Md5sum: "d6548b156ea68a4e003e786df99eee76"},
|
||||||
}
|
}
|
||||||
CheckListing(flocal, items)
|
CheckListing(flocal, items)
|
||||||
CheckListing(fremote, items)
|
CheckListing(fremote, items)
|
||||||
@@ -197,36 +214,51 @@ func TestSync(flocal, fremote fs.Fs) {
|
|||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
log.Printf("Sync after changing a file's size only")
|
log.Printf("Sync after changing a file's size only")
|
||||||
WriteFile("potato", "smaller but same date", t1)
|
WriteFile("potato", "smaller but same date", t3)
|
||||||
err = fs.Sync(fremote, flocal, true)
|
err = fs.Sync(fremote, flocal, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Sync failed: %v", err)
|
log.Fatalf("Sync failed: %v", err)
|
||||||
}
|
}
|
||||||
items = []Item{
|
items = []Item{
|
||||||
{Path: "empty space", Size: 0, ModTime: t2, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
{Path: "empty space", Size: 0, ModTime: t2, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
||||||
{Path: "potato", Size: 21, ModTime: t1, Md5sum: "100defcf18c42a1e0dc42a789b107cd2"},
|
{Path: "potato", Size: 21, ModTime: t3, Md5sum: "100defcf18c42a1e0dc42a789b107cd2"},
|
||||||
}
|
}
|
||||||
CheckListing(flocal, items)
|
CheckListing(flocal, items)
|
||||||
CheckListing(fremote, items)
|
CheckListing(fremote, items)
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
|
||||||
log.Printf("Sync after removing a file")
|
log.Printf("Sync after removing a file and adding a file --dry-run")
|
||||||
|
WriteFile("potato2", "------------------------------------------------------------", t1)
|
||||||
err = os.Remove(localName + "/potato")
|
err = os.Remove(localName + "/potato")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Remove failed: %v", err)
|
log.Fatalf("Remove failed: %v", err)
|
||||||
}
|
}
|
||||||
|
fs.Config.DryRun = true
|
||||||
err = fs.Sync(fremote, flocal, true)
|
err = fs.Sync(fremote, flocal, true)
|
||||||
|
fs.Config.DryRun = false
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Sync failed: %v", err)
|
log.Fatalf("Sync failed: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
before := []Item{
|
||||||
|
{Path: "empty space", Size: 0, ModTime: t2, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
||||||
|
{Path: "potato", Size: 21, ModTime: t3, Md5sum: "100defcf18c42a1e0dc42a789b107cd2"},
|
||||||
|
}
|
||||||
items = []Item{
|
items = []Item{
|
||||||
{Path: "empty space", Size: 0, ModTime: t2, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
{Path: "empty space", Size: 0, ModTime: t2, Md5sum: "d41d8cd98f00b204e9800998ecf8427e"},
|
||||||
|
{Path: "potato2", Size: 60, ModTime: t1, Md5sum: "d6548b156ea68a4e003e786df99eee76"},
|
||||||
|
}
|
||||||
|
CheckListing(flocal, items)
|
||||||
|
CheckListing(fremote, before)
|
||||||
|
|
||||||
|
log.Printf("Sync after removing a file and adding a file")
|
||||||
|
err = fs.Sync(fremote, flocal, true)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Sync failed: %v", err)
|
||||||
}
|
}
|
||||||
CheckListing(flocal, items)
|
CheckListing(flocal, items)
|
||||||
CheckListing(fremote, items)
|
CheckListing(fremote, items)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLs(flocal, fremote fs.Fs) {
|
func TestLs(flocal, fremote fs.Fs) {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
const Version = "v0.98"
|
const Version = "v1.00"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
const Version = "v0.98"
|
const Version = "v1.00"
|
||||||
|
|||||||
Reference in New Issue
Block a user