diff --git a/libmuttonserver.go b/libmuttonserver.go index eff79f8..21e27d2 100644 --- a/libmuttonserver.go +++ b/libmuttonserver.go @@ -45,7 +45,7 @@ func main() { // stdin[0] is evaluated after fallthrough // stdin[1] is expected to be the OLD incomplete target location with "\x1d" representing path separators - always pass in UNIX format // stdin[2] is expected to be the NEW incomplete target location with "\x1d" representing path separators - always pass in UNIX format - sync.Rename(strings.ReplaceAll(stdin[1], "\x1d", "/"), strings.ReplaceAll(stdin[2], "\x1d", "/"), true) + sync.RenameLocal(strings.ReplaceAll(stdin[1], "\x1d", "/"), strings.ReplaceAll(stdin[2], "\x1d", "/")) fallthrough // fallthrough to add the old entry to the deletions directory case "shear": // shear an entry from the server and add it to the deletions directory diff --git a/src/cli/edit.go b/src/cli/edit.go index 69328e9..f149b6e 100644 --- a/src/cli/edit.go +++ b/src/cli/edit.go @@ -11,13 +11,13 @@ import ( "strings" ) -// RenameCli renames an entry at oldLocation to a new location (user input) on both the client and the server +// RenameCli renames an entry at oldLocationIncomplete to a new location (user input) on both the client and the server func RenameCli(oldLocationIncomplete string) { // prompt user for new location and rename newLocationIncomplete := input("New location:") - sync.Rename(oldLocationIncomplete, newLocationIncomplete, false) + sync.RenameRemoteFromClient(oldLocationIncomplete, newLocationIncomplete) - // exit is done from sync.Rename + // exit is done from sync.RenameRemoteFromClient } // EditEntryField edits a field of an entry at targetLocation (user input) diff --git a/src/sync/client.go b/src/sync/client.go index a0bbd16..636ee9e 100644 --- a/src/sync/client.go +++ b/src/sync/client.go @@ -370,17 +370,6 @@ func syncLists(localEntryModMap, remoteEntryModMap map[string]int64, manualSync fmt.Println("Client is synchronized with server") } -// ShearRemoteFromClient removes the target file or directory from the local system and calls the server to remove it remotely and add it to the deletions list -// can safely be called in offline mode, as well, so this is the intended interface for shearing (ShearLocal should only be used directly in the server binary) -func ShearRemoteFromClient(targetLocationIncomplete string) { - deviceID := ShearLocal(targetLocationIncomplete, "") // remove the target from the local system and get the device ID of the client - - // call the server to remotely shear the target and add it to the deletions list - GetSSHOutput("libmuttonserver shear", deviceID+"\n"+strings.ReplaceAll(targetLocationIncomplete, backend.PathSeparator, "\x1d"), false) - - backend.Exit(0) // sync is not required after shearing since the target has already been removed from the local system -} - // deletionSync removes entries from the client that have been deleted on the server (multi-client deletion) func deletionSync(deletions []string) { var filesDeleted bool @@ -395,7 +384,36 @@ func deletionSync(deletions []string) { } } +// ShearRemoteFromClient removes the target file or directory from the local system and calls the server to remove it remotely and add it to the deletions list +// can safely be called in offline mode, as well, so this is the intended interface for shearing (ShearLocal should only be used directly by the server binary) +func ShearRemoteFromClient(targetLocationIncomplete string) { + deviceID := ShearLocal(targetLocationIncomplete, "") // remove the target from the local system and get the device ID of the client + + // call the server to remotely shear the target and add it to the deletions list + GetSSHOutput("libmuttonserver shear", deviceID+"\n"+strings.ReplaceAll(targetLocationIncomplete, backend.PathSeparator, "\x1d"), false) + + backend.Exit(0) // sync is not required after shearing since the target has already been removed from the local system +} + +// RenameRemoteFromClient renames oldLocationIncomplete to newLocationIncomplete on the local system and calls the server to perform the rename remotely and add the old target to the deletions list +// can safely be called in offline mode, as well, so this is the intended interface for renaming (RenameLocal should only be used directly by the server binary) +func RenameRemoteFromClient(oldLocationIncomplete, newLocationIncomplete string) { + RenameLocal(oldLocationIncomplete, newLocationIncomplete) // move the target on the local system + + deviceIDList := genDeviceIDList() + if len(*deviceIDList) > 0 { // ensure a device ID exists (online mode) + // call the server to move the target on the remote system and add the old target to the deletions list + GetSSHOutput("libmuttonserver rename", + (*deviceIDList)[0].Name()+"\n"+ + strings.ReplaceAll(oldLocationIncomplete, backend.PathSeparator, "\x1d")+"\n"+ + strings.ReplaceAll(newLocationIncomplete, backend.PathSeparator, "\x1d"), false) + } + + backend.Exit(0) +} + // AddFolderRemoteFromClient creates a new entry-containing directory on the local system and calls the server to create the folder remotely +// can safely be called in offline mode, as well, so this is the intended interface for adding folders (AddFolderLocal should only be used directly by the server binary) func AddFolderRemoteFromClient(targetLocationIncomplete string) { AddFolderLocal(targetLocationIncomplete) // add the folder on the local system GetSSHOutput("libmuttonserver addfolder", strings.ReplaceAll(targetLocationIncomplete, backend.PathSeparator, "\x1d"), false) // call the server to create the folder remotely diff --git a/src/sync/common.go b/src/sync/common.go index 58aec5c..110997d 100644 --- a/src/sync/common.go +++ b/src/sync/common.go @@ -30,42 +30,6 @@ func genDeviceIDList() *[]fs.DirEntry { return &deviceIDList } -// Rename renames oldLocation to newLocation -// if running on the client, also calls the server to rename the entry and add the old entry name to the deletions list -func Rename(oldLocationIncomplete, newLocationIncomplete string, onServer bool) { - // get full paths for both locations - oldLocation := backend.TargetLocationFormat(oldLocationIncomplete) - newLocation := backend.TargetLocationFormat(newLocationIncomplete) - - // ensure oldLocation exists - backend.TargetIsFile(oldLocation, true, 0) - - // ensure newLocation does not exist - _, isAccessible := backend.TargetIsFile(newLocation, false, 0) - if isAccessible { - fmt.Println(backend.AnsiError + "\"" + newLocation + "\" already exists" + backend.AnsiReset) - os.Exit(1) - } - - // rename oldLocation to newLocation - err := os.Rename(oldLocation, newLocation) - if err != nil { - fmt.Println(backend.AnsiError + "Failed to rename - does the target containing directory exist?" + backend.AnsiReset) - } - - // call server to complete rename - if !onServer { - deviceIDList := genDeviceIDList() - if len(*deviceIDList) > 0 { // ensure a device ID exists (online mode) - GetSSHOutput("libmuttonserver rename", - (*deviceIDList)[0].Name()+"\n"+ - strings.ReplaceAll(oldLocationIncomplete, backend.PathSeparator, "\x1d")+"\n"+ - strings.ReplaceAll(newLocationIncomplete, backend.PathSeparator, "\x1d"), false) - } - backend.Exit(0) // do not exit program on server, as fallthrough is used to add the old entry name to the deletions list - } -} - // ShearLocal removes the target file or directory from the local system // returns: deviceID (on client), for use in ShearRemoteFromClient // if the local system is a server, it will also add the target to the deletions list for all clients (except the requesting client) @@ -112,6 +76,32 @@ func ShearLocal(targetLocationIncomplete, clientDeviceID string) string { // do not exit program, as this function is used as part of ShearRemoteFromClient } +// RenameLocal renames oldLocationIncomplete to newLocationIncomplete on the local system +// this function should only be used directly by the server binary +func RenameLocal(oldLocationIncomplete, newLocationIncomplete string) { + // get full paths for both locations + oldLocation := backend.TargetLocationFormat(oldLocationIncomplete) + newLocation := backend.TargetLocationFormat(newLocationIncomplete) + + // ensure oldLocation exists + backend.TargetIsFile(oldLocation, true, 0) + + // ensure newLocation does not exist + _, isAccessible := backend.TargetIsFile(newLocation, false, 0) + if isAccessible { + fmt.Println(backend.AnsiError + "\"" + newLocation + "\" already exists" + backend.AnsiReset) + os.Exit(1) + } + + // rename oldLocation to newLocation + err := os.Rename(oldLocation, newLocation) + if err != nil { + fmt.Println(backend.AnsiError + "Failed to rename - does the target containing directory exist?" + backend.AnsiReset) + } + + // do not exit program, as this function is used as part of RenameRemoteFromClient +} + // AddFolderLocal creates a new entry-containing directory on the local system // this function should only be used directly by the server binary func AddFolderLocal(targetLocationIncomplete string) {