mirror of
https://github.com/gilbertchen/duplicacy
synced 2025-12-10 05:13:17 +00:00
Run goimports on all source files
This commit is contained in:
@@ -5,22 +5,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"strconv"
|
||||
"runtime"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gilbertchen/cli"
|
||||
|
||||
"github.com/gilbertchen/duplicacy/src"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/gilbertchen/duplicacy/src"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -239,7 +240,6 @@ func configRepository(context *cli.Context, init bool) {
|
||||
preferencePath = path.Join(repository, duplicacy.DUPLICACY_DIRECTORY) // TOKEEP
|
||||
}
|
||||
|
||||
|
||||
if stat, _ := os.Stat(path.Join(preferencePath, "preferences")); stat != nil {
|
||||
duplicacy.LOG_ERROR("REPOSITORY_INIT", "The repository %s has already been initialized", repository)
|
||||
return
|
||||
@@ -890,7 +890,6 @@ func diff(context *cli.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
password := ""
|
||||
if preference.Encrypted {
|
||||
password = duplicacy.GetPassword(*preference, "password", "Enter storage password:", false, false)
|
||||
@@ -1058,7 +1057,6 @@ func copySnapshots(context *cli.Context) {
|
||||
sourceManager.SetupSnapshotCache(source.Name)
|
||||
duplicacy.SavePassword(*source, "password", sourcePassword)
|
||||
|
||||
|
||||
_, destination := getRepositoryPreference(context, context.String("to"))
|
||||
|
||||
if destination.Name == source.Name {
|
||||
@@ -1072,7 +1070,6 @@ func copySnapshots(context *cli.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
duplicacy.LOG_INFO("STORAGE_SET", "Destination storage set to %s", destination.StorageURL)
|
||||
destinationStorage := duplicacy.CreateStorage(*destination, false, threads)
|
||||
if destinationStorage == nil {
|
||||
@@ -1521,7 +1518,6 @@ func main() {
|
||||
Action: pruneSnapshots,
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
Name: "password",
|
||||
Flags: []cli.Flag{
|
||||
@@ -1683,7 +1679,6 @@ func main() {
|
||||
ArgsUsage: "<storage url>",
|
||||
Action: infoStorage,
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"bytes"
|
||||
"sync"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"mime/multipart"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
@@ -29,6 +29,7 @@ func (err ACDError) Error() string {
|
||||
}
|
||||
|
||||
var ACDRefreshTokenURL = "https://duplicacy.com/acd_refresh"
|
||||
|
||||
type ACDClient struct {
|
||||
HTTPClient *http.Client
|
||||
|
||||
@@ -42,7 +43,6 @@ type ACDClient struct {
|
||||
TestMode bool
|
||||
}
|
||||
|
||||
|
||||
func NewACDClient(tokenFile string) (*ACDClient, error) {
|
||||
|
||||
description, err := ioutil.ReadFile(tokenFile)
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"fmt"
|
||||
"testing"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
crypto_rand "crypto/rand"
|
||||
"math/rand"
|
||||
|
||||
@@ -88,8 +88,7 @@ func (storage *ACDStorage) deletePathID(path string) {
|
||||
storage.idCacheLock.Unlock()
|
||||
}
|
||||
|
||||
|
||||
func (storage *ACDStorage) convertFilePath(filePath string) (string) {
|
||||
func (storage *ACDStorage) convertFilePath(filePath string) string {
|
||||
if strings.HasPrefix(filePath, "chunks/") && strings.HasSuffix(filePath, ".fsl") {
|
||||
return "fossils/" + filePath[len("chunks/"):len(filePath)-len(".fsl")]
|
||||
}
|
||||
@@ -183,7 +182,6 @@ func (storage *ACDStorage) ListFiles(threadIndex int, dir string) ([]string, []i
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
|
||||
for _, entry := range entries {
|
||||
name := entry.Name
|
||||
if parent == "fossils" {
|
||||
@@ -389,16 +387,16 @@ func (storage *ACDStorage) UploadFile(threadIndex int, filePath string, content
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *ACDStorage) IsCacheNeeded() (bool) { return true }
|
||||
func (storage *ACDStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *ACDStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *ACDStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *ACDStorage) IsStrongConsistent() (bool) { return true }
|
||||
func (storage *ACDStorage) IsStrongConsistent() bool { return true }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *ACDStorage) IsFastListing() (bool) { return true }
|
||||
func (storage *ACDStorage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *ACDStorage) EnableTestMode() {}
|
||||
|
||||
@@ -189,16 +189,16 @@ func (storage *AzureStorage) UploadFile(threadIndex int, filePath string, conten
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *AzureStorage) IsCacheNeeded() (bool) { return true }
|
||||
func (storage *AzureStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *AzureStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *AzureStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *AzureStorage) IsStrongConsistent() (bool) { return true }
|
||||
func (storage *AzureStorage) IsStrongConsistent() bool { return true }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *AzureStorage) IsFastListing() (bool) { return true }
|
||||
func (storage *AzureStorage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *AzureStorage) EnableTestMode() {}
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"bytes"
|
||||
"strconv"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"crypto/sha1"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type B2Error struct {
|
||||
@@ -51,7 +51,6 @@ type B2Client struct {
|
||||
UploadToken string
|
||||
|
||||
TestMode bool
|
||||
|
||||
}
|
||||
|
||||
func NewB2Client(accountID string, applicationKey string) *B2Client {
|
||||
@@ -168,8 +167,7 @@ func (client *B2Client) call(url string, input interface{}) (io.ReadCloser, int6
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
e := &B2Error {
|
||||
}
|
||||
e := &B2Error{}
|
||||
|
||||
if err := json.NewDecoder(response.Body).Decode(e); err != nil {
|
||||
return nil, 0, err
|
||||
@@ -299,8 +297,7 @@ func (client *B2Client) ListFileNames(startFileName string, singleFile bool, inc
|
||||
|
||||
defer readCloser.Close()
|
||||
|
||||
output := B2ListFileNamesOutput {
|
||||
}
|
||||
output := B2ListFileNamesOutput{}
|
||||
|
||||
if err = json.NewDecoder(readCloser).Decode(&output); err != nil {
|
||||
return nil, err
|
||||
@@ -405,7 +402,7 @@ type B2GetUploadArgumentOutput struct {
|
||||
AuthorizationToken string
|
||||
}
|
||||
|
||||
func (client *B2Client) getUploadURL() (error) {
|
||||
func (client *B2Client) getUploadURL() error {
|
||||
input := make(map[string]string)
|
||||
input["bucketId"] = client.BucketID
|
||||
|
||||
@@ -431,7 +428,6 @@ func (client *B2Client) getUploadURL() (error) {
|
||||
|
||||
func (client *B2Client) UploadFile(filePath string, content []byte, rateLimit int) (err error) {
|
||||
|
||||
|
||||
hasher := sha1.New()
|
||||
hasher.Write(content)
|
||||
hash := hex.EncodeToString(hasher.Sum(nil))
|
||||
@@ -517,4 +513,3 @@ func (client *B2Client) UploadFile(filePath string, content []byte, rateLimit in
|
||||
|
||||
return fmt.Errorf("Maximum backoff reached")
|
||||
}
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
crypto_rand "crypto/rand"
|
||||
"math/rand"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func createB2ClientForTest(t *testing.T) (*B2Client, string) {
|
||||
|
||||
@@ -236,16 +236,16 @@ func (storage *B2Storage) UploadFile(threadIndex int, filePath string, content [
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *B2Storage) IsCacheNeeded() (bool) { return true }
|
||||
func (storage *B2Storage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *B2Storage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *B2Storage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *B2Storage) IsStrongConsistent() (bool) { return true }
|
||||
func (storage *B2Storage) IsStrongConsistent() bool { return true }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *B2Storage) IsFastListing() (bool) { return true }
|
||||
func (storage *B2Storage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *B2Storage) EnableTestMode() {
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"bytes"
|
||||
"os"
|
||||
"io"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"strings"
|
||||
"strconv"
|
||||
"runtime"
|
||||
"encoding/hex"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BackupManager performs the two major operations, backup and restore, and passes other operations, mostly related to
|
||||
@@ -35,12 +35,10 @@ type BackupManager struct {
|
||||
config *Config // contains a number of options
|
||||
}
|
||||
|
||||
|
||||
func (manager *BackupManager) SetDryRun(dryRun bool) {
|
||||
manager.config.dryRun = dryRun
|
||||
}
|
||||
|
||||
|
||||
// CreateBackupManager creates a backup manager using the specified 'storage'. 'snapshotID' is a unique id to
|
||||
// identify snapshots created for this repository. 'top' is the top directory of the repository. 'password' is the
|
||||
// master key which can be nil if encryption is not enabled.
|
||||
@@ -230,7 +228,6 @@ func (manager *BackupManager) Backup(top string, quickMode bool, threads int, ta
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if incompleteSnapshot != nil {
|
||||
|
||||
// This is the last chunk from the incomplete snapshot that can be found in the cache
|
||||
@@ -398,7 +395,6 @@ func (manager *BackupManager) Backup(top string, quickMode bool, threads int, ta
|
||||
LOG_INFO("SNAPSHOT_FAIL", "Will abort the backup on chunk %d", chunkToFail)
|
||||
}
|
||||
|
||||
|
||||
chunkMaker := CreateChunkMaker(manager.config, false)
|
||||
chunkUploader := CreateChunkUploader(manager.config, manager.storage, nil, threads, nil)
|
||||
|
||||
@@ -924,7 +920,6 @@ func (manager *BackupManager) Restore(top string, revision int, inPlace bool, qu
|
||||
file.RestoreMetadata(fullPath, nil)
|
||||
}
|
||||
|
||||
|
||||
if deleteMode && len(patterns) == 0 {
|
||||
// Reverse the order to make sure directories are empty before being deleted
|
||||
for i := range extraFiles {
|
||||
@@ -1019,7 +1014,7 @@ func (encoder *fileEncoder) NextFile() (io.Reader, bool) {
|
||||
// UploadSnapshot uploads the specified snapshot to the storage. It turns Files, ChunkHashes, and ChunkLengths into
|
||||
// sequences of chunks, and uploads these chunks, and finally the snapshot file.
|
||||
func (manager *BackupManager) UploadSnapshot(chunkMaker *ChunkMaker, uploader *ChunkUploader, top string, snapshot *Snapshot,
|
||||
chunkCache map[string]bool, ) ( totalSnapshotChunkSize int64,
|
||||
chunkCache map[string]bool) (totalSnapshotChunkSize int64,
|
||||
numberOfNewSnapshotChunks int, totalUploadedSnapshotChunkSize int64,
|
||||
totalUploadedSnapshotChunkBytes int64) {
|
||||
|
||||
@@ -1455,7 +1450,6 @@ func (manager *BackupManager) RestoreFile(chunkDownloader *ChunkDownloader, chun
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
if existingFile != nil {
|
||||
existingFile.Close()
|
||||
existingFile = nil
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
crypto_rand "crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
"math/rand"
|
||||
"encoding/hex"
|
||||
"time"
|
||||
"crypto/sha256"
|
||||
crypto_rand "crypto/rand"
|
||||
|
||||
"runtime/debug"
|
||||
)
|
||||
@@ -236,7 +236,6 @@ func TestBackupManager(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
|
||||
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
||||
@@ -244,11 +243,11 @@ func TestBackupManager(t *testing.T) {
|
||||
backupManager.SetupSnapshotCache("default")
|
||||
|
||||
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
||||
backupManager.Backup(testDir + "/repository1", /*quickMode=*/true, threads, "first", false, false)
|
||||
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, true, threads, "first", false, false)
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
SetDuplicacyPreferencePath(testDir + "/repository2/.duplicacy")
|
||||
backupManager.Restore(testDir + "/repository2", threads, /*inPlace=*/false, /*quickMode=*/false, threads, /*overwrite=*/true,
|
||||
/*deleteMode=*/false, /*showStatistics=*/false, /*patterns=*/nil)
|
||||
backupManager.Restore(testDir+"/repository2", threads /*inPlace=*/, false /*quickMode=*/, false, threads /*overwrite=*/, true,
|
||||
/*deleteMode=*/ false /*showStatistics=*/, false /*patterns=*/, nil)
|
||||
|
||||
for _, f := range []string{"file1", "file2", "dir1/file3"} {
|
||||
if _, err := os.Stat(testDir + "/repository2/" + f); os.IsNotExist(err) {
|
||||
@@ -268,11 +267,11 @@ func TestBackupManager(t *testing.T) {
|
||||
modifyFile(testDir+"/repository1/dir1/file3", 0.3)
|
||||
|
||||
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
||||
backupManager.Backup(testDir + "/repository1", /*quickMode=*/true, threads, "second", false, false)
|
||||
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, true, threads, "second", false, false)
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
SetDuplicacyPreferencePath(testDir + "/repository2/.duplicacy")
|
||||
backupManager.Restore(testDir + "/repository2", 2, /*inPlace=*/true, /*quickMode=*/true, threads, /*overwrite=*/true,
|
||||
/*deleteMode=*/false, /*showStatistics=*/false, /*patterns=*/nil)
|
||||
backupManager.Restore(testDir+"/repository2", 2 /*inPlace=*/, true /*quickMode=*/, true, threads /*overwrite=*/, true,
|
||||
/*deleteMode=*/ false /*showStatistics=*/, false /*patterns=*/, nil)
|
||||
|
||||
for _, f := range []string{"file1", "file2", "dir1/file3"} {
|
||||
hash1 := getFileHash(testDir + "/repository1/" + f)
|
||||
@@ -288,7 +287,7 @@ func TestBackupManager(t *testing.T) {
|
||||
os.Mkdir(testDir+"/repository1/dir2/dir3", 0700)
|
||||
os.Mkdir(testDir+"/repository1/dir4", 0700)
|
||||
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
||||
backupManager.Backup(testDir + "/repository1", /*quickMode=*/false, threads, "third", false, false)
|
||||
backupManager.Backup(testDir+"/repository1" /*quickMode=*/, false, threads, "third", false, false)
|
||||
time.Sleep(time.Duration(delay) * time.Second)
|
||||
|
||||
// Create some directories and files under repository2 that will be deleted during restore
|
||||
@@ -299,8 +298,8 @@ func TestBackupManager(t *testing.T) {
|
||||
createRandomFile(testDir+"/repository2/dir5/file5", 100)
|
||||
|
||||
SetDuplicacyPreferencePath(testDir + "/repository2/.duplicacy")
|
||||
backupManager.Restore(testDir + "/repository2", 3, /*inPlace=*/true, /*quickMode=*/false, threads, /*overwrite=*/true,
|
||||
/*deleteMode=*/true, /*showStatistics=*/false, /*patterns=*/nil)
|
||||
backupManager.Restore(testDir+"/repository2", 3 /*inPlace=*/, true /*quickMode=*/, false, threads /*overwrite=*/, true,
|
||||
/*deleteMode=*/ true /*showStatistics=*/, false /*patterns=*/, nil)
|
||||
|
||||
for _, f := range []string{"file1", "file2", "dir1/file3"} {
|
||||
hash1 := getFileHash(testDir + "/repository1/" + f)
|
||||
@@ -311,23 +310,23 @@ func TestBackupManager(t *testing.T) {
|
||||
}
|
||||
|
||||
// These files/dirs should not exist because deleteMode == true
|
||||
checkExistence(t, testDir + "/repository2/dir5", false, false);
|
||||
checkExistence(t, testDir + "/repository2/dir5/dir6", false, false);
|
||||
checkExistence(t, testDir + "/repository2/dir7", false, false);
|
||||
checkExistence(t, testDir + "/repository2/file4", false, false);
|
||||
checkExistence(t, testDir + "/repository2/dir5/file5", false, false);
|
||||
checkExistence(t, testDir+"/repository2/dir5", false, false)
|
||||
checkExistence(t, testDir+"/repository2/dir5/dir6", false, false)
|
||||
checkExistence(t, testDir+"/repository2/dir7", false, false)
|
||||
checkExistence(t, testDir+"/repository2/file4", false, false)
|
||||
checkExistence(t, testDir+"/repository2/dir5/file5", false, false)
|
||||
|
||||
// These empty dirs should exist
|
||||
checkExistence(t, testDir + "/repository2/dir2", true, true);
|
||||
checkExistence(t, testDir + "/repository2/dir2/dir3", true, true);
|
||||
checkExistence(t, testDir + "/repository2/dir4", true, true);
|
||||
checkExistence(t, testDir+"/repository2/dir2", true, true)
|
||||
checkExistence(t, testDir+"/repository2/dir2/dir3", true, true)
|
||||
checkExistence(t, testDir+"/repository2/dir4", true, true)
|
||||
|
||||
// Remove file2 and dir1/file3 and restore them from revision 3
|
||||
os.Remove(testDir + "/repository1/file2")
|
||||
os.Remove(testDir + "/repository1/dir1/file3")
|
||||
SetDuplicacyPreferencePath(testDir + "/repository1/.duplicacy")
|
||||
backupManager.Restore(testDir + "/repository1", 3, /*inPlace=*/true, /*quickMode=*/false, threads, /*overwrite=*/true,
|
||||
/*deleteMode=*/false, /*showStatistics=*/false, /*patterns=*/[]string{"+file2", "+dir1/file3", "-*"})
|
||||
backupManager.Restore(testDir+"/repository1", 3 /*inPlace=*/, true /*quickMode=*/, false, threads /*overwrite=*/, true,
|
||||
/*deleteMode=*/ false /*showStatistics=*/, false /*patterns=*/, []string{"+file2", "+dir1/file3", "-*"})
|
||||
|
||||
for _, f := range []string{"file1", "file2", "dir1/file3"} {
|
||||
hash1 := getFileHash(testDir + "/repository1/" + f)
|
||||
|
||||
@@ -5,19 +5,18 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"fmt"
|
||||
"hash"
|
||||
"bytes"
|
||||
"runtime"
|
||||
"crypto/cipher"
|
||||
"compress/zlib"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"compress/zlib"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"runtime"
|
||||
|
||||
"github.com/bkaradzic/go-lz4"
|
||||
|
||||
)
|
||||
|
||||
// A chunk needs to acquire a new buffer and return the old one for every encrypt/decrypt operation, therefore
|
||||
@@ -132,7 +131,7 @@ func (chunk *Chunk) Write(p []byte) (int, error){
|
||||
|
||||
// GetHash returns the chunk hash.
|
||||
func (chunk *Chunk) GetHash() string {
|
||||
if (len(chunk.hash) == 0) {
|
||||
if len(chunk.hash) == 0 {
|
||||
chunk.hash = chunk.hasher.Sum(nil)
|
||||
}
|
||||
|
||||
@@ -379,4 +378,3 @@ func (chunk *Chunk) Decrypt(encryptionKey []byte, derivationKey string) (err err
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"bytes"
|
||||
crypto_rand "crypto/rand"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestChunk(t *testing.T) {
|
||||
@@ -67,7 +67,6 @@ func TestChunk(t *testing.T) {
|
||||
t.Errorf("Original data:\n%x\nDecrypted data:\n%x\n", plainData, decryptedData)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -330,7 +330,6 @@ func (downloader *ChunkDownloader) Download(threadIndex int, task ChunkDownloadT
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
err = chunk.Decrypt(downloader.config.ChunkKey, task.chunkHash)
|
||||
if err != nil {
|
||||
LOG_ERROR("UPLOAD_CHUNK", "Failed to decrypt the chunk %s: %v", chunkID, err)
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ChunkMaker breaks data into chunks using buzhash. To save memory, the chunk maker only use a circular buffer
|
||||
@@ -229,9 +229,8 @@ func (maker *ChunkMaker) ForEachChunk(reader io.Reader, endOfChunk func(chunk *C
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Minimum chunk size has been reached. Calculate the buzhash for the minimum size chunk.
|
||||
if (!minimumReached) {
|
||||
if !minimumReached {
|
||||
|
||||
bytes := maker.minimumChunkSize
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"bytes"
|
||||
crypto_rand "crypto/rand"
|
||||
"math/rand"
|
||||
"io"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func splitIntoChunks(content []byte, n, averageChunkSize, maxChunkSize, minChunkSize,
|
||||
@@ -76,7 +76,7 @@ func splitIntoChunks(content []byte, n, averageChunkSize, maxChunkSize, minChunk
|
||||
return buffers[i], true
|
||||
})
|
||||
|
||||
if (totalFileSize != int64(totalChunkSize)) {
|
||||
if totalFileSize != int64(totalChunkSize) {
|
||||
LOG_ERROR("CHUNK_SPLIT", "total chunk size: %d, total file size: %d", totalChunkSize, totalFileSize)
|
||||
}
|
||||
return chunks, totalChunkSize
|
||||
@@ -84,7 +84,6 @@ func splitIntoChunks(content []byte, n, averageChunkSize, maxChunkSize, minChunk
|
||||
|
||||
func TestChunkMaker(t *testing.T) {
|
||||
|
||||
|
||||
//sizes := [...] int { 64 }
|
||||
sizes := [...]int{64, 256, 1024, 1024 * 10}
|
||||
|
||||
@@ -101,7 +100,7 @@ func TestChunkMaker(t *testing.T) {
|
||||
|
||||
capacities := [...]int{32, 33, 34, 61, 62, 63, 64, 65, 66, 126, 127, 128, 129, 130,
|
||||
255, 256, 257, 511, 512, 513, 1023, 1024, 1025,
|
||||
32, 48, 64, 128, 256, 512, 1024, 2048, }
|
||||
32, 48, 64, 128, 256, 512, 1024, 2048}
|
||||
|
||||
//capacities := [...]int { 32 }
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
"path"
|
||||
"testing"
|
||||
"runtime/debug"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
crypto_rand "crypto/rand"
|
||||
"math/rand"
|
||||
@@ -56,7 +56,6 @@ func TestUploaderAndDownloader(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
numberOfChunks := 100
|
||||
maxChunkSize := 64 * 1024
|
||||
|
||||
@@ -102,7 +101,6 @@ func TestUploaderAndDownloader(t *testing.T) {
|
||||
|
||||
chunkUploader.Stop()
|
||||
|
||||
|
||||
chunkDownloader := CreateChunkDownloader(config, storage, nil, true, testThreads)
|
||||
chunkDownloader.totalChunkSize = int64(totalFileSize)
|
||||
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"bytes"
|
||||
"os"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"hash"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"sync/atomic"
|
||||
"crypto/rand"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
|
||||
blake2 "github.com/minio/blake2b-simd"
|
||||
)
|
||||
@@ -344,7 +344,7 @@ func DownloadConfig(storage Storage, password string) (config *Config, isEncrypt
|
||||
|
||||
}
|
||||
|
||||
func UploadConfig(storage Storage, config *Config, password string) (bool) {
|
||||
func UploadConfig(storage Storage, config *Config, password string) bool {
|
||||
|
||||
// This is the key to encrypt the config file.
|
||||
var masterKey []byte
|
||||
@@ -417,7 +417,6 @@ func ConfigStorage(storage Storage, compressionLevel int, averageChunkSize int,
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
config := CreateConfigFromParameters(compressionLevel, averageChunkSize, maximumChunkSize, minimumChunkSize, len(password) > 0,
|
||||
copyFrom)
|
||||
if config == nil {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/gilbertchen/go-dropbox"
|
||||
)
|
||||
|
||||
@@ -85,7 +86,7 @@ func (storage *DropboxStorage) ListFiles(threadIndex int, dir string) (files []s
|
||||
|
||||
if output.HasMore {
|
||||
output, err = storage.clients[threadIndex].ListFolderContinue(
|
||||
&dropbox.ListFolderContinueInput { Cursor: output.Cursor, })
|
||||
&dropbox.ListFolderContinueInput{Cursor: output.Cursor})
|
||||
|
||||
} else {
|
||||
break
|
||||
@@ -281,16 +282,16 @@ func (storage *DropboxStorage) UploadFile(threadIndex int, filePath string, cont
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *DropboxStorage) IsCacheNeeded() (bool) { return true }
|
||||
func (storage *DropboxStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *DropboxStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *DropboxStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *DropboxStorage) IsStrongConsistent() (bool) { return false }
|
||||
func (storage *DropboxStorage) IsStrongConsistent() bool { return false }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *DropboxStorage) IsFastListing() (bool) { return false }
|
||||
func (storage *DropboxStorage) IsFastListing() bool { return false }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *DropboxStorage) EnableTestMode() {}
|
||||
|
||||
@@ -4,22 +4,20 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
"encoding/json"
|
||||
"encoding/base64"
|
||||
"strings"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
||||
// This is the hidden directory in the repository for storing various files.
|
||||
var DUPLICACY_DIRECTORY = ".duplicacy"
|
||||
var DUPLICACY_FILE = ".duplicacy"
|
||||
@@ -323,7 +321,6 @@ func (entry *Entry) RestoreMetadata(fullPath string, fileInfo *os.FileInfo) bool
|
||||
return SetOwner(fullPath, entry, fileInfo)
|
||||
}
|
||||
|
||||
|
||||
// Return -1 if 'left' should appear before 'right', 1 if opposite, and 0 if they are the same.
|
||||
// Files are always arranged before subdirectories under the same parent directory.
|
||||
func (left *Entry) Compare(right *Entry) int {
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEntrySort(t *testing.T) {
|
||||
@@ -107,7 +107,6 @@ func TestEntryList(t *testing.T) {
|
||||
"ab3/c",
|
||||
}
|
||||
|
||||
|
||||
var entry1, entry2 *Entry
|
||||
|
||||
for i, p1 := range DATA {
|
||||
@@ -217,4 +216,3 @@ func TestEntryList(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ type FileReader struct {
|
||||
}
|
||||
|
||||
// CreateFileReader creates a file reader.
|
||||
func CreateFileReader(top string, files[] *Entry) (*FileReader) {
|
||||
func CreateFileReader(top string, files []*Entry) *FileReader {
|
||||
|
||||
reader := &FileReader{
|
||||
top: top,
|
||||
@@ -68,7 +68,3 @@ func (reader *FileReader) NextFile() bool{
|
||||
reader.CurrentFile = nil
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"path"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
"math/rand"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FileStorage is a local on-disk file storage implementing the Storage interface.
|
||||
@@ -248,16 +248,16 @@ func (storage *FileStorage) UploadFile(threadIndex int, filePath string, content
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *FileStorage) IsCacheNeeded () (bool) { return storage.isCacheNeeded }
|
||||
func (storage *FileStorage) IsCacheNeeded() bool { return storage.isCacheNeeded }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *FileStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *FileStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *FileStorage) IsStrongConsistent() (bool) { return true }
|
||||
func (storage *FileStorage) IsStrongConsistent() bool { return true }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *FileStorage) IsFastListing() (bool) { return false }
|
||||
func (storage *FileStorage) IsFastListing() bool { return false }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *FileStorage) EnableTestMode() {}
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"path"
|
||||
"time"
|
||||
"sync"
|
||||
"strings"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
@@ -35,7 +35,6 @@ type GCDStorage struct {
|
||||
isConnected bool
|
||||
numberOfThreads int
|
||||
TestMode bool
|
||||
|
||||
}
|
||||
|
||||
type GCDConfig struct {
|
||||
@@ -96,7 +95,7 @@ func (storage *GCDStorage) shouldRetry(threadIndex int, err error) (bool, error)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (storage *GCDStorage) convertFilePath(filePath string) (string) {
|
||||
func (storage *GCDStorage) convertFilePath(filePath string) string {
|
||||
if strings.HasPrefix(filePath, "chunks/") && strings.HasSuffix(filePath, ".fsl") {
|
||||
return "fossils/" + filePath[len("chunks/"):len(filePath)-len(".fsl")]
|
||||
}
|
||||
@@ -174,7 +173,6 @@ func (storage *GCDStorage) listFiles(threadIndex int, parentID string, listFiles
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
@@ -614,16 +612,16 @@ func (storage *GCDStorage) UploadFile(threadIndex int, filePath string, content
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *GCDStorage) IsCacheNeeded() (bool) { return true }
|
||||
func (storage *GCDStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *GCDStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *GCDStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *GCDStorage) IsStrongConsistent() (bool) { return false }
|
||||
func (storage *GCDStorage) IsStrongConsistent() bool { return false }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *GCDStorage) IsFastListing() (bool) { return true }
|
||||
func (storage *GCDStorage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *GCDStorage) EnableTestMode() { storage.TestMode = true }
|
||||
|
||||
@@ -5,22 +5,22 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"net/url"
|
||||
"math/rand"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
gcs "cloud.google.com/go/storage"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
gcs "cloud.google.com/go/storage"
|
||||
"google.golang.org/api/googleapi"
|
||||
"google.golang.org/api/iterator"
|
||||
"google.golang.org/api/option"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
type GCSStorage struct {
|
||||
@@ -31,7 +31,6 @@ type GCSStorage struct {
|
||||
|
||||
numberOfThreads int
|
||||
TestMode bool
|
||||
|
||||
}
|
||||
|
||||
type GCSConfig struct {
|
||||
@@ -149,7 +148,6 @@ func (storage *GCSStorage) shouldRetry(backoff *int, err error) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
||||
// ListFiles return the list of files and subdirectories under 'dir' (non-recursively)
|
||||
func (storage *GCSStorage) ListFiles(threadIndex int, dir string) ([]string, []int64, error) {
|
||||
for len(dir) > 0 && dir[len(dir)-1] == '/' {
|
||||
@@ -288,16 +286,16 @@ func (storage *GCSStorage) UploadFile(threadIndex int, filePath string, content
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *GCSStorage) IsCacheNeeded() (bool) { return true }
|
||||
func (storage *GCSStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *GCSStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *GCSStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *GCSStorage) IsStrongConsistent() (bool) { return true }
|
||||
func (storage *GCSStorage) IsStrongConsistent() bool { return true }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *GCSStorage) IsFastListing() (bool) { return true }
|
||||
func (storage *GCSStorage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *GCSStorage) EnableTestMode() { storage.TestMode = true }
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
"sync"
|
||||
"bytes"
|
||||
"strings"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
net_url "net/url"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
@@ -436,7 +436,7 @@ func (client *HubicClient) MoveFile(from string, to string) error {
|
||||
return client.DeleteFile(from)
|
||||
}
|
||||
|
||||
func (client *HubicClient) CreateDirectory(path string) (error) {
|
||||
func (client *HubicClient) CreateDirectory(path string) error {
|
||||
|
||||
for len(path) > 0 && path[len(path)-1] == '/' {
|
||||
path = path[:len(path)-1]
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"fmt"
|
||||
"testing"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
crypto_rand "crypto/rand"
|
||||
"math/rand"
|
||||
|
||||
@@ -190,16 +190,16 @@ func (storage *HubicStorage) UploadFile(threadIndex int, filePath string, conten
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *HubicStorage) IsCacheNeeded() (bool) { return true }
|
||||
func (storage *HubicStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *HubicStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *HubicStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *HubicStorage) IsStrongConsistent() (bool) { return false }
|
||||
func (storage *HubicStorage) IsStrongConsistent() bool { return false }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *HubicStorage) IsFastListing() (bool) { return true }
|
||||
func (storage *HubicStorage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *HubicStorage) EnableTestMode() {
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
var keyringFile string
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"time"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"testing"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"sync"
|
||||
"bytes"
|
||||
"strings"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
@@ -167,7 +167,7 @@ func (client *OneDriveClient) call(url string, method string, input interface{},
|
||||
continue
|
||||
} else {
|
||||
if err := json.NewDecoder(response.Body).Decode(errorResponse); err != nil {
|
||||
return nil, 0, OneDriveError { Status: response.StatusCode, Message: fmt.Sprintf("Unexpected response"), }
|
||||
return nil, 0, OneDriveError{Status: response.StatusCode, Message: fmt.Sprintf("Unexpected response")}
|
||||
}
|
||||
|
||||
errorResponse.Error.Status = response.StatusCode
|
||||
@@ -340,7 +340,7 @@ func (client *OneDriveClient) MoveFile(path string, parent string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *OneDriveClient) CreateDirectory(path string, name string) (error) {
|
||||
func (client *OneDriveClient) CreateDirectory(path string, name string) error {
|
||||
|
||||
url := OneDriveAPIURL + "/root/children"
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"fmt"
|
||||
"testing"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
crypto_rand "crypto/rand"
|
||||
"math/rand"
|
||||
@@ -30,7 +30,6 @@ func TestOneDriveClient(t *testing.T) {
|
||||
fmt.Printf("name: %s, isDir: %t\n", file.Name, len(file.Folder) != 0)
|
||||
}
|
||||
|
||||
|
||||
testID, _, _, err := oneDriveClient.GetFileInfo("test")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to list the test directory: %v", err)
|
||||
|
||||
@@ -225,16 +225,16 @@ func (storage *OneDriveStorage) UploadFile(threadIndex int, filePath string, con
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *OneDriveStorage) IsCacheNeeded() (bool) { return true }
|
||||
func (storage *OneDriveStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *OneDriveStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *OneDriveStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *OneDriveStorage) IsStrongConsistent() (bool) { return false }
|
||||
func (storage *OneDriveStorage) IsStrongConsistent() bool { return false }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *OneDriveStorage) IsFastListing() (bool) { return true }
|
||||
func (storage *OneDriveStorage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *OneDriveStorage) EnableTestMode() {
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"encoding/json"
|
||||
"path"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Preference stores options for each storage.
|
||||
@@ -91,7 +91,7 @@ func SetDuplicacyPreferencePath(p string) {
|
||||
preferencePath = p
|
||||
}
|
||||
|
||||
func SavePreferences() (bool) {
|
||||
func SavePreferences() bool {
|
||||
description, err := json.MarshalIndent(Preferences, "", " ")
|
||||
if err != nil {
|
||||
LOG_ERROR("PREFERENCE_MARSHAL", "Failed to marshal the repository preferences: %v", err)
|
||||
@@ -108,7 +108,7 @@ func SavePreferences() (bool) {
|
||||
return true
|
||||
}
|
||||
|
||||
func FindPreference(name string) (*Preference) {
|
||||
func FindPreference(name string) *Preference {
|
||||
for i, preference := range Preferences {
|
||||
if preference.Name == name || preference.StorageURL == name {
|
||||
return &Preferences[i]
|
||||
|
||||
@@ -6,6 +6,7 @@ package duplicacy
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gilbertchen/goamz/aws"
|
||||
"github.com/gilbertchen/goamz/s3"
|
||||
)
|
||||
@@ -197,16 +198,16 @@ func (storage *S3CStorage) UploadFile(threadIndex int, filePath string, content
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *S3CStorage) IsCacheNeeded () (bool) { return true }
|
||||
func (storage *S3CStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *S3CStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *S3CStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *S3CStorage) IsStrongConsistent() (bool) { return false }
|
||||
func (storage *S3CStorage) IsStrongConsistent() bool { return false }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *S3CStorage) IsFastListing() (bool) { return true }
|
||||
func (storage *S3CStorage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *S3CStorage) EnableTestMode() {}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
@@ -255,16 +255,16 @@ func (storage *S3Storage) UploadFile(threadIndex int, filePath string, content [
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *S3Storage) IsCacheNeeded () (bool) { return true }
|
||||
func (storage *S3Storage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *S3Storage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *S3Storage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *S3Storage) IsStrongConsistent() (bool) { return false }
|
||||
func (storage *S3Storage) IsStrongConsistent() bool { return false }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *S3Storage) IsFastListing() (bool) { return true }
|
||||
func (storage *S3Storage) IsFastListing() bool { return true }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *S3Storage) EnableTestMode() {}
|
||||
|
||||
@@ -7,15 +7,15 @@ package duplicacy
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"net"
|
||||
"path"
|
||||
"time"
|
||||
"runtime"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"github.com/pkg/sftp"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
type SFTPStorage struct {
|
||||
@@ -31,7 +31,6 @@ func CreateSFTPStorageWithPassword(server string, port int, username string, sto
|
||||
|
||||
authMethods := []ssh.AuthMethod{ssh.Password(password)}
|
||||
|
||||
|
||||
hostKeyCallback := func(hostname string, remote net.Addr,
|
||||
key ssh.PublicKey) error {
|
||||
return nil
|
||||
@@ -294,16 +293,16 @@ func (storage *SFTPStorage) UploadFile(threadIndex int, filePath string, content
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
func (storage *SFTPStorage) IsCacheNeeded () (bool) { return true }
|
||||
func (storage *SFTPStorage) IsCacheNeeded() bool { return true }
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
func (storage *SFTPStorage) IsMoveFileImplemented() (bool) { return true }
|
||||
func (storage *SFTPStorage) IsMoveFileImplemented() bool { return true }
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
func (storage *SFTPStorage) IsStrongConsistent() (bool) { return true }
|
||||
func (storage *SFTPStorage) IsStrongConsistent() bool { return true }
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
func (storage *SFTPStorage) IsFastListing() (bool) { return false }
|
||||
func (storage *SFTPStorage) IsFastListing() bool { return false }
|
||||
|
||||
// Enable the test mode.
|
||||
func (storage *SFTPStorage) EnableTestMode() {}
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
"unsafe"
|
||||
"time"
|
||||
"os"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
ole "github.com/gilbertchen/go-ole"
|
||||
)
|
||||
@@ -77,7 +77,6 @@ func getIVSSAsync(unknown *ole.IUnknown, iid *ole.GUID) (async *IVSSAsync) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
//665c1d5f-c218-414d-a05d-7fef5f9d5c86
|
||||
var IID_IVSS = &ole.GUID{0x665c1d5f, 0xc218, 0x414d, [8]byte{0xa0, 0x5d, 0x7f, 0xef, 0x5f, 0x9d, 0x5c, 0x86}}
|
||||
|
||||
@@ -238,7 +237,7 @@ type SnapshotProperties struct {
|
||||
Status int
|
||||
}
|
||||
|
||||
func (vss *IVSS) GetSnapshotProperties(snapshotSetID ole.GUID, properties *SnapshotProperties) (int) {
|
||||
func (vss *IVSS) GetSnapshotProperties(snapshotSetID ole.GUID, properties *SnapshotProperties) int {
|
||||
var ret uintptr
|
||||
if runtime.GOARCH == "386" {
|
||||
address := uint(uintptr(unsafe.Pointer(&snapshotSetID)))
|
||||
@@ -292,8 +291,7 @@ func (vss *IVSS) DeleteSnapshots(snapshotID ole.GUID) (int, int, ole.GUID) {
|
||||
return int(ret), int(deleted), deletedGUID
|
||||
}
|
||||
|
||||
|
||||
func uint16ArrayToString(p *uint16) (string) {
|
||||
func uint16ArrayToString(p *uint16) string {
|
||||
if p == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -481,9 +479,7 @@ func CreateShadowCopy(top string, shadowCopy bool) (shadowTop string) {
|
||||
}
|
||||
async.Release()
|
||||
|
||||
|
||||
properties := SnapshotProperties {
|
||||
}
|
||||
properties := SnapshotProperties{}
|
||||
|
||||
ret = vssBackupComponent.GetSnapshotProperties(snapshotID, &properties)
|
||||
if ret != 0 {
|
||||
@@ -521,5 +517,3 @@ func CreateShadowCopy(top string, shadowCopy bool) (shadowTop string) {
|
||||
return shadowLink + "\\" + top[2:]
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"time"
|
||||
"path"
|
||||
"strings"
|
||||
"strconv"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Snapshot represents a backup of the repository.
|
||||
@@ -409,7 +409,7 @@ func (snapshot *Snapshot) SetSequence(sequenceType string, sequence [] string) {
|
||||
}
|
||||
|
||||
// encodeSequence turns a sequence of binary hashes into a sequence of hex hashes.
|
||||
func encodeSequence(sequence[] string) ([] string) {
|
||||
func encodeSequence(sequence []string) []string {
|
||||
|
||||
sequenceInHex := make([]string, len(sequence))
|
||||
|
||||
@@ -419,5 +419,3 @@ func encodeSequence(sequence[] string) ([] string) {
|
||||
|
||||
return sequenceInHex
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"fmt"
|
||||
"text/tabwriter"
|
||||
"sort"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
"time"
|
||||
"math"
|
||||
"path"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/aryann/difflib"
|
||||
)
|
||||
@@ -174,7 +174,6 @@ type SnapshotManager struct {
|
||||
snapshotCache *FileStorage
|
||||
|
||||
chunkDownloader *ChunkDownloader
|
||||
|
||||
}
|
||||
|
||||
// CreateSnapshotManager creates a snapshot manager
|
||||
@@ -234,7 +233,7 @@ type sequenceReader struct {
|
||||
sequence []string
|
||||
buffer *bytes.Buffer
|
||||
index int
|
||||
refillFunc func(hash string) ([]byte)
|
||||
refillFunc func(hash string) []byte
|
||||
}
|
||||
|
||||
// Read reads a new chunk using the refill function when there is no more data in the buffer
|
||||
@@ -277,7 +276,7 @@ func (manager *SnapshotManager) DownloadSnapshotFileSequence(snapshot *Snapshot,
|
||||
reader := sequenceReader{
|
||||
sequence: snapshot.FileSequence,
|
||||
buffer: new(bytes.Buffer),
|
||||
refillFunc: func (chunkHash string) ([]byte) {
|
||||
refillFunc: func(chunkHash string) []byte {
|
||||
i := manager.chunkDownloader.AddChunk(chunkHash)
|
||||
chunk := manager.chunkDownloader.WaitForChunk(i)
|
||||
return chunk.GetBytes()
|
||||
@@ -315,7 +314,6 @@ func (manager *SnapshotManager) DownloadSnapshotFileSequence(snapshot *Snapshot,
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
// DownloadSnapshotSequence downloads the content represented by a sequence of chunks, and then unmarshal the content
|
||||
// using the specified 'loadFunction'. It purpose is to decode the chunk sequences representing chunk hashes or chunk lengths
|
||||
// in a snapshot.
|
||||
@@ -331,7 +329,6 @@ func (manager *SnapshotManager) DownloadSnapshotSequence(snapshot *Snapshot, seq
|
||||
|
||||
content := manager.DownloadSequence(sequence)
|
||||
|
||||
|
||||
if len(content) == 0 {
|
||||
LOG_ERROR("SNAPSHOT_PARSE", "Failed to load %s specified in the snapshot %s at revision %d",
|
||||
sequenceType, snapshot.ID, snapshot.Revision)
|
||||
@@ -799,7 +796,6 @@ func (manager *SnapshotManager) CheckSnapshots(snapshotID string, revisionsToChe
|
||||
snapshotMap[snapshotID] = nil
|
||||
}
|
||||
|
||||
|
||||
snapshotIDIndex := 0
|
||||
for snapshotID, _ = range snapshotMap {
|
||||
|
||||
@@ -1127,7 +1123,7 @@ func (manager *SnapshotManager) VerifySnapshot(snapshot *Snapshot) bool {
|
||||
}
|
||||
|
||||
// RetrieveFile retrieve the file in the specifed snapshot.
|
||||
func (manager *SnapshotManager) RetrieveFile(snapshot *Snapshot, file *Entry, output func([]byte)()) bool {
|
||||
func (manager *SnapshotManager) RetrieveFile(snapshot *Snapshot, file *Entry, output func([]byte)) bool {
|
||||
|
||||
if file.Size == 0 {
|
||||
return true
|
||||
@@ -1181,7 +1177,7 @@ func (manager *SnapshotManager) RetrieveFile(snapshot *Snapshot, file *Entry, ou
|
||||
}
|
||||
|
||||
// FindFile returns the file entry that has the given file name.
|
||||
func (manager *SnapshotManager) FindFile(snapshot *Snapshot, filePath string, suppressError bool) (*Entry) {
|
||||
func (manager *SnapshotManager) FindFile(snapshot *Snapshot, filePath string, suppressError bool) *Entry {
|
||||
for _, entry := range snapshot.Files {
|
||||
if entry.Path == filePath {
|
||||
return entry
|
||||
@@ -1280,7 +1276,6 @@ func (manager *SnapshotManager) Diff(top string, snapshotID string, revisions []
|
||||
leftSnapshot = manager.DownloadSnapshot(snapshotID, revisions[0])
|
||||
}
|
||||
|
||||
|
||||
if len(filePath) > 0 {
|
||||
|
||||
manager.DownloadSnapshotContents(leftSnapshot, nil)
|
||||
@@ -1486,7 +1481,6 @@ func (manager *SnapshotManager) ShowHistory(top string, snapshotID string, revis
|
||||
LOG_INFO("SNAPSHOT_HISTORY", "%7d:", revision)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
stat, err := os.Stat(joinPath(top, filePath))
|
||||
@@ -1512,7 +1506,7 @@ func (manager *SnapshotManager) ShowHistory(top string, snapshotID string, revis
|
||||
|
||||
// fossilizeChunk turns the chunk into a fossil.
|
||||
func (manager *SnapshotManager) fossilizeChunk(chunkID string, filePath string,
|
||||
exclusive bool, collection *FossilCollection) (bool) {
|
||||
exclusive bool, collection *FossilCollection) bool {
|
||||
if exclusive {
|
||||
err := manager.storage.DeleteFile(0, filePath)
|
||||
if err != nil {
|
||||
@@ -1548,7 +1542,7 @@ func (manager *SnapshotManager) fossilizeChunk(chunkID string, filePath string,
|
||||
}
|
||||
|
||||
// resurrectChunk turns the fossil back into a chunk
|
||||
func (manager *SnapshotManager) resurrectChunk(fossilPath string, chunkID string) (bool) {
|
||||
func (manager *SnapshotManager) resurrectChunk(fossilPath string, chunkID string) bool {
|
||||
chunkPath, exist, _, err := manager.storage.FindChunk(0, chunkID, false)
|
||||
if err != nil {
|
||||
LOG_ERROR("CHUNK_FIND", "Failed to locate the path for the chunk %s: %v", chunkID, err)
|
||||
@@ -1571,8 +1565,6 @@ func (manager *SnapshotManager) resurrectChunk(fossilPath string, chunkID string
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
|
||||
// PruneSnapshots deletes snapshots by revisions, tags, or a retention policy. The main idea is two-step
|
||||
// fossil collection.
|
||||
// 1. Delete snapshots specified by revision, retention policy, with a tag. Find any resulting unreferenced
|
||||
@@ -2113,7 +2105,6 @@ func (manager *SnapshotManager) PruneSnapshots(selfID string, snapshotID string,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Save the fossil collection if it is not empty.
|
||||
@@ -2181,7 +2172,6 @@ func (manager *SnapshotManager) PruneSnapshots(selfID string, snapshotID string,
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
// CheckSnapshot performs sanity checks on the given snapshot.
|
||||
func (manager *SnapshotManager) CheckSnapshot(snapshot *Snapshot) (err error) {
|
||||
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"os"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func createDummySnapshot(snapshotID string, revision int, endTime int64) *Snapshot {
|
||||
|
||||
@@ -6,14 +6,14 @@ package duplicacy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"strconv"
|
||||
"os"
|
||||
"net"
|
||||
"path"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
@@ -47,16 +47,16 @@ type Storage interface {
|
||||
|
||||
// If a local snapshot cache is needed for the storage to avoid downloading/uploading chunks too often when
|
||||
// managing snapshots.
|
||||
IsCacheNeeded() (bool)
|
||||
IsCacheNeeded() bool
|
||||
|
||||
// If the 'MoveFile' method is implemented.
|
||||
IsMoveFileImplemented() (bool)
|
||||
IsMoveFileImplemented() bool
|
||||
|
||||
// If the storage can guarantee strong consistency.
|
||||
IsStrongConsistent() (bool)
|
||||
IsStrongConsistent() bool
|
||||
|
||||
// If the storage supports fast listing of files names.
|
||||
IsFastListing() (bool)
|
||||
IsFastListing() bool
|
||||
|
||||
// Enable the test mode.
|
||||
EnableTestMode()
|
||||
@@ -274,8 +274,7 @@ func CreateStorage(preference Preference, resetPassword bool, threads int) (stor
|
||||
|
||||
}
|
||||
|
||||
authMethods := [] ssh.AuthMethod {
|
||||
}
|
||||
authMethods := []ssh.AuthMethod{}
|
||||
passwordAuthMethods := []ssh.AuthMethod{
|
||||
ssh.PasswordCallback(passwordCallback),
|
||||
ssh.KeyboardInteractive(keyboardInteractive),
|
||||
|
||||
@@ -5,19 +5,19 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"time"
|
||||
"flag"
|
||||
"path"
|
||||
"testing"
|
||||
"strings"
|
||||
"strconv"
|
||||
"io/ioutil"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
crypto_rand "crypto/rand"
|
||||
"math/rand"
|
||||
@@ -396,7 +396,6 @@ func TestStorage(t *testing.T) {
|
||||
|
||||
chunk := CreateChunk(config, true)
|
||||
|
||||
|
||||
for _, chunkID := range chunks {
|
||||
|
||||
chunk.Reset(false)
|
||||
|
||||
@@ -5,21 +5,21 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"bufio"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"strconv"
|
||||
"runtime"
|
||||
"crypto/sha256"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"github.com/gilbertchen/gopass"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
)
|
||||
|
||||
var RunInBackground bool = false
|
||||
@@ -41,7 +41,7 @@ func init() {
|
||||
|
||||
}
|
||||
|
||||
func CreateRateLimitedReader(content []byte, rate int) (*RateLimitedReader) {
|
||||
func CreateRateLimitedReader(content []byte, rate int) *RateLimitedReader {
|
||||
return &RateLimitedReader{
|
||||
Content: content,
|
||||
Rate: float64(rate * 1024),
|
||||
@@ -84,7 +84,7 @@ func IsValidRegex(pattern string) (valid bool, err error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (reader *RateLimitedReader) Length() (int64) {
|
||||
func (reader *RateLimitedReader) Length() int64 {
|
||||
return int64(len(reader.Content))
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ func GenerateKeyFromPassword(password string) []byte {
|
||||
}
|
||||
|
||||
// Get password from preference, env, but don't start any keyring request
|
||||
func GetPasswordFromPreference(preference Preference, passwordType string) (string) {
|
||||
func GetPasswordFromPreference(preference Preference, passwordType string) string {
|
||||
passwordID := passwordType
|
||||
if preference.Name != "default" {
|
||||
passwordID = preference.Name + "_" + passwordID
|
||||
@@ -196,7 +196,7 @@ func GetPasswordFromPreference(preference Preference, passwordType string) (stri
|
||||
|
||||
// GetPassword attempts to get the password from KeyChain/KeyRing, environment variables, or keyboard input.
|
||||
func GetPassword(preference Preference, passwordType string, prompt string,
|
||||
showPassword bool, resetPassword bool) (string) {
|
||||
showPassword bool, resetPassword bool) string {
|
||||
passwordID := passwordType
|
||||
password := GetPasswordFromPreference(preference, passwordType)
|
||||
if password != "" {
|
||||
@@ -386,7 +386,7 @@ func joinPath(components ...string) string {
|
||||
return combinedPath
|
||||
}
|
||||
|
||||
func PrettyNumber(number int64) (string) {
|
||||
func PrettyNumber(number int64) string {
|
||||
|
||||
G := int64(1024 * 1024 * 1024)
|
||||
M := int64(1024 * 1024)
|
||||
@@ -405,7 +405,7 @@ func PrettyNumber(number int64) (string) {
|
||||
}
|
||||
}
|
||||
|
||||
func PrettySize(size int64) (string) {
|
||||
func PrettySize(size int64) string {
|
||||
if size > 1024*1024 {
|
||||
return fmt.Sprintf("%.2fM", float64(size)/(1024.0*1024.0))
|
||||
} else if size > 1024 {
|
||||
@@ -415,7 +415,7 @@ func PrettySize(size int64) (string) {
|
||||
}
|
||||
}
|
||||
|
||||
func PrettyTime(seconds int64) (string) {
|
||||
func PrettyTime(seconds int64) string {
|
||||
|
||||
day := int64(3600 * 24)
|
||||
|
||||
@@ -431,7 +431,7 @@ func PrettyTime(seconds int64) (string) {
|
||||
}
|
||||
}
|
||||
|
||||
func AtoSize(sizeString string) (int) {
|
||||
func AtoSize(sizeString string) int {
|
||||
sizeString = strings.ToLower(sizeString)
|
||||
|
||||
sizeRegex := regexp.MustCompile(`^([0-9]+)([mk])?$`)
|
||||
@@ -451,7 +451,7 @@ func AtoSize(sizeString string) (int) {
|
||||
return size
|
||||
}
|
||||
|
||||
func MinInt(x, y int) (int) {
|
||||
func MinInt(x, y int) int {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"bytes"
|
||||
"syscall"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/gilbertchen/xattr"
|
||||
)
|
||||
@@ -31,7 +31,7 @@ func GetOwner(entry *Entry, fileInfo *os.FileInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
func SetOwner(fullPath string, entry *Entry, fileInfo *os.FileInfo) (bool) {
|
||||
func SetOwner(fullPath string, entry *Entry, fileInfo *os.FileInfo) bool {
|
||||
stat, ok := (*fileInfo).Sys().(*syscall.Stat_t)
|
||||
if ok && stat != nil && (int(stat.Uid) != entry.UID || int(stat.Gid) != entry.GID) {
|
||||
if entry.UID != -1 && entry.GID != -1 {
|
||||
|
||||
@@ -5,15 +5,14 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
"bytes"
|
||||
|
||||
crypto_rand "crypto/rand"
|
||||
|
||||
"testing"
|
||||
|
||||
)
|
||||
|
||||
func TestMatchPattern(t *testing.T) {
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
package duplicacy
|
||||
|
||||
import (
|
||||
"os"
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -36,6 +36,7 @@ type reparseDataBuffer struct {
|
||||
// GenericReparseBuffer
|
||||
reparseBuffer byte
|
||||
}
|
||||
|
||||
const (
|
||||
FSCTL_GET_REPARSE_POINT = 0x900A8
|
||||
MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024
|
||||
@@ -103,7 +104,7 @@ func GetOwner(entry *Entry, fileInfo *os.FileInfo) {
|
||||
entry.GID = -1
|
||||
}
|
||||
|
||||
func SetOwner(fullPath string, entry *Entry, fileInfo *os.FileInfo) (bool) {
|
||||
func SetOwner(fullPath string, entry *Entry, fileInfo *os.FileInfo) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user