From 7a5ff7fac996d8c2711ba41ff09c9b5fcea37b90 Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Wed, 15 May 2024 16:25:42 -0400 Subject: [PATCH] Implement initial server-side code --- src/sync/{sync.go => client.go} | 16 ++++++-------- src/sync/{walk.go => common.go} | 16 ++++++++++++-- src/sync/server.go | 37 +++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 12 deletions(-) rename src/sync/{sync.go => client.go} (88%) rename src/sync/{walk.go => common.go} (60%) create mode 100644 src/sync/server.go diff --git a/src/sync/sync.go b/src/sync/client.go similarity index 88% rename from src/sync/sync.go rename to src/sync/client.go index 73230ea..dddd0b7 100644 --- a/src/sync/sync.go +++ b/src/sync/client.go @@ -84,15 +84,15 @@ func getSSHOutput(cmd string, manualSync bool) string { return outputString } -// getRemoteData returns lists of remote entries, mod times, folders, and deletions (four separate lists) -func getRemoteData(manualSync bool) ([]string, []int64, []string, []string) { +// getRemoteDataFromClient returns lists of remote entries, mod times, folders, and deletions (four separate lists) +func getRemoteDataFromClient(manualSync bool) ([]string, []int64, []string, []string) { // get remote output over SSH - output := getSSHOutput("ls && uname -r", manualSync) // TODO replace cmd with remote server command (e.g. "libmuttonserver fetch") + output := getSSHOutput("libmuttonserver", manualSync) // split output into slice based on occurrences of "\x1f" outputSlice := strings.Split(output, "\x1f") - // re-form the lists + // 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") modsStrings := strings.Split(outputSlice[1], "\n") folders := strings.Split(outputSlice[2], "\n") @@ -114,11 +114,7 @@ func getLocalData() ([]string, []int64) { fileList, _ := WalkEntryDir() // get a list of all entry modification times - var modList []int64 - for _, file := range fileList { - modTime, _ := os.Stat(backend.EntryRoot + file) - modList = append(modList, modTime.ModTime().Unix()) - } + modList := getModTimes(fileList) // return the lists return fileList, modList @@ -127,7 +123,7 @@ func getLocalData() ([]string, []int64) { // RunJob runs the SSH sync job func RunJob(manualSync bool) { // TODO fetch remote lists - remoteEntries, remoteMods, remoteFolders, remoteDeletions := getRemoteData(manualSync) + remoteEntries, remoteMods, remoteFolders, remoteDeletions := getRemoteDataFromClient(manualSync) fmt.Println(remoteEntries, remoteMods, remoteFolders, remoteDeletions) // TODO placeholder // TODO sync deletions and folders diff --git a/src/sync/walk.go b/src/sync/common.go similarity index 60% rename from src/sync/walk.go rename to src/sync/common.go index b29bbb0..a167298 100644 --- a/src/sync/walk.go +++ b/src/sync/common.go @@ -9,6 +9,7 @@ import ( ) // WalkEntryDir walks the entry directory and returns lists of all files and directories found (two separate lists) +// initCommand is used to specify to the end user how to generate the entry directory if it does not exists func WalkEntryDir() ([]string, []string) { // define file/directory containing slices so that they may be accessed by the anonymous WalkDir function var fileList []string @@ -21,10 +22,10 @@ func WalkEntryDir() ([]string, []string) { // check for errors encountered while walking directory if err != nil { if os.IsNotExist(err) { - fmt.Println(backend.AnsiError + "\nThe entry directory does not exist - run \"mutn init\" to create it" + backend.AnsiReset) + fmt.Println(backend.AnsiError+"The entry directory does not exist - run \""+os.Args[0], "init"+"\" to create it"+backend.AnsiReset) // TODO implement init command for libmuttonserver } else { // otherwise, print the source of the error - fmt.Println(backend.AnsiError + "\nAn unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset) + fmt.Println(backend.AnsiError + "An unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset) } os.Exit(1) } @@ -44,3 +45,14 @@ func WalkEntryDir() ([]string, []string) { return fileList, dirList } + +func getModTimes(entryList []string) []int64 { + // get a list of all entry modification times + var modList []int64 + for _, file := range entryList { + modTime, _ := os.Stat(backend.EntryRoot + file) + modList = append(modList, modTime.ModTime().Unix()) + } + + return modList +} diff --git a/src/sync/server.go b/src/sync/server.go new file mode 100644 index 0000000..e9ca779 --- /dev/null +++ b/src/sync/server.go @@ -0,0 +1,37 @@ +package sync + +import ( + "fmt" + "github.com/rwinkhart/MUTN/src/backend" + "os" +) + +// GetRemoteDataFromServer prints to stdout the remote entries, mod times, folders, and deletions +// lists in output are separated by "\x1f" +// output is meant to be captured over SSH for interpretation by the client +func GetRemoteDataFromServer() { + entryList, dirList := WalkEntryDir() + modList := getModTimes(entryList) + deletionsList, err := os.ReadDir(backend.ConfigDir + "/deletions") + if err != nil { + fmt.Println(backend.AnsiError + "Failed to read the deletions directory: " + err.Error() + backend.AnsiReset) + os.Exit(1) + } + + // print the lists to stdout + for _, entry := range entryList { + fmt.Println(entry) + } + fmt.Println("\x1f") + for _, mod := range modList { + fmt.Println(mod) + } + fmt.Print("\x1f") // do not print new lines as the prior output is []int64 + for _, dir := range dirList { + fmt.Println(dir) + } + fmt.Println("\x1f") + for _, deletion := range deletionsList { + fmt.Println(deletion.Name()) + } +}