Version 1.0.0
This commit is contained in:
parent
cd58325ee3
commit
4b7701ea0d
14
Main.go
14
Main.go
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/SommerEngineering/Sync/Sync"
|
"github.com/SommerEngineering/Sync/Sync"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,6 +26,17 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if local dir exist
|
||||||
|
if dirInfo, dirError := os.Stat(localDir); dirError != nil {
|
||||||
|
log.Println("There is an error with the local directory: " + dirError.Error())
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if !dirInfo.IsDir() {
|
||||||
|
log.Println("There is an error with the local directory: You provided a file instead!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the password was provided:
|
// Check if the password was provided:
|
||||||
for true {
|
for true {
|
||||||
if password == `` {
|
if password == `` {
|
||||||
@ -55,4 +67,6 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
defer ssh.Close()
|
defer ssh.Close()
|
||||||
|
Sync.Synchronise(ssh, supervised, localDir, remoteDir)
|
||||||
|
log.Println("Synchronising done.")
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,20 @@
|
|||||||
package Sync
|
package Sync
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/pkg/sftp"
|
"github.com/pkg/sftp"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
test string = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
func Synchronise(ssh *ssh.Client, supervised bool, localDir, remoteDir string) {
|
func Synchronise(ssh *ssh.Client, supervised bool, localDir, remoteDir string) {
|
||||||
@ -27,13 +39,11 @@ func Synchronise(ssh *ssh.Client, supervised bool, localDir, remoteDir string) {
|
|||||||
remotely, because your remotely files are newer that these files.
|
remotely, because your remotely files are newer that these files.
|
||||||
- delete these local files! (may ask the user)
|
- delete these local files! (may ask the user)
|
||||||
- Download any new files
|
- Download any new files
|
||||||
- Are remote files present, which are locally not present
|
- Are remote files present, which are locally not present?
|
||||||
and these remote files are newer than ndl?
|
|
||||||
- Meaning: These files are new to the local side
|
- Meaning: These files are new to the local side
|
||||||
- Download these files! (may ask the user)
|
- Download these files! (may ask the user)
|
||||||
- Upload any new files
|
- Upload any new files
|
||||||
- Are local files present, which are remotely not present
|
- Are local files present, which are remotely not present?
|
||||||
and these local files are newer than ndr?
|
|
||||||
- Meaning: These files are new to the remote side
|
- Meaning: These files are new to the remote side
|
||||||
- Upload these files! (may ask the user)
|
- Upload these files! (may ask the user)
|
||||||
- Changed remote files
|
- Changed remote files
|
||||||
@ -45,4 +55,538 @@ func Synchronise(ssh *ssh.Client, supervised bool, localDir, remoteDir string) {
|
|||||||
- Meaning: These files are changed on the local side
|
- Meaning: These files are changed on the local side
|
||||||
- Upload these files and replace the remote copies (may ask the user)
|
- Upload these files and replace the remote copies (may ask the user)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read the local files ============================================================================================
|
||||||
|
//
|
||||||
|
log.Println("Try to read all local files now...")
|
||||||
|
localFiles = make(map[string]os.FileInfo)
|
||||||
|
filepath.Walk(localDir, walkerlocal)
|
||||||
|
log.Printf("Found %d local files.\n", len(localFiles))
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read the remote files ============================================================================================
|
||||||
|
//
|
||||||
|
log.Println("Try to read all remote files now...")
|
||||||
|
remoteFiles = make(map[string]os.FileInfo)
|
||||||
|
|
||||||
|
sftp, sftpError := sftp.NewClient(ssh)
|
||||||
|
if sftpError != nil {
|
||||||
|
log.Println("Was not able to connect to the server: " + sftpError.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer sftp.Close()
|
||||||
|
|
||||||
|
counterRemoteFile := 0
|
||||||
|
walker := sftp.Walk(remoteDir)
|
||||||
|
for walker.Step() {
|
||||||
|
counterRemoteFile++
|
||||||
|
if walker.Err() != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteFiles[walker.Path()] = walker.Stat()
|
||||||
|
if counterRemoteFile%512 == 0 {
|
||||||
|
fmt.Printf("%05d.\n", counterRemoteFile)
|
||||||
|
} else if counterRemoteFile%16 == 0 {
|
||||||
|
fmt.Printf("%05d.", counterRemoteFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println()
|
||||||
|
log.Printf("Found %d remote files.\n", len(remoteFiles))
|
||||||
|
|
||||||
|
//
|
||||||
|
// Normalise all local paths ============================================================================================
|
||||||
|
//
|
||||||
|
localFilesNormalised = make(map[string]os.FileInfo)
|
||||||
|
for key, value := range localFiles {
|
||||||
|
normalised := normalisePath(localDir, key)
|
||||||
|
if normalised != `` {
|
||||||
|
localFilesNormalised[normalised] = value
|
||||||
|
normalised2localFiles[normalised] = key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Normalise all remote paths ============================================================================================
|
||||||
|
//
|
||||||
|
remoteFilesNormalised = make(map[string]os.FileInfo)
|
||||||
|
for key, value := range remoteFiles {
|
||||||
|
normalised := normalisePath(remoteDir, key)
|
||||||
|
if normalised != `` {
|
||||||
|
remoteFilesNormalised[normalised] = value
|
||||||
|
normalised2remoteFiles[normalised] = key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Determine ndl and ndr ============================================================================================
|
||||||
|
//
|
||||||
|
ndl := time.Date(1, time.January, 1, 1, 1, 1, 1, time.UTC)
|
||||||
|
ndr := ndl
|
||||||
|
for _, remoteFileInfo := range remoteFiles {
|
||||||
|
if remoteFileInfo.ModTime().UTC().After(ndr) {
|
||||||
|
ndr = remoteFileInfo.ModTime().UTC()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, localFileInfo := range localFiles {
|
||||||
|
if localFileInfo.ModTime().UTC().After(ndl) {
|
||||||
|
ndl = localFileInfo.ModTime().UTC()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("The newest local file's time: %v\n", ndl)
|
||||||
|
log.Printf("The newest remote file's time: %v\n", ndr)
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free remote space ============================================================================================
|
||||||
|
//
|
||||||
|
deleteRemoteFiles := make([]string, 0)
|
||||||
|
for remoteFileNormalised, remoteFileInfo := range remoteFilesNormalised {
|
||||||
|
localFileNormaliesed := localFilesNormalised[remoteFileNormalised]
|
||||||
|
if localFileNormaliesed == nil {
|
||||||
|
if remoteFileInfo.ModTime().UTC().Before(ndl) {
|
||||||
|
deleteRemoteFiles = append(deleteRemoteFiles, remoteFileNormalised)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Found %d remote files to delete.\n", len(deleteRemoteFiles))
|
||||||
|
|
||||||
|
if len(deleteRemoteFiles) > 0 {
|
||||||
|
sort.Strings(deleteRemoteFiles)
|
||||||
|
shouldDeleteRemoteFiles := true
|
||||||
|
if supervised {
|
||||||
|
fmt.Println(`=================================================================`)
|
||||||
|
for _, file := range deleteRemoteFiles {
|
||||||
|
fmt.Println(normalised2remoteFiles[file])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("Should I delete these remote files? <y|n> ")
|
||||||
|
shouldDeleteRemoteFiles = readYesNoAnswer(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldDeleteRemoteFiles {
|
||||||
|
// 1. Remove all files
|
||||||
|
for _, remoteFileNormalised := range deleteRemoteFiles {
|
||||||
|
|
||||||
|
// Skip all directories:
|
||||||
|
if remoteFilesNormalised[remoteFileNormalised].IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
removeError := sftp.Remove(normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
if removeError != nil {
|
||||||
|
log.Printf("Was not able to delete the remote file %s: %s\n", normalised2remoteFiles[remoteFileNormalised], removeError.Error())
|
||||||
|
} else {
|
||||||
|
log.Printf("Deleted the remote file %s\n", normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Remove all directories
|
||||||
|
for _, remoteFileNormalised := range deleteRemoteFiles {
|
||||||
|
|
||||||
|
// Skip all files:
|
||||||
|
if !remoteFilesNormalised[remoteFileNormalised].IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Does not work: File an issue!
|
||||||
|
removeError := sftp.Remove(normalised2remoteFiles[remoteFileNormalised] + `/`)
|
||||||
|
if removeError != nil {
|
||||||
|
log.Printf("Was not able to delete the remote directory %s: %s\n", normalised2remoteFiles[remoteFileNormalised], removeError.Error())
|
||||||
|
} else {
|
||||||
|
log.Printf("Deleted the remote directory %s\n", normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, remoteFileNormalised := range deleteRemoteFiles {
|
||||||
|
delete(remoteFiles, normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
delete(remoteFilesNormalised, remoteFileNormalised)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free local space ============================================================================================
|
||||||
|
//
|
||||||
|
deleteLocalFiles := make([]string, 0)
|
||||||
|
for localFileNormalised, localFileInfo := range localFilesNormalised {
|
||||||
|
remoteFileNormaliesed := remoteFilesNormalised[localFileNormalised]
|
||||||
|
if remoteFileNormaliesed == nil {
|
||||||
|
if localFileInfo.ModTime().UTC().Before(ndr) {
|
||||||
|
deleteLocalFiles = append(deleteLocalFiles, localFileNormalised)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Found %d local files to delete.\n", len(deleteLocalFiles))
|
||||||
|
|
||||||
|
if len(deleteLocalFiles) > 0 {
|
||||||
|
sort.Strings(deleteLocalFiles)
|
||||||
|
shouldDeleteLocalFiles := true
|
||||||
|
if supervised {
|
||||||
|
fmt.Println(`=================================================================`)
|
||||||
|
for _, file := range deleteLocalFiles {
|
||||||
|
fmt.Println(normalised2localFiles[file])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("Should I delete these local files? <y|n> ")
|
||||||
|
shouldDeleteLocalFiles = readYesNoAnswer(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldDeleteLocalFiles {
|
||||||
|
for _, localFileNormalised := range deleteLocalFiles {
|
||||||
|
|
||||||
|
// Skip all directories:
|
||||||
|
if localFilesNormalised[localFileNormalised].IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
removeError := os.Remove(normalised2localFiles[localFileNormalised])
|
||||||
|
if removeError != nil {
|
||||||
|
log.Printf("Was not able to delete the local file %s: %s\n", normalised2localFiles[localFileNormalised], removeError.Error())
|
||||||
|
} else {
|
||||||
|
log.Printf("Deleted the local file %s\n", normalised2localFiles[localFileNormalised])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, localFileNormalised := range deleteLocalFiles {
|
||||||
|
|
||||||
|
// Skip all files:
|
||||||
|
if !localFilesNormalised[localFileNormalised].IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
removeError := os.Remove(normalised2localFiles[localFileNormalised])
|
||||||
|
if removeError != nil {
|
||||||
|
log.Printf("Was not able to delete the local directory %s: %s\n", normalised2localFiles[localFileNormalised], removeError.Error())
|
||||||
|
} else {
|
||||||
|
log.Printf("Deleted the local directory %s\n", normalised2localFiles[localFileNormalised])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, localFileNormalised := range deleteLocalFiles {
|
||||||
|
delete(localFiles, normalised2localFiles[localFileNormalised])
|
||||||
|
delete(localFilesNormalised, localFileNormalised)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Download new files ============================================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
downloadRemoteFiles := make([]string, 0)
|
||||||
|
for remoteFileNormalised, _ := range remoteFilesNormalised {
|
||||||
|
localFileNormaliesed := localFilesNormalised[remoteFileNormalised]
|
||||||
|
if localFileNormaliesed == nil {
|
||||||
|
downloadRemoteFiles = append(downloadRemoteFiles, remoteFileNormalised)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Found %d new remote files to download.\n", len(downloadRemoteFiles))
|
||||||
|
|
||||||
|
if len(downloadRemoteFiles) > 0 {
|
||||||
|
sort.Strings(downloadRemoteFiles)
|
||||||
|
shouldDownloadRemoteFiles := true
|
||||||
|
if supervised {
|
||||||
|
fmt.Println(`=================================================================`)
|
||||||
|
for _, file := range downloadRemoteFiles {
|
||||||
|
fmt.Println(normalised2remoteFiles[file])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("Should I download these new remote files? <y|n> ")
|
||||||
|
shouldDownloadRemoteFiles = readYesNoAnswer(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldDownloadRemoteFiles {
|
||||||
|
|
||||||
|
// 1. Create all new directories
|
||||||
|
for _, remoteFileNormalised := range downloadRemoteFiles {
|
||||||
|
|
||||||
|
// Skip all files
|
||||||
|
if !remoteFilesNormalised[remoteFileNormalised].IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newLocalDir := filepath.Join(localDir, strings.Replace(normalised2remoteFiles[remoteFileNormalised], remoteDir, ``, 1))
|
||||||
|
log.Printf("Try to create the new local directory %s...\n", newLocalDir)
|
||||||
|
if mkdirError := os.MkdirAll(newLocalDir, os.ModeDir); mkdirError != nil {
|
||||||
|
log.Printf("Was not able to create the local directory %s: %s\n", newLocalDir, mkdirError.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. All new files
|
||||||
|
for _, remoteFileNormalised := range downloadRemoteFiles {
|
||||||
|
|
||||||
|
// Skip all directories
|
||||||
|
if remoteFilesNormalised[remoteFileNormalised].IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Try to download the new remote file %s...\n", normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
remoteFileHandle, remoteFileHandleError := sftp.Open(normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
if remoteFileHandleError != nil {
|
||||||
|
log.Printf("Was not able to open the remote file %s: %s\n", normalised2remoteFiles[remoteFileNormalised], remoteFileHandleError.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, filename := filepath.Split(normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
path, _ := filepath.Split(strings.Replace(normalised2remoteFiles[remoteFileNormalised], remoteDir, ``, 1))
|
||||||
|
newLocalFile := filepath.Join(localDir, path, filename)
|
||||||
|
localFileHandle, localFileHandleError := os.Create(newLocalFile)
|
||||||
|
if localFileHandleError != nil {
|
||||||
|
log.Printf("Was not able to create the local file %s: %s\n", newLocalFile, localFileHandleError.Error())
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, copyError := io.Copy(localFileHandle, remoteFileHandle)
|
||||||
|
if copyError != nil {
|
||||||
|
log.Printf("Was not able to download the new remote file %s to the local file %s: %s\n", normalised2remoteFiles[remoteFileNormalised], newLocalFile, copyError.Error())
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
localFileHandle.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
localFileHandle.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Upload new files ============================================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
uploadLocalFiles := make([]string, 0)
|
||||||
|
for localFileNormalised, _ := range localFilesNormalised {
|
||||||
|
remoteFileNormaliesed := remoteFilesNormalised[localFileNormalised]
|
||||||
|
if remoteFileNormaliesed == nil {
|
||||||
|
uploadLocalFiles = append(uploadLocalFiles, localFileNormalised)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Found %d new local files to upload.\n", len(uploadLocalFiles))
|
||||||
|
|
||||||
|
if len(uploadLocalFiles) > 0 {
|
||||||
|
sort.Strings(uploadLocalFiles)
|
||||||
|
shouldUploadLocalFiles := true
|
||||||
|
if supervised {
|
||||||
|
fmt.Println(`=================================================================`)
|
||||||
|
for _, file := range uploadLocalFiles {
|
||||||
|
fmt.Println(normalised2localFiles[file])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("Should I upload these local new files? <y|n> ")
|
||||||
|
shouldUploadLocalFiles = readYesNoAnswer(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldUploadLocalFiles {
|
||||||
|
|
||||||
|
// 1. Create new directories
|
||||||
|
for _, localFileNormalised := range uploadLocalFiles {
|
||||||
|
|
||||||
|
// Skip all files
|
||||||
|
if !localFilesNormalised[localFileNormalised].IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newRemoteDir := filepath.ToSlash(filepath.Join(remoteDir, strings.Replace(normalised2localFiles[localFileNormalised], localDir, ``, 1)))
|
||||||
|
log.Printf("Try to create the new remote directory %s...\n", newRemoteDir)
|
||||||
|
if mkdirError := sftp.Mkdir(newRemoteDir); mkdirError != nil {
|
||||||
|
log.Printf("Was not able to create the remote directory %s: %s\n", newRemoteDir, mkdirError.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. All new files
|
||||||
|
for _, localFileNormalised := range uploadLocalFiles {
|
||||||
|
|
||||||
|
// Skip all directories
|
||||||
|
if localFilesNormalised[localFileNormalised].IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Try to upload the new local file %s...\n", normalised2localFiles[localFileNormalised])
|
||||||
|
|
||||||
|
_, filename := filepath.Split(normalised2localFiles[localFileNormalised])
|
||||||
|
path, _ := filepath.Split(strings.Replace(normalised2localFiles[localFileNormalised], localDir, ``, 1))
|
||||||
|
newRemoteFile := filepath.ToSlash(filepath.Join(remoteDir, path, filename))
|
||||||
|
remoteFileHandle, remoteFileHandleError := sftp.Create(newRemoteFile)
|
||||||
|
if remoteFileHandleError != nil {
|
||||||
|
log.Printf("Was not able to create the remote file %s: %s\n", newRemoteFile, remoteFileHandleError.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
localFileHandle, localFileHandleError := os.Open(normalised2localFiles[localFileNormalised])
|
||||||
|
if localFileHandleError != nil {
|
||||||
|
log.Printf("Was not able to open the local file %s: %s\n", normalised2localFiles[localFileNormalised], localFileHandleError.Error())
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, copyError := io.Copy(remoteFileHandle, localFileHandle)
|
||||||
|
if copyError != nil {
|
||||||
|
log.Printf("Was not able to upload the new local file %s to the remote file %s: %s\n", normalised2localFiles[localFileNormalised], newRemoteFile, copyError.Error())
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
localFileHandle.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
localFileHandle.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Changed files on the remote side ============================================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
changedRemoteFiles := make([]string, 0)
|
||||||
|
for remoteFileNormalised, remoteFileInfo := range remoteFilesNormalised {
|
||||||
|
localFileNormaliesed := localFilesNormalised[remoteFileNormalised]
|
||||||
|
if localFileNormaliesed != nil && !localFileNormaliesed.IsDir() {
|
||||||
|
if remoteFileInfo.ModTime().UTC().After(localFileNormaliesed.ModTime().UTC()) {
|
||||||
|
changedRemoteFiles = append(changedRemoteFiles, remoteFileNormalised)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Found %d remote files which are changed.\n", len(changedRemoteFiles))
|
||||||
|
|
||||||
|
if len(changedRemoteFiles) > 0 {
|
||||||
|
sort.Strings(changedRemoteFiles)
|
||||||
|
shouldDownloadRemoteFiles := true
|
||||||
|
if supervised {
|
||||||
|
fmt.Println(`=================================================================`)
|
||||||
|
for _, file := range changedRemoteFiles {
|
||||||
|
fmt.Println(normalised2remoteFiles[file])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("Should I download these changed remote files? <y|n> ")
|
||||||
|
shouldDownloadRemoteFiles = readYesNoAnswer(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldDownloadRemoteFiles {
|
||||||
|
for _, remoteFileNormalised := range changedRemoteFiles {
|
||||||
|
log.Printf("Try to download the changed remote file %s...\n", normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
remoteFileHandle, remoteFileHandleError := sftp.Open(normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
if remoteFileHandleError != nil {
|
||||||
|
log.Printf("Was not able to open the remote file %s: %s\n", normalised2remoteFiles[remoteFileNormalised], remoteFileHandleError.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, filename := filepath.Split(normalised2remoteFiles[remoteFileNormalised])
|
||||||
|
path, _ := filepath.Split(strings.Replace(normalised2remoteFiles[remoteFileNormalised], remoteDir, ``, 1))
|
||||||
|
existingLocalFile := filepath.Join(localDir, path, filename)
|
||||||
|
localFileHandle, localFileHandleError := os.Create(existingLocalFile)
|
||||||
|
if localFileHandleError != nil {
|
||||||
|
log.Printf("Was not able to overwrite the local file %s: %s\n", existingLocalFile, localFileHandleError.Error())
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, copyError := io.Copy(localFileHandle, remoteFileHandle)
|
||||||
|
if copyError != nil {
|
||||||
|
log.Printf("Was not able to download the changed remote file %s to the local file %s: %s\n", normalised2remoteFiles[remoteFileNormalised], existingLocalFile, copyError.Error())
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
localFileHandle.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
localFileHandle.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Changed files on the local side ============================================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
changedLocalFiles := make([]string, 0)
|
||||||
|
for localFileNormalised, localFileInfo := range localFilesNormalised {
|
||||||
|
remoteFileNormaliesed := remoteFilesNormalised[localFileNormalised]
|
||||||
|
if remoteFileNormaliesed != nil && !remoteFileNormaliesed.IsDir() {
|
||||||
|
if localFileInfo.ModTime().UTC().After(remoteFileNormaliesed.ModTime().UTC()) {
|
||||||
|
changedLocalFiles = append(changedLocalFiles, localFileNormalised)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Found %d local files which are changed.\n", len(changedLocalFiles))
|
||||||
|
|
||||||
|
if len(changedLocalFiles) > 0 {
|
||||||
|
sort.Strings(changedLocalFiles)
|
||||||
|
shouldUploadLocalFiles := true
|
||||||
|
if supervised {
|
||||||
|
fmt.Println(`=================================================================`)
|
||||||
|
for _, file := range changedLocalFiles {
|
||||||
|
fmt.Println(normalised2localFiles[file])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Print("Should I upload these changed local files? <y|n> ")
|
||||||
|
shouldUploadLocalFiles = readYesNoAnswer(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if shouldUploadLocalFiles {
|
||||||
|
for _, localFileNormalised := range changedLocalFiles {
|
||||||
|
log.Printf("Try to upload the changed local file %s...\n", normalised2localFiles[localFileNormalised])
|
||||||
|
|
||||||
|
_, filename := filepath.Split(normalised2localFiles[localFileNormalised])
|
||||||
|
path, _ := filepath.Split(strings.Replace(normalised2localFiles[localFileNormalised], localDir, ``, 1))
|
||||||
|
existingRemoteFile := filepath.ToSlash(filepath.Join(remoteDir, path, filename))
|
||||||
|
remoteFileHandle, remoteFileHandleError := sftp.Create(existingRemoteFile)
|
||||||
|
if remoteFileHandleError != nil {
|
||||||
|
log.Printf("Was not able to overwrite the remote file %s: %s\n", existingRemoteFile, remoteFileHandleError.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
localFileHandle, localFileHandleError := os.Open(normalised2localFiles[localFileNormalised])
|
||||||
|
if localFileHandleError != nil {
|
||||||
|
log.Printf("Was not able to open the local file %s: %s\n", normalised2localFiles[localFileNormalised], localFileHandleError.Error())
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
_, copyError := io.Copy(remoteFileHandle, localFileHandle)
|
||||||
|
if copyError != nil {
|
||||||
|
log.Printf("Was not able to upload the changed local file %s to the remote file %s: %s\n", normalised2localFiles[localFileNormalised], existingRemoteFile, copyError.Error())
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
localFileHandle.Close()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteFileHandle.Close()
|
||||||
|
localFileHandle.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func walkerlocal(path string, info os.FileInfo, err error) error {
|
||||||
|
localFiles[path] = info
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readYesNoAnswer(defaultAnswer bool) bool { // true := yes
|
||||||
|
answer := ``
|
||||||
|
if _, scanError := fmt.Scan(&answer); scanError != nil {
|
||||||
|
return defaultAnswer
|
||||||
|
}
|
||||||
|
|
||||||
|
if answer == `` || answer == ` ` {
|
||||||
|
return defaultAnswer
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.ToLower(answer) == `y` {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
package Sync
|
package Sync
|
||||||
|
|
||||||
var (
|
import (
|
||||||
callbackPassword = ``
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
callbackPassword = ``
|
||||||
|
localFiles = make(map[string]os.FileInfo) // The local files with local separator
|
||||||
|
localFilesNormalised = make(map[string]os.FileInfo) // The local files with std separator i.e. / and removed base dir
|
||||||
|
normalised2localFiles = make(map[string]string) // Mapping from normalised local file to local file
|
||||||
|
remoteFiles = make(map[string]os.FileInfo) // The remote files with remote separator
|
||||||
|
remoteFilesNormalised = make(map[string]os.FileInfo) // The remote files with std separator i.e. / and removed base dir
|
||||||
|
normalised2remoteFiles = make(map[string]string) // Mapping from normalised remote file to remote file
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user