mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-09-02 07:07:26 -04:00
Map entries to mod times from the beginning
This commit is contained in:
@@ -50,4 +50,4 @@ func ReadConfig(readKeys []string, missingValueError string) []string {
|
|||||||
// sshPort = <remote ssh port>
|
// sshPort = <remote ssh port>
|
||||||
// sshIdentity = <ssh private key identity file path>
|
// sshIdentity = <ssh private key identity file path>
|
||||||
// netPinEnabled = <true/false>
|
// netPinEnabled = <true/false>
|
||||||
// deviceID = <device id> TODO remove from config file
|
// deviceID = <device id>
|
||||||
|
|||||||
+53
-37
@@ -10,6 +10,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// global constants used only in this file
|
||||||
|
const (
|
||||||
|
ansiUpload = "\033[38;5;4m"
|
||||||
|
ansiDownload = "\033[38;5;2m"
|
||||||
|
)
|
||||||
|
|
||||||
// getSSHOutput runs a command over SSH and returns the output
|
// getSSHOutput runs a command over SSH and returns the output
|
||||||
// currently only supports password-less key-based authentication TODO add password support, still require key
|
// currently only supports password-less key-based authentication TODO add password support, still require key
|
||||||
func getSSHOutput(cmd string, manualSync bool) string {
|
func getSSHOutput(cmd string, manualSync bool) string {
|
||||||
@@ -92,19 +98,19 @@ func getSSHOutput(cmd string, manualSync bool) string {
|
|||||||
return outputString
|
return outputString
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRemoteDataFromClient returns lists of remote entries, mod times, folders, and deletions (four separate lists)
|
// getRemoteDataFromClient returns a map of remote entries to their modification times, a list of remote folders, and a list of queued deletions
|
||||||
func getRemoteDataFromClient(manualSync bool) ([]string, []int64, []string, []string) {
|
func getRemoteDataFromClient(manualSync bool) (map[string]int64, []string, []string) {
|
||||||
// get remote output over SSH
|
// get remote output over SSH
|
||||||
output := getSSHOutput("libmuttonserver", manualSync)
|
output := getSSHOutput("libmuttonserver", manualSync)
|
||||||
|
|
||||||
// split output into slice based on occurrences of "\x1f"
|
// split output into slice based on occurrences of "\x1d"
|
||||||
outputSlice := strings.Split(output, "\x1f")
|
outputSlice := strings.Split(output, "\x1d")
|
||||||
|
|
||||||
// re-form the lists TODO handle error for index out of bounds (occurs if reading deletions directory on server fails)
|
// re-form the lists TODO handle error for index out of bounds (occurs if reading deletions directory on server fails)
|
||||||
entries := strings.Split(outputSlice[0], "\n")[1:]
|
entries := strings.Split(outputSlice[0], "\x1f")[1:]
|
||||||
modsStrings := strings.Split(outputSlice[1], "\n")[1:]
|
modsStrings := strings.Split(outputSlice[1], "\x1f")[1:]
|
||||||
folders := strings.Split(outputSlice[2], "\n")[2:]
|
folders := strings.Split(outputSlice[2], "\x1f")[1:]
|
||||||
deletions := strings.Split(outputSlice[3], "\n")[1:]
|
deletions := strings.Split(outputSlice[3], "\x1f")[1:]
|
||||||
|
|
||||||
// convert the mod times to int64
|
// convert the mod times to int64
|
||||||
var mods []int64
|
var mods []int64
|
||||||
@@ -113,49 +119,59 @@ func getRemoteDataFromClient(manualSync bool) ([]string, []int64, []string, []st
|
|||||||
mods = append(mods, mod)
|
mods = append(mods, mod)
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries, mods, folders, deletions
|
// map remote entries to their modification times
|
||||||
|
entryModMap := make(map[string]int64)
|
||||||
|
for i, entry := range entries {
|
||||||
|
entryModMap[entry] = mods[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return entryModMap, folders, deletions
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLocalData returns lists of local entries and mod times (two separate lists)
|
// getLocalData returns a map of local entries to their modification times
|
||||||
func getLocalData() ([]string, []int64) {
|
func getLocalData() map[string]int64 {
|
||||||
// get a list of all entries
|
// get a list of all entries
|
||||||
fileList, _ := WalkEntryDir()
|
entries, _ := WalkEntryDir()
|
||||||
|
|
||||||
// get a list of all entry modification times
|
// get a list of all entry modification times
|
||||||
modList := getModTimes(fileList)
|
modList := getModTimes(entries)
|
||||||
|
|
||||||
|
// map the entries to their modification times
|
||||||
|
entryModMap := make(map[string]int64)
|
||||||
|
for i, entry := range entries {
|
||||||
|
entryModMap[entry] = modList[i]
|
||||||
|
}
|
||||||
|
|
||||||
// return the lists
|
// return the lists
|
||||||
return fileList, modList
|
return entryModMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// syncLists syncs entries between the client and server based on modification times
|
// syncLists syncs entries between the client and server based on modification times
|
||||||
func syncLists(entries [2][]string, modTimes [2][]int64) {
|
// using maps means that syncing will be done in an arbitrary order, but it is a worthy tradeoff for speed and simplicity
|
||||||
// create a map of all server entries to their mod times
|
func syncLists(localEntryModMap, remoteEntryModMap map[string]int64) {
|
||||||
serverMap := make(map[string]int64)
|
|
||||||
for i, entry := range entries[1] {
|
|
||||||
serverMap[entry] = modTimes[1][i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate over client entries
|
// iterate over client entries
|
||||||
for i, entry := range entries[0] {
|
for entry, localModTime := range localEntryModMap {
|
||||||
// check if the entry is present in serverMap
|
// check if the entry is present in the server map
|
||||||
if serverModTime, present := serverMap[entry]; present {
|
if remoteModTime, present := remoteEntryModMap[entry]; present {
|
||||||
// entry exists on both client and server, compare mod times
|
// entry exists on both client and server, compare mod times
|
||||||
if serverModTime > modTimes[0][i] {
|
if remoteModTime > localModTime {
|
||||||
|
fmt.Println(ansiDownload+entry+backend.AnsiReset, "is newer on server, downloading...")
|
||||||
// TODO entry is newer on server, download
|
// TODO entry is newer on server, download
|
||||||
} else if serverModTime < modTimes[0][i] {
|
} else if remoteModTime < localModTime {
|
||||||
|
fmt.Println(ansiUpload+entry+backend.AnsiReset, "is newer on client, uploading...")
|
||||||
// TODO entry is newer on client, upload
|
// TODO entry is newer on client, upload
|
||||||
}
|
}
|
||||||
// remove entry from serverMap (process of elimination)
|
// remove entry from remoteEntryModMap (process of elimination)
|
||||||
delete(serverMap, entry)
|
delete(remoteEntryModMap, entry)
|
||||||
} else {
|
} else {
|
||||||
// TODO entry does not exist on sever, upload
|
fmt.Println(ansiUpload+entry+backend.AnsiReset, "does not exist on server, uploading...")
|
||||||
|
// TODO entry does not exist on server, upload
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate over remaining entries in serverMap
|
// iterate over remaining entries in remoteEntryModMap
|
||||||
for entry := range serverMap {
|
for entry := range remoteEntryModMap {
|
||||||
fmt.Println(entry) // TODO placeholder
|
fmt.Println(ansiDownload+entry+backend.AnsiReset, "does not exist on server, downloading...")
|
||||||
// TODO entry does not exist on client, download
|
// TODO entry does not exist on client, download
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,16 +179,16 @@ func syncLists(entries [2][]string, modTimes [2][]int64) {
|
|||||||
// RunJob runs the SSH sync job
|
// RunJob runs the SSH sync job
|
||||||
func RunJob(manualSync bool) {
|
func RunJob(manualSync bool) {
|
||||||
// fetch remote lists
|
// fetch remote lists
|
||||||
remoteEntries, remoteMods, remoteFolders, remoteDeletions := getRemoteDataFromClient(manualSync)
|
remoteEntryModMap, remoteFolders, remoteDeletions := getRemoteDataFromClient(manualSync)
|
||||||
fmt.Println(remoteEntries, remoteMods, remoteFolders, remoteDeletions) // TODO placeholder
|
fmt.Println(remoteFolders, remoteDeletions) // TODO placeholder
|
||||||
|
|
||||||
// TODO sync deletions and folders
|
// TODO sync deletions and folders
|
||||||
|
|
||||||
// fetch local lists
|
// fetch local lists
|
||||||
localEntries, localMods := getLocalData()
|
localEntryModMap := getLocalData()
|
||||||
fmt.Println(localEntries, localMods) // TODO placeholder
|
|
||||||
|
|
||||||
// TODO sync new and updated entries
|
// sync new and updated entries
|
||||||
|
syncLists(localEntryModMap, remoteEntryModMap)
|
||||||
|
|
||||||
// exit program after successful sync
|
// exit program after successful sync
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
|||||||
+8
-8
@@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// GetRemoteDataFromServer prints to stdout the remote entries, mod times, folders, and deletions
|
// GetRemoteDataFromServer prints to stdout the remote entries, mod times, folders, and deletions
|
||||||
// lists in output are separated by "\x1f"
|
// lists in output are separated by "\x1d"
|
||||||
// output is meant to be captured over SSH for interpretation by the client
|
// output is meant to be captured over SSH for interpretation by the client
|
||||||
func GetRemoteDataFromServer() {
|
func GetRemoteDataFromServer() {
|
||||||
entryList, dirList := WalkEntryDir()
|
entryList, dirList := WalkEntryDir()
|
||||||
@@ -20,19 +20,19 @@ func GetRemoteDataFromServer() {
|
|||||||
|
|
||||||
// print the lists to stdout
|
// print the lists to stdout
|
||||||
for _, entry := range entryList {
|
for _, entry := range entryList {
|
||||||
fmt.Print("\n" + entry)
|
fmt.Print("\x1f" + entry)
|
||||||
}
|
}
|
||||||
fmt.Print("\x1f")
|
fmt.Print("\x1d")
|
||||||
for _, mod := range modList {
|
for _, mod := range modList {
|
||||||
fmt.Print("\n")
|
fmt.Print("\x1f")
|
||||||
fmt.Print(mod)
|
fmt.Print(mod)
|
||||||
}
|
}
|
||||||
fmt.Print("\x1f")
|
fmt.Print("\x1d")
|
||||||
for _, dir := range dirList {
|
for _, dir := range dirList {
|
||||||
fmt.Print("\n" + dir)
|
fmt.Print("\x1f" + dir)
|
||||||
}
|
}
|
||||||
fmt.Print("\x1f")
|
fmt.Print("\x1d")
|
||||||
for _, deletion := range deletionsList {
|
for _, deletion := range deletionsList {
|
||||||
fmt.Print("\n" + deletion.Name())
|
fmt.Print("\x1f" + deletion.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user