mirror of
https://github.com/rwinkhart/MUTN.git
synced 2026-08-28 04:46:41 -04:00
Fix Windows sync (WalkEntryDir now returns only UNIX-style separators); fix setting remote mod time on remote files when downloading; fix server binary compilation; fix init failing silently during SSH configuration
This commit is contained in:
+1
-1
@@ -35,7 +35,7 @@ func main() {
|
||||
fmt.Print(backend.EntryRoot + "\x1d" + strconv.FormatBool(backend.IsWindows))
|
||||
case "init":
|
||||
// create the necessary directories for libmuttonserver to function
|
||||
backend.DirInit()
|
||||
backend.DirInit(false)
|
||||
os.MkdirAll(backend.ConfigDir+backend.PathSeparator+"deletions", 0700)
|
||||
case "version", "-v":
|
||||
versionServer()
|
||||
|
||||
@@ -21,11 +21,11 @@ func determineIndentation(skippedDirList []bool, dirList []string, currentDirInd
|
||||
var lastPrefixIndex int // tracks the index (in both skippedDirList and dirList) of the last displayed parent directory
|
||||
var trimmedDirectory = dirList[currentDirIndex]
|
||||
|
||||
// determine initial indentation multiplier based on PathSeparator occurrences
|
||||
indent := strings.Count(trimmedDirectory, backend.PathSeparator) - 1 // subtract 1 to avoid indenting root-level directories
|
||||
// determine initial indentation multiplier based on "/" occurrences
|
||||
indent := strings.Count(trimmedDirectory, "/") - 1 // subtract 1 to avoid indenting root-level directories
|
||||
|
||||
for i, skipped := range skippedDirList[:currentDirIndex] { // checks each skipped directory to determine if it is a parent to the current directory
|
||||
if strings.HasPrefix(trimmedDirectory, dirList[i]+backend.PathSeparator) { // if the current directory is the child of this iteration's directory...
|
||||
if strings.HasPrefix(trimmedDirectory, dirList[i]+"/") { // if the current directory is the child of this iteration's directory...
|
||||
if skipped { // ...and this iteration's directory was skipped...
|
||||
subtractor++ // increment the subtractor to indicate that the visual indentation should be reduced
|
||||
} else {
|
||||
@@ -106,7 +106,7 @@ func EntryListGen() {
|
||||
|
||||
// check if next directory is within the current one
|
||||
if dirListLength > i+1 {
|
||||
if nextDir := dirList[i+1]; directory == nextDir[:strings.LastIndex(nextDir, backend.PathSeparator)] {
|
||||
if nextDir := dirList[i+1]; directory == nextDir[:strings.LastIndex(nextDir, "/")] {
|
||||
containsSubdirectory = true
|
||||
} else {
|
||||
containsSubdirectory = false
|
||||
@@ -120,14 +120,14 @@ func EntryListGen() {
|
||||
for _, file := range fileList {
|
||||
|
||||
// print the current file if it belongs in the current directory - otherwise, break the loop and move on to the next directory
|
||||
if lastSlash := strings.LastIndex(file, backend.PathSeparator) + 1; file[:lastSlash-1] == directory {
|
||||
if lastSlash := strings.LastIndex(file, "/") + 1; file[:lastSlash-1] == directory {
|
||||
|
||||
// print directory header if this is the first run of the loop
|
||||
if !containsFiles {
|
||||
containsFiles = true
|
||||
skippedDirList[i] = false // the directory header is being printed, indicate that it is not being skipped
|
||||
indent, vanityDirectory = determineIndentation(skippedDirList, dirList, i) // calculate the final indentation multiplier
|
||||
printDirectoryHeader(vanityDirectory, indent)
|
||||
fmt.Printf("\n\n"+strings.Repeat(" ", indent*2)+ansiDirectoryHeader+"%s/"+backend.AnsiReset+"\n", vanityDirectory)
|
||||
}
|
||||
|
||||
charCounter, colorAlternator = printFileEntry(file, lastSlash, charCounter, indent, colorAlternator)
|
||||
@@ -139,7 +139,7 @@ func EntryListGen() {
|
||||
if dirListLength > 1 { // and directories besides the root-level exist... display directory header and empty directory warning
|
||||
skippedDirList[i] = false // the directory header is being printed, indicate that it is not being skipped
|
||||
indent, vanityDirectory = determineIndentation(skippedDirList, dirList, i) // calculate the final indentation multiplier
|
||||
printDirectoryHeader(vanityDirectory, indent)
|
||||
fmt.Printf("\n\n"+strings.Repeat(" ", indent*2)+ansiDirectoryHeader+"%s/"+backend.AnsiReset+"\n", vanityDirectory)
|
||||
fmt.Print(strings.Repeat(" ", indent*2) + ansiEmptyDirectoryWarning + "-empty directory-" + backend.AnsiReset)
|
||||
} else { // warn if the only thing that exists is the root-level directory
|
||||
fmt.Print("\n\nNothing's here! For help creating your first entry, run \"mutn help\".")
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
//go:build !windows
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rwinkhart/MUTN/src/backend"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func printDirectoryHeader(vanityDirectory string, indent int) {
|
||||
fmt.Printf("\n\n"+strings.Repeat(" ", indent*2)+ansiDirectoryHeader+"%s/"+backend.AnsiReset+"\n", vanityDirectory)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rwinkhart/MUTN/src/backend"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func printDirectoryHeader(vanityDirectory string, indent int) {
|
||||
fmt.Printf("\n\n"+strings.Repeat(" ", indent*2)+ansiDirectoryHeader+"%s/"+backend.AnsiReset+"\n", strings.ReplaceAll(vanityDirectory, backend.PathSeparator, "/"))
|
||||
}
|
||||
+1
-1
@@ -40,7 +40,7 @@ func TempInitCli() {
|
||||
sshKeyProtected := inputBinary("Is the identity file password-protected?")
|
||||
|
||||
// write config file
|
||||
backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshKey": sshKey, "sshKeyProtected": strconv.FormatBool(sshKeyProtected)}, false)
|
||||
backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshKey": sshKey, "sshKeyProtected": strconv.FormatBool(sshKeyProtected), "sshEntryRoot": "null", "sshIsWindows": "null"}, false)
|
||||
|
||||
// generate device ID
|
||||
sshEntryRoot, sshIsWindows := sync.DeviceIDGen()
|
||||
|
||||
+1
-1
@@ -260,7 +260,7 @@ func sftpSync(downloadList, uploadList []string, manualSync bool) {
|
||||
localFile.Close()
|
||||
|
||||
// set the modification time of the local file to match the value saved from the remote file (from before the download)
|
||||
err = os.Chtimes(remoteEntryFullPath, time.Now(), modTime)
|
||||
err = os.Chtimes(localEntryFullPath, time.Now(), modTime)
|
||||
}
|
||||
|
||||
if filesTransfered {
|
||||
|
||||
@@ -3,49 +3,10 @@ package sync
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rwinkhart/MUTN/src/backend"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// WalkEntryDir walks the entry directory and returns lists of all files and directories found (two separate lists)
|
||||
func WalkEntryDir() ([]string, []string) {
|
||||
// define file/directory containing slices so that they may be accessed by the anonymous WalkDir function
|
||||
var fileList []string
|
||||
var dirList []string
|
||||
|
||||
// walk entry directory
|
||||
_ = filepath.WalkDir(backend.EntryRoot,
|
||||
func(fullPath string, entry fs.DirEntry, err error) error {
|
||||
|
||||
// check for errors encountered while walking directory
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
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 + "An unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// trim root path from each path before storing
|
||||
trimmedPath := fullPath[rootLength:]
|
||||
|
||||
// create separate slices for entries and directories
|
||||
if !entry.IsDir() {
|
||||
fileList = append(fileList, trimmedPath)
|
||||
} else {
|
||||
dirList = append(dirList, trimmedPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return fileList, dirList
|
||||
}
|
||||
|
||||
func getModTimes(entryList []string) []int64 {
|
||||
// get a list of all entry modification times
|
||||
var modList []int64
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
//go:build !windows
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rwinkhart/MUTN/src/backend"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// WalkEntryDir walks the entry directory and returns lists of all files and directories found (two separate lists)
|
||||
// regardless of platform, all paths are stored with forward slashes (UNIX-style)
|
||||
func WalkEntryDir() ([]string, []string) {
|
||||
// define file/directory containing slices so that they may be accessed by the anonymous WalkDir function
|
||||
var fileList []string
|
||||
var dirList []string
|
||||
|
||||
// walk entry directory
|
||||
_ = filepath.WalkDir(backend.EntryRoot,
|
||||
func(fullPath string, entry fs.DirEntry, err error) error {
|
||||
|
||||
// check for errors encountered while walking directory
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
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 + "An unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// trim root path from each path before storing
|
||||
trimmedPath := fullPath[rootLength:]
|
||||
|
||||
// append the path to the appropriate slice
|
||||
if !entry.IsDir() {
|
||||
fileList = append(fileList, trimmedPath)
|
||||
} else {
|
||||
dirList = append(dirList, trimmedPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return fileList, dirList
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//go:build windows
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/rwinkhart/MUTN/src/backend"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// WalkEntryDir walks the entry directory and returns lists of all files and directories found (two separate lists)
|
||||
// regardless of platform, all paths are stored with forward slashes (UNIX-style)
|
||||
func WalkEntryDir() ([]string, []string) {
|
||||
// define file/directory containing slices so that they may be accessed by the anonymous WalkDir function
|
||||
var fileList []string
|
||||
var dirList []string
|
||||
|
||||
// walk entry directory
|
||||
_ = filepath.WalkDir(backend.EntryRoot,
|
||||
func(fullPath string, entry fs.DirEntry, err error) error {
|
||||
|
||||
// check for errors encountered while walking directory
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
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 + "An unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// trim root path from each path before storing and replace backslashes with forward slashes
|
||||
trimmedPath := strings.ReplaceAll(fullPath[rootLength:], "\\", "/")
|
||||
|
||||
// append the path to the appropriate slice
|
||||
if !entry.IsDir() {
|
||||
fileList = append(fileList, trimmedPath)
|
||||
} else {
|
||||
dirList = append(dirList, trimmedPath)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return fileList, dirList
|
||||
}
|
||||
+1
-1
@@ -15,7 +15,7 @@ func DeviceIDGen() (string, string) {
|
||||
deviceIDSuffix := backend.StringGen(rand.Intn(48)+48, false, 0) // TODO consider using complex string generator and removing unsafe characters manually
|
||||
deviceID := deviceIDPrefix + "-" + deviceIDSuffix
|
||||
os.Create(backend.ConfigDir + backend.PathSeparator + "devices" + backend.PathSeparator + deviceID) // TODO remove existing device ID file if it exists (from both client and server)
|
||||
sshEntryRootSSHIsWindows := strings.Split(GetSSHOutput("libmuttonserver register "+deviceID, false), "\x1d") // register device ID with server and fetch remote EntryRoot and OS type
|
||||
sshEntryRootSSHIsWindows := strings.Split(GetSSHOutput("libmuttonserver register "+deviceID, true), "\x1d") // register device ID with server and fetch remote EntryRoot and OS type; manualSync is true so the user is alerted if device ID registration fails
|
||||
|
||||
return sshEntryRootSSHIsWindows[0], sshEntryRootSSHIsWindows[1]
|
||||
}
|
||||
|
||||
+3
-3
@@ -23,7 +23,7 @@ func GetRemoteDataFromServer(clientDeviceID string) {
|
||||
|
||||
// entry list
|
||||
for _, entry := range entryList {
|
||||
printToStdout(entry)
|
||||
fmt.Print("\x1f" + entry)
|
||||
}
|
||||
|
||||
// modification time list
|
||||
@@ -36,7 +36,7 @@ func GetRemoteDataFromServer(clientDeviceID string) {
|
||||
// directory/folder list
|
||||
fmt.Print("\x1d")
|
||||
for _, dir := range dirList {
|
||||
printToStdout(dir)
|
||||
fmt.Print("\x1f" + dir)
|
||||
}
|
||||
|
||||
// deletions list
|
||||
@@ -45,7 +45,7 @@ func GetRemoteDataFromServer(clientDeviceID string) {
|
||||
// print deletion if it is relevant to the current client device
|
||||
affectedIDTargetLocationIncomplete := strings.Split(deletion.Name(), "\x1d")
|
||||
if affectedIDTargetLocationIncomplete[0] == clientDeviceID {
|
||||
fmt.Print("\x1f" + strings.ReplaceAll(affectedIDTargetLocationIncomplete[1], "\x1e", "/")) // do not use printToStdout as separators are filling in for \x1e
|
||||
fmt.Print("\x1f" + strings.ReplaceAll(affectedIDTargetLocationIncomplete[1], "\x1e", "/"))
|
||||
|
||||
// assume successful client deletion and remove deletions file (if assumption is somehow false, worst case scenario is that the client will re-upload the deleted entry)
|
||||
os.Remove(backend.ConfigDir + backend.PathSeparator + "deletions" + backend.PathSeparator + deletion.Name())
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
//go:build !windows
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// printToStdout prints a string to stdout with UNIX path separators
|
||||
func printToStdout(targetLocationIncomplete string) {
|
||||
fmt.Print("\x1f" + targetLocationIncomplete)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
//go:build windows
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// printToStdout prints a string to stdout with UNIX path separators
|
||||
func printToStdout(targetLocationIncomplete string) {
|
||||
fmt.Print("\x1f" + strings.ReplaceAll(targetLocationIncomplete, "\\", "/"))
|
||||
}
|
||||
Reference in New Issue
Block a user