mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-28 04:46:42 -04:00
Properly format function documentation comments
This commit is contained in:
@@ -4,12 +4,10 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// global variables used across multiple files
|
|
||||||
var (
|
var (
|
||||||
Home, _ = os.UserHomeDir()
|
Home, _ = os.UserHomeDir()
|
||||||
)
|
)
|
||||||
|
|
||||||
// global constants used across multiple files
|
|
||||||
const (
|
const (
|
||||||
AnsiError = "\033[38;5;9m"
|
AnsiError = "\033[38;5;9m"
|
||||||
AnsiReset = "\033[0m"
|
AnsiReset = "\033[0m"
|
||||||
|
|||||||
@@ -2,19 +2,17 @@
|
|||||||
|
|
||||||
package core
|
package core
|
||||||
|
|
||||||
// EntryRoot path to libmutton entry directory
|
var EntryRoot = Home + "/.local/share/libmutton" // path to libmutton entry directory
|
||||||
var EntryRoot = Home + "/.local/share/libmutton"
|
var ConfigDir = Home + "/.config/libmutton" // path to libmutton configuration directory
|
||||||
var ConfigDir = Home + "/.config/libmutton"
|
var ConfigPath = ConfigDir + "/libmutton.ini" // path to libmutton configuration file
|
||||||
var ConfigPath = ConfigDir + "/libmutton.ini"
|
|
||||||
|
|
||||||
// PathSeparator defines the character used to separate directories in a path (platform-specific)
|
|
||||||
const (
|
const (
|
||||||
PathSeparator = "/"
|
PathSeparator = "/" // platform-specific path separator
|
||||||
IsWindows = false
|
IsWindows = false // platform indicator
|
||||||
)
|
)
|
||||||
|
|
||||||
// enableVirtualTerminalProcessing is a dummy function on UNIX-like systems (only needed on Windows)
|
// enableVirtualTerminalProcessing is a dummy function on UNIX-like systems (only needed on Windows).
|
||||||
// TODO remove after migration off of GPG, as pinentry is responsible for disabling ANSI escape sequence interpretation
|
// TODO Remove after migration off of GPG, as pinentry is responsible for disabling ANSI escape sequence interpretation.
|
||||||
func enableVirtualTerminalProcessing() {
|
func enableVirtualTerminalProcessing() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-9
@@ -7,19 +7,17 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EntryRoot path to libmutton entry directory
|
var EntryRoot = Home + "\\AppData\\Local\\libmutton\\entries" // path to libmutton entry directory
|
||||||
var EntryRoot = Home + "\\AppData\\Local\\libmutton\\entries"
|
var ConfigDir = Home + "\\AppData\\Local\\libmutton\\config" // path to libmutton configuration directory
|
||||||
var ConfigDir = Home + "\\AppData\\Local\\libmutton\\config"
|
var ConfigPath = ConfigDir + "\\libmutton.ini" // path to libmutton configuration file
|
||||||
var ConfigPath = ConfigDir + "\\libmutton.ini"
|
|
||||||
|
|
||||||
// PathSeparator defines the character used to separate directories in a path (platform-specific)
|
|
||||||
const (
|
const (
|
||||||
PathSeparator = "\\"
|
PathSeparator = "\\" // platform-specific path separator
|
||||||
IsWindows = true
|
IsWindows = true // platform indicator
|
||||||
)
|
)
|
||||||
|
|
||||||
// enableVirtualTerminalProcessing ensures ANSI escape sequences are interpreted properly on Windows
|
// enableVirtualTerminalProcessing ensures ANSI escape sequences are interpreted properly on Windows.
|
||||||
// TODO remove after migration off of GPG, as pinentry is responsible for disabling ANSI escape sequence interpretation
|
// TODO Remove after migration off of GPG, as pinentry is responsible for disabling ANSI escape sequence interpretation.
|
||||||
func enableVirtualTerminalProcessing() {
|
func enableVirtualTerminalProcessing() {
|
||||||
stdout := syscall.Handle(os.Stdout.Fd())
|
stdout := syscall.Handle(os.Stdout.Fd())
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"gopkg.in/ini.v1"
|
"gopkg.in/ini.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// loadConfig loads the libmutton.ini file and returns the configuration
|
// loadConfig loads the libmutton.ini file and returns the configuration.
|
||||||
// utility function for ParseConfig and WriteConfig, do not call directly
|
// It is a utility function for ParseConfig and WriteConfig; do not call directly.
|
||||||
func loadConfig() *ini.File {
|
func loadConfig() *ini.File {
|
||||||
cfg, err := ini.Load(ConfigPath)
|
cfg, err := ini.Load(ConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -18,10 +18,10 @@ func loadConfig() *ini.File {
|
|||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseConfig reads the libmutton.ini file and returns a slice of values for the specified keys
|
// ParseConfig reads the libmutton.ini file and returns a slice of values for the specified keys.
|
||||||
// requires requestedValues: a slice of arrays (length 2) each containing a section and a key name
|
// Requires: requestedValues (a slice of length 2 arrays each containing a section and a key name),
|
||||||
// requires missingValueError: an error message to display if a key is missing a value, set to "" for auto-generated or "0" to exit/return silently with code 0
|
// missingValueError (an error message to display if a key is missing a value, set to "" for auto-generated or "0" to exit/return silently with code 0).
|
||||||
// returns config: a slice of values for the specified keys
|
// Returns: config (slice of values for the specified keys).
|
||||||
func ParseConfig(valuesRequested [][2]string, missingValueError string) []string {
|
func ParseConfig(valuesRequested [][2]string, missingValueError string) []string {
|
||||||
cfg := loadConfig()
|
cfg := loadConfig()
|
||||||
|
|
||||||
@@ -49,8 +49,8 @@ func ParseConfig(valuesRequested [][2]string, missingValueError string) []string
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteConfig writes the provided key-value pairs under the specified section headers in the libmutton.ini file
|
// WriteConfig writes the provided key-value pairs under the specified section headers in the libmutton.ini file.
|
||||||
// requires valuesToWrite: a slice of arrays (length 3) each containing a section, a key name, and a value
|
// Requires: valuesToWrite (a slice of length 3 arrays each containing a section, a key name, and a value).
|
||||||
func WriteConfig(valuesToWrite [][3]string, append bool) {
|
func WriteConfig(valuesToWrite [][3]string, append bool) {
|
||||||
var cfg *ini.File
|
var cfg *ini.File
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CopyArgument copies a field from an entry to the clipboard
|
// CopyArgument copies a field from an entry to the clipboard.
|
||||||
func CopyArgument(executableName, targetLocation string, field int) {
|
func CopyArgument(executableName, targetLocation string, field int) {
|
||||||
if isFile, _ := TargetIsFile(targetLocation, true, 2); isFile {
|
if isFile, _ := TargetIsFile(targetLocation, true, 2); isFile {
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ func CopyArgument(executableName, targetLocation string, field int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClipClearArgument is called to clear the clipboard after 30 seconds if the contents have not been modified
|
// ClipClearArgument is called to clear the clipboard after 30 seconds if the contents have not been modified.
|
||||||
func ClipClearArgument() {
|
func ClipClearArgument() {
|
||||||
// read previous clipboard contents from stdin
|
// read previous clipboard contents from stdin
|
||||||
clipScanner := bufio.NewScanner(os.Stdin)
|
clipScanner := bufio.NewScanner(os.Stdin)
|
||||||
@@ -71,7 +71,7 @@ func ClipClearArgument() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenTOTP generates a TOTP token from a secret (supports standard and Steam TOTP)
|
// GenTOTP generates a TOTP token from a secret (supports standard and Steam TOTP).
|
||||||
func GenTOTP(secret string, time time.Time, forSteam bool) string {
|
func GenTOTP(secret string, time time.Time, forSteam bool) string {
|
||||||
var totpToken string
|
var totpToken string
|
||||||
var err error
|
var err error
|
||||||
|
|||||||
+2
-4
@@ -10,9 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO MacOS support is entirely untested - I would appreciate feedback on this implementation
|
// copyField copies a field from an entry to the clipboard.
|
||||||
|
|
||||||
// copyField copies a field from an entry to the clipboard
|
|
||||||
func copyField(executableName, copySubject string) {
|
func copyField(executableName, copySubject string) {
|
||||||
cmd := exec.Command("pbcopy")
|
cmd := exec.Command("pbcopy")
|
||||||
writeToStdin(cmd, copySubject)
|
writeToStdin(cmd, copySubject)
|
||||||
@@ -35,7 +33,7 @@ func copyField(executableName, copySubject string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clipClear is called in a separate process to clear the clipboard after 30 seconds
|
// clipClear is called in a separate process to clear the clipboard after 30 seconds.
|
||||||
func clipClear(oldContents string) {
|
func clipClear(oldContents string) {
|
||||||
time.Sleep(30 * time.Second)
|
time.Sleep(30 * time.Second)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -10,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// copyField copies a field from an entry to the clipboard
|
// copyField copies a field from an entry to the clipboard.
|
||||||
func copyField(executableName, copySubject string) {
|
func copyField(executableName, copySubject string) {
|
||||||
cmd := exec.Command("termux-clipboard-set")
|
cmd := exec.Command("termux-clipboard-set")
|
||||||
writeToStdin(cmd, copySubject)
|
writeToStdin(cmd, copySubject)
|
||||||
@@ -33,7 +33,7 @@ func copyField(executableName, copySubject string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clipClear is called in a separate process to clear the clipboard after 30 seconds
|
// clipClear is called in a separate process to clear the clipboard after 30 seconds.
|
||||||
func clipClear(oldContents string) {
|
func clipClear(oldContents string) {
|
||||||
time.Sleep(30 * time.Second)
|
time.Sleep(30 * time.Second)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// copyField copies a field from an entry to the clipboard
|
// copyField copies a field from an entry to the clipboard.
|
||||||
func copyField(executableName, copySubject string) {
|
func copyField(executableName, copySubject string) {
|
||||||
var envSet bool // track whether environment variables are set
|
var envSet bool // track whether environment variables are set
|
||||||
var cmd *exec.Cmd
|
var cmd *exec.Cmd
|
||||||
@@ -44,7 +44,7 @@ func copyField(executableName, copySubject string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clipClear is called in a separate process to clear the clipboard after 30 seconds
|
// clipClear is called in a separate process to clear the clipboard after 30 seconds.
|
||||||
func clipClear(oldContents string) {
|
func clipClear(oldContents string) {
|
||||||
time.Sleep(30 * time.Second)
|
time.Sleep(30 * time.Second)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -10,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// copyField copies a field from an entry to the clipboard
|
// copyField copies a field from an entry to the clipboard.
|
||||||
func copyField(executableName, copySubject string) {
|
func copyField(executableName, copySubject string) {
|
||||||
cmd := exec.Command("powershell.exe", "-c", fmt.Sprintf("echo '%s' | Set-Clipboard", strings.ReplaceAll(copySubject, "'", "''")))
|
cmd := exec.Command("powershell.exe", "-c", fmt.Sprintf("echo '%s' | Set-Clipboard", strings.ReplaceAll(copySubject, "'", "''")))
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
@@ -32,7 +32,7 @@ func copyField(executableName, copySubject string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clipClear is called in a separate process to clear the clipboard after 30 seconds
|
// clipClear is called in a separate process to clear the clipboard after 30 seconds.
|
||||||
func clipClear(oldContents string) {
|
func clipClear(oldContents string) {
|
||||||
time.Sleep(30 * time.Second)
|
time.Sleep(30 * time.Second)
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
// GetOldEntryData decrypts and returns old entry data (with all required lines present)
|
// GetOldEntryData decrypts and returns old entry data (with all required lines present).
|
||||||
func GetOldEntryData(targetLocation string, field int) []string {
|
func GetOldEntryData(targetLocation string, field int) []string {
|
||||||
// ensure targetLocation exists
|
// ensure targetLocation exists
|
||||||
TargetIsFile(targetLocation, true, 2)
|
TargetIsFile(targetLocation, true, 2)
|
||||||
@@ -10,14 +10,14 @@ func GetOldEntryData(targetLocation string, field int) []string {
|
|||||||
|
|
||||||
// return the old entry data with all required lines present
|
// return the old entry data with all required lines present
|
||||||
if field > 0 {
|
if field > 0 {
|
||||||
return EnsureSliceLength(unencryptedEntry, field)
|
return ensureSliceLength(unencryptedEntry, field)
|
||||||
} else {
|
} else {
|
||||||
return unencryptedEntry
|
return unencryptedEntry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureSliceLength ensures slice is long enough to contain the specified index
|
// ensureSliceLength is a utility function that ensures a slice is long enough to contain the specified index.
|
||||||
func EnsureSliceLength(slice []string, index int) []string {
|
func ensureSliceLength(slice []string, index int) []string {
|
||||||
for len(slice) <= index {
|
for len(slice) <= index {
|
||||||
slice = append(slice, "")
|
slice = append(slice, "")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package core
|
|||||||
|
|
||||||
import "os"
|
import "os"
|
||||||
|
|
||||||
|
// Exit (hard) is meant to be used in non-interactive CLI implementations to exit the program after an operation.
|
||||||
func Exit(code int) {
|
func Exit(code int) {
|
||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
package core
|
package core
|
||||||
|
|
||||||
|
// Exit (soft) is meant to be used in interactive implementations (GUIs/TUIs) to keep the program running after an operation.
|
||||||
func Exit(code int) {
|
func Exit(code int) {
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
// TODO GPG support is a temporary feature - it will be replaced with a different encryption scheme in the future
|
// TODO GPG support is a temporary feature - it will be replaced with a different encryption scheme in the future
|
||||||
|
|
||||||
// DecryptGPG decrypts a GPG-encrypted file and returns the contents as a slice of (trimmed) strings
|
// DecryptGPG decrypts a GPG-encrypted file and returns the contents as a slice of (trimmed) strings.
|
||||||
func DecryptGPG(targetLocation string) []string {
|
func DecryptGPG(targetLocation string) []string {
|
||||||
cmd := exec.Command("gpg", "--pinentry-mode", "loopback", "-q", "-d", targetLocation)
|
cmd := exec.Command("gpg", "--pinentry-mode", "loopback", "-q", "-d", targetLocation)
|
||||||
output, err := cmd.Output()
|
output, err := cmd.Output()
|
||||||
@@ -26,7 +26,7 @@ func DecryptGPG(targetLocation string) []string {
|
|||||||
return outputSlice
|
return outputSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptGPG encrypts a slice of strings using GPG and returns the encrypted data as a byte slice
|
// EncryptGPG encrypts a slice of strings using GPG and returns the encrypted data as a byte slice.
|
||||||
func EncryptGPG(input []string) []byte {
|
func EncryptGPG(input []string) []byte {
|
||||||
cmd := exec.Command("gpg", "-q", "-r", ParseConfig([][2]string{{"LIBMUTTON", "gpgID"}}, "")[0], "-e")
|
cmd := exec.Command("gpg", "-q", "-r", ParseConfig([][2]string{{"LIBMUTTON", "gpgID"}}, "")[0], "-e")
|
||||||
writeToStdin(cmd, strings.Join(input, "\n"))
|
writeToStdin(cmd, strings.Join(input, "\n"))
|
||||||
|
|||||||
+3
-3
@@ -9,7 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GpgUIDListGen generates a list of all GPG key IDs on the system and returns them as a slice of strings
|
// GpgUIDListGen generates a list of all GPG key IDs on the system and returns them as a slice of strings.
|
||||||
func GpgUIDListGen() []string {
|
func GpgUIDListGen() []string {
|
||||||
cmd := exec.Command("gpg", "-k", "--with-colons")
|
cmd := exec.Command("gpg", "-k", "--with-colons")
|
||||||
gpgOutputBytes, _ := cmd.Output()
|
gpgOutputBytes, _ := cmd.Output()
|
||||||
@@ -24,7 +24,7 @@ func GpgUIDListGen() []string {
|
|||||||
return uidSlice
|
return uidSlice
|
||||||
}
|
}
|
||||||
|
|
||||||
// GpgKeyGen generates a new GPG key and returns the key ID
|
// GpgKeyGen generates a new GPG key and returns the key ID.
|
||||||
func GpgKeyGen() string {
|
func GpgKeyGen() string {
|
||||||
gpgGenTempFile := CreateTempFile()
|
gpgGenTempFile := CreateTempFile()
|
||||||
defer func(name string) {
|
defer func(name string) {
|
||||||
@@ -52,7 +52,7 @@ func GpgKeyGen() string {
|
|||||||
return "libmutton-" + unixTime + " (gpg-libmutton) <github.com/rwinkhart/libmutton>"
|
return "libmutton-" + unixTime + " (gpg-libmutton) <github.com/rwinkhart/libmutton>"
|
||||||
}
|
}
|
||||||
|
|
||||||
// DirInit creates the libmutton directories
|
// DirInit creates the libmutton directories.
|
||||||
func DirInit(preserveOldConfigDir bool) {
|
func DirInit(preserveOldConfigDir bool) {
|
||||||
// create EntryRoot
|
// create EntryRoot
|
||||||
err := os.MkdirAll(EntryRoot, 0700)
|
err := os.MkdirAll(EntryRoot, 0700)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
package core
|
package core
|
||||||
|
|
||||||
// TargetLocationFormat returns the full location of an entry (given the name) formatted for the current platform
|
// TargetLocationFormat returns the full location of an entry (given the name) formatted for the current platform.
|
||||||
func TargetLocationFormat(targetLocationIncomplete string) string {
|
func TargetLocationFormat(targetLocationIncomplete string) string {
|
||||||
return EntryRoot + targetLocationIncomplete
|
return EntryRoot + targetLocationIncomplete
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ package core
|
|||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
// TargetLocationFormat returns the full location of an entry (given the name) formatted for the current platform
|
// TargetLocationFormat returns the full location of an entry (given the name) formatted for the current platform.
|
||||||
func TargetLocationFormat(targetLocationIncomplete string) string {
|
func TargetLocationFormat(targetLocationIncomplete string) string {
|
||||||
return EntryRoot + strings.ReplaceAll(targetLocationIncomplete, "/", PathSeparator)
|
return EntryRoot + strings.ReplaceAll(targetLocationIncomplete, "/", PathSeparator)
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -11,9 +11,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TargetIsFile TargetStatusCheck checks if the targetLocation is a file, directory, or is inaccessible
|
// TargetIsFile checks if the targetLocation is a file, directory, or is inaccessible.
|
||||||
// failCondition: 0 = fail on inaccessible, 1 = fail on inaccessible/file, 2 = fail on inaccessible/directory
|
// Requires: failCondition (0 = fail on inaccessible, 1 = fail on inaccessible&file, 2 = fail on inaccessible&directory).
|
||||||
// returns: isFile, isAccessible
|
// Returns: isFile, isAccessible.
|
||||||
func TargetIsFile(targetLocation string, errorOnFail bool, failCondition uint8) (bool, bool) {
|
func TargetIsFile(targetLocation string, errorOnFail bool, failCondition uint8) (bool, bool) {
|
||||||
targetInfo, err := os.Stat(targetLocation)
|
targetInfo, err := os.Stat(targetLocation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -39,7 +39,7 @@ func TargetIsFile(targetLocation string, errorOnFail bool, failCondition uint8)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteEntry writes entryData to an encrypted file at targetLocation
|
// WriteEntry writes entryData to an encrypted file at targetLocation.
|
||||||
func WriteEntry(targetLocation string, entryData []string, verifyEntryDoesNotExist bool) {
|
func WriteEntry(targetLocation string, entryData []string, verifyEntryDoesNotExist bool) {
|
||||||
if verifyEntryDoesNotExist {
|
if verifyEntryDoesNotExist {
|
||||||
_, isAccessible := TargetIsFile(targetLocation, false, 0)
|
_, isAccessible := TargetIsFile(targetLocation, false, 0)
|
||||||
@@ -57,7 +57,7 @@ func WriteEntry(targetLocation string, entryData []string, verifyEntryDoesNotExi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeToStdin writes a string to a command's stdin
|
// writeToStdin is a utility function that writes a string to a command's stdin.
|
||||||
func writeToStdin(cmd *exec.Cmd, input string) {
|
func writeToStdin(cmd *exec.Cmd, input string) {
|
||||||
stdin, err := cmd.StdinPipe()
|
stdin, err := cmd.StdinPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -73,7 +73,7 @@ func writeToStdin(cmd *exec.Cmd, input string) {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTempFile creates a temporary file and returns a pointer to it
|
// CreateTempFile creates a temporary file and returns a pointer to it.
|
||||||
func CreateTempFile() *os.File {
|
func CreateTempFile() *os.File {
|
||||||
tempFile, err := os.CreateTemp("", "*.markdown")
|
tempFile, err := os.CreateTemp("", "*.markdown")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -83,7 +83,7 @@ func CreateTempFile() *os.File {
|
|||||||
return tempFile
|
return tempFile
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveTrailingEmptyStrings removes empty strings from the end of a slice
|
// RemoveTrailingEmptyStrings removes empty strings from the end of a slice.
|
||||||
func RemoveTrailingEmptyStrings(slice []string) []string {
|
func RemoveTrailingEmptyStrings(slice []string) []string {
|
||||||
for i := len(slice) - 1; i >= 0; i-- {
|
for i := len(slice) - 1; i >= 0; i-- {
|
||||||
if slice[i] != "" {
|
if slice[i] != "" {
|
||||||
@@ -93,9 +93,9 @@ func RemoveTrailingEmptyStrings(slice []string) []string {
|
|||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StringGen generates a random string of a specified length and complexity
|
// StringGen generates a random string of a specified length and complexity.
|
||||||
// safeForFileName: if true, the generated string will only contain special characters that are safe for file names (only impacts complex strings)
|
// Requires: complexity (minimum percentage of special characters to be returned in the generated string; only impacts complex strings),
|
||||||
// complexity: minimum percentage of special characters to be returned in the generated string (only impacts complex strings)
|
// safeForFileName: (if true, the generated string will only contain special characters that are safe for file names; only impacts complex strings).
|
||||||
func StringGen(length int, complex bool, complexity float64, safeForFileName bool) string {
|
func StringGen(length int, complex bool, complexity float64, safeForFileName bool) string {
|
||||||
var actualSpecialChars int // track the number of special characters in the generated string
|
var actualSpecialChars int // track the number of special characters in the generated string
|
||||||
var minSpecialChars int // track the minimum number of special characters to accept
|
var minSpecialChars int // track the minimum number of special characters to accept
|
||||||
@@ -146,7 +146,7 @@ func StringGen(length int, complex bool, complexity float64, safeForFileName boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EntryIsNotEmpty iterates through entryData and returns true if any line is not empty
|
// EntryIsNotEmpty iterates through entryData and returns true if any line is not empty.
|
||||||
func EntryIsNotEmpty(entryData []string) bool {
|
func EntryIsNotEmpty(entryData []string) bool {
|
||||||
for _, line := range entryData {
|
for _, line := range entryData {
|
||||||
if line != "" {
|
if line != "" {
|
||||||
|
|||||||
+1
-3
@@ -2,12 +2,10 @@ package sync
|
|||||||
|
|
||||||
import "github.com/rwinkhart/libmutton/core"
|
import "github.com/rwinkhart/libmutton/core"
|
||||||
|
|
||||||
// define field separator constants
|
|
||||||
const (
|
const (
|
||||||
FSSpace = "\u259d" // ▝ space/list separator
|
FSSpace = "\u259d" // ▝ space/list separator
|
||||||
FSPath = "\u259e" // ▞ path separator
|
FSPath = "\u259e" // ▞ path separator
|
||||||
FSMisc = "\u259f" // ▟ misc. field separator (if \u259d is already used)
|
FSMisc = "\u259f" // ▟ misc. field separator (if \u259d is already used)
|
||||||
)
|
)
|
||||||
|
|
||||||
// rootLength stores length of core.EntryRoot string
|
var rootLength = len(core.EntryRoot) // length of core.EntryRoot string
|
||||||
var rootLength = len(core.EntryRoot)
|
|
||||||
|
|||||||
+20
-20
@@ -13,15 +13,15 @@ import (
|
|||||||
"golang.org/x/crypto/ssh/knownhosts"
|
"golang.org/x/crypto/ssh/knownhosts"
|
||||||
)
|
)
|
||||||
|
|
||||||
// global constants used only in this file
|
// ANSI color constants used only in this file
|
||||||
const (
|
const (
|
||||||
ansiDelete = "\033[38;5;1m"
|
ansiDelete = "\033[38;5;1m"
|
||||||
ansiDownload = "\033[38;5;2m"
|
ansiDownload = "\033[38;5;2m"
|
||||||
ansiUpload = "\033[38;5;4m"
|
ansiUpload = "\033[38;5;4m"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetSSHClient returns an SSH client connection to the server (also returns the remote EntryRoot as a string and the server's OS as a bool - IsWindows)
|
// GetSSHClient returns an SSH client connection to the server (also returns the remote EntryRoot and an indicator of the server's OS).
|
||||||
// only supports key-based authentication (passphrases are supported for CLI-based implementations)
|
// Only supports key-based authentication (passphrases are supported for CLI-based implementations).
|
||||||
func GetSSHClient(manualSync bool) (*ssh.Client, string, bool) {
|
func GetSSHClient(manualSync bool) (*ssh.Client, string, bool) {
|
||||||
// get SSH config info, exit if not configured (displaying an error if the sync job was called manually)
|
// get SSH config info, exit if not configured (displaying an error if the sync job was called manually)
|
||||||
var sshUserConfig []string
|
var sshUserConfig []string
|
||||||
@@ -99,7 +99,7 @@ func GetSSHClient(manualSync bool) (*ssh.Client, string, bool) {
|
|||||||
return sshClient, entryRoot, isWindows
|
return sshClient, entryRoot, isWindows
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSSHOutput runs a command over SSH and returns the output as a string
|
// GetSSHOutput runs a command over SSH and returns the output as a string.
|
||||||
func GetSSHOutput(sshClient *ssh.Client, cmd, stdin string) string {
|
func GetSSHOutput(sshClient *ssh.Client, cmd, stdin string) string {
|
||||||
// create a session
|
// create a session
|
||||||
sshSession, err := sshClient.NewSession()
|
sshSession, err := sshClient.NewSession()
|
||||||
@@ -126,7 +126,7 @@ func GetSSHOutput(sshClient *ssh.Client, cmd, stdin string) string {
|
|||||||
return outputString
|
return outputString
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRemoteDataFromClient returns a map of remote entries to their modification times, a list of remote folders, a list of queued deletions, and the current server+client times as UNIX timestamps
|
// getRemoteDataFromClient returns a map of remote entries to their modification times, a list of remote folders, a list of queued deletions, and the current server&client times as UNIX timestamps.
|
||||||
func getRemoteDataFromClient(sshClient *ssh.Client, manualSync bool) (map[string]int64, []string, []string, int64, int64) {
|
func getRemoteDataFromClient(sshClient *ssh.Client, manualSync bool) (map[string]int64, []string, []string, int64, int64) {
|
||||||
// get remote output over SSH
|
// get remote output over SSH
|
||||||
clientDeviceID, _ := os.ReadDir(core.ConfigDir + core.PathSeparator + "devices")
|
clientDeviceID, _ := os.ReadDir(core.ConfigDir + core.PathSeparator + "devices")
|
||||||
@@ -171,7 +171,7 @@ func getRemoteDataFromClient(sshClient *ssh.Client, manualSync bool) (map[string
|
|||||||
return entryModMap, folders, deletions, serverTime, clientTime
|
return entryModMap, folders, deletions, serverTime, clientTime
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLocalData returns a map of local entries to their modification times
|
// getLocalData returns a map of local entries to their modification times.
|
||||||
func getLocalData() map[string]int64 {
|
func getLocalData() map[string]int64 {
|
||||||
// get a list of all entries
|
// get a list of all entries
|
||||||
entries, _ := WalkEntryDir()
|
entries, _ := WalkEntryDir()
|
||||||
@@ -189,7 +189,7 @@ func getLocalData() map[string]int64 {
|
|||||||
return entryModMap
|
return entryModMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// targetLocationFormatSFTP formats the target location to match the remote server's entry directory and path separator
|
// targetLocationFormatSFTP formats the target location to match the remote server's entry directory and path separator.
|
||||||
func targetLocationFormatSFTP(targetName, serverEntryRoot string, serverIsWindows bool) string {
|
func targetLocationFormatSFTP(targetName, serverEntryRoot string, serverIsWindows bool) string {
|
||||||
if !serverIsWindows {
|
if !serverIsWindows {
|
||||||
return serverEntryRoot + targetName
|
return serverEntryRoot + targetName
|
||||||
@@ -198,7 +198,7 @@ func targetLocationFormatSFTP(targetName, serverEntryRoot string, serverIsWindow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sftpSync takes two slices of entries (one for downloads and one for uploads) and syncs them between the client and server using SFTP
|
// sftpSync takes two slices of entries (one for downloads and one for uploads) and syncs them between the client and server using SFTP.
|
||||||
func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, downloadList, uploadList []string) {
|
func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, downloadList, uploadList []string) {
|
||||||
// create an SFTP client from sshClient
|
// create an SFTP client from sshClient
|
||||||
sftpClient, err := sftp.NewClient(sshClient)
|
sftpClient, err := sftp.NewClient(sshClient)
|
||||||
@@ -323,8 +323,8 @@ func sftpSync(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows bool, dow
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// syncLists determines which entries need to be downloaded and uploaded for synchronizations and calls sftpSync with this information
|
// syncLists determines which entries need to be downloaded and uploaded for synchronizations and calls sftpSync with this information.
|
||||||
// using maps means that syncing will be done in an arbitrary order, but it is a worthy tradeoff for speed and simplicity
|
// Using maps means that syncing will be done in an arbitrary order, but it is a worthy tradeoff for speed and simplicity.
|
||||||
func syncLists(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows, timeSynced bool, localEntryModMap, remoteEntryModMap map[string]int64) {
|
func syncLists(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows, timeSynced bool, localEntryModMap, remoteEntryModMap map[string]int64) {
|
||||||
// initialize slices to store entries that need to be downloaded or uploaded
|
// initialize slices to store entries that need to be downloaded or uploaded
|
||||||
var downloadList, uploadList []string
|
var downloadList, uploadList []string
|
||||||
@@ -367,7 +367,7 @@ func syncLists(sshClient *ssh.Client, sshEntryRoot string, sshIsWindows, timeSyn
|
|||||||
fmt.Println("Client is synchronized with server")
|
fmt.Println("Client is synchronized with server")
|
||||||
}
|
}
|
||||||
|
|
||||||
// deletionSync removes entries from the client that have been deleted on the server (multi-client deletion)
|
// deletionSync removes entries from the client that have been deleted on the server (multi-client deletion).
|
||||||
func deletionSync(deletions []string) {
|
func deletionSync(deletions []string) {
|
||||||
var filesDeleted bool
|
var filesDeleted bool
|
||||||
for _, deletion := range deletions {
|
for _, deletion := range deletions {
|
||||||
@@ -381,8 +381,8 @@ 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
|
// 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)
|
// It 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(sshClient *ssh.Client, targetLocationIncomplete string) {
|
func ShearRemoteFromClient(sshClient *ssh.Client, targetLocationIncomplete string) {
|
||||||
deviceID := ShearLocal(targetLocationIncomplete, "") // remove the target from the local system and get the device ID of the client
|
deviceID := ShearLocal(targetLocationIncomplete, "") // remove the target from the local system and get the device ID of the client
|
||||||
|
|
||||||
@@ -394,8 +394,8 @@ func ShearRemoteFromClient(sshClient *ssh.Client, targetLocationIncomplete strin
|
|||||||
core.Exit(0) // sync is not required after shearing since the target has already been removed from the local system
|
core.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
|
// 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)
|
// It 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(sshClient *ssh.Client, oldLocationIncomplete, newLocationIncomplete string) {
|
func RenameRemoteFromClient(sshClient *ssh.Client, oldLocationIncomplete, newLocationIncomplete string) {
|
||||||
RenameLocal(oldLocationIncomplete, newLocationIncomplete, false) // move the target on the local system
|
RenameLocal(oldLocationIncomplete, newLocationIncomplete, false) // move the target on the local system
|
||||||
|
|
||||||
@@ -411,8 +411,8 @@ func RenameRemoteFromClient(sshClient *ssh.Client, oldLocationIncomplete, newLoc
|
|||||||
core.Exit(0)
|
core.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFolderRemoteFromClient creates a new entry-containing directory on the local system and calls the server to create the folder remotely
|
// 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)
|
// It 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(sshClient *ssh.Client, targetLocationIncomplete string) {
|
func AddFolderRemoteFromClient(sshClient *ssh.Client, targetLocationIncomplete string) {
|
||||||
AddFolderLocal(targetLocationIncomplete) // add the folder on the local system
|
AddFolderLocal(targetLocationIncomplete) // add the folder on the local system
|
||||||
GetSSHOutput(sshClient, "libmuttonserver addfolder", strings.ReplaceAll(targetLocationIncomplete, core.PathSeparator, FSPath)) // call the server to create the folder remotely
|
GetSSHOutput(sshClient, "libmuttonserver addfolder", strings.ReplaceAll(targetLocationIncomplete, core.PathSeparator, FSPath)) // call the server to create the folder remotely
|
||||||
@@ -420,7 +420,7 @@ func AddFolderRemoteFromClient(sshClient *ssh.Client, targetLocationIncomplete s
|
|||||||
core.Exit(0)
|
core.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// folderSync creates folders on the client (from the given list of folder names)
|
// folderSync creates folders on the client (from the given list of folder names).
|
||||||
func folderSync(folders []string) {
|
func folderSync(folders []string) {
|
||||||
for _, folder := range folders {
|
for _, folder := range folders {
|
||||||
// store the full local path of the folder
|
// store the full local path of the folder
|
||||||
@@ -438,8 +438,8 @@ func folderSync(folders []string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunJob runs the SSH sync job
|
// RunJob runs the SSH sync job.
|
||||||
// setting manualSync to true will throw errors if sync is not configured, as online mode is assumed
|
// Setting manualSync to true will throw errors if sync is not configured (online mode is assumed).
|
||||||
func RunJob(manualSync bool) {
|
func RunJob(manualSync bool) {
|
||||||
// get SSH client to re-use throughout the sync process
|
// get SSH client to re-use throughout the sync process
|
||||||
sshClient, sshEntryRoot, sshIsWindows := GetSSHClient(manualSync)
|
sshClient, sshEntryRoot, sshIsWindows := GetSSHClient(manualSync)
|
||||||
|
|||||||
+10
-10
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/rwinkhart/libmutton/core"
|
"github.com/rwinkhart/libmutton/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getModTimes returns a list of all entry modification times
|
// getModTimes returns a list of all entry modification times.
|
||||||
func getModTimes(entryList []string) []int64 {
|
func getModTimes(entryList []string) []int64 {
|
||||||
var modList []int64
|
var modList []int64
|
||||||
for _, file := range entryList {
|
for _, file := range entryList {
|
||||||
@@ -20,7 +20,7 @@ func getModTimes(entryList []string) []int64 {
|
|||||||
return modList
|
return modList
|
||||||
}
|
}
|
||||||
|
|
||||||
// genDeviceIDList returns a pointer to a slice of all registered device IDs
|
// genDeviceIDList returns a pointer to a slice of all registered device IDs.
|
||||||
func genDeviceIDList() *[]fs.DirEntry {
|
func genDeviceIDList() *[]fs.DirEntry {
|
||||||
// create a slice of all registered devices
|
// create a slice of all registered devices
|
||||||
deviceIDList, err := os.ReadDir(core.ConfigDir + core.PathSeparator + "devices")
|
deviceIDList, err := os.ReadDir(core.ConfigDir + core.PathSeparator + "devices")
|
||||||
@@ -31,10 +31,10 @@ func genDeviceIDList() *[]fs.DirEntry {
|
|||||||
return &deviceIDList
|
return &deviceIDList
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShearLocal removes the target file or directory from the local system
|
// ShearLocal removes the target file or directory from the local system.
|
||||||
// returns: deviceID (on client), for use in ShearRemoteFromClient
|
// Returns: deviceID (only 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)
|
// If the local system is a server, it will also add the target to the deletions list for all clients (except the requesting client).
|
||||||
// this function should only be used directly by the server binary
|
// This function should only be used directly by the server binary.
|
||||||
func ShearLocal(targetLocationIncomplete, clientDeviceID string) string {
|
func ShearLocal(targetLocationIncomplete, clientDeviceID string) string {
|
||||||
// determine if running on a server
|
// determine if running on a server
|
||||||
var onServer bool
|
var onServer bool
|
||||||
@@ -77,8 +77,8 @@ func ShearLocal(targetLocationIncomplete, clientDeviceID string) string {
|
|||||||
// do not exit program, as this function is used as part of ShearRemoteFromClient
|
// do not exit program, as this function is used as part of ShearRemoteFromClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenameLocal renames oldLocationIncomplete to newLocationIncomplete on the local system
|
// RenameLocal renames oldLocationIncomplete to newLocationIncomplete on the local system.
|
||||||
// this function should only be used directly by the server binary
|
// This function should only be used directly by the server binary.
|
||||||
func RenameLocal(oldLocationIncomplete, newLocationIncomplete string, verifyOldLocationExists bool) {
|
func RenameLocal(oldLocationIncomplete, newLocationIncomplete string, verifyOldLocationExists bool) {
|
||||||
// get full paths for both locations
|
// get full paths for both locations
|
||||||
oldLocation := core.TargetLocationFormat(oldLocationIncomplete)
|
oldLocation := core.TargetLocationFormat(oldLocationIncomplete)
|
||||||
@@ -104,8 +104,8 @@ func RenameLocal(oldLocationIncomplete, newLocationIncomplete string, verifyOldL
|
|||||||
// do not exit program, as this function is used as part of RenameRemoteFromClient
|
// do not exit program, as this function is used as part of RenameRemoteFromClient
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddFolderLocal creates a new entry-containing directory on the local system
|
// AddFolderLocal creates a new entry-containing directory on the local system.
|
||||||
// this function should only be used directly by the server binary
|
// This function should only be used directly by the server binary.
|
||||||
func AddFolderLocal(targetLocationIncomplete string) {
|
func AddFolderLocal(targetLocationIncomplete string) {
|
||||||
// get the full targetLocation path and create the target
|
// get the full targetLocation path and create the target
|
||||||
targetLocationComplete := core.TargetLocationFormat(targetLocationIncomplete)
|
targetLocationComplete := core.TargetLocationFormat(targetLocationIncomplete)
|
||||||
|
|||||||
+3
-3
@@ -11,8 +11,8 @@ import (
|
|||||||
"github.com/rwinkhart/libmutton/core"
|
"github.com/rwinkhart/libmutton/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WalkEntryDir walks the entry directory and returns lists of all files and directories found (two separate lists)
|
// 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)
|
// Regardless of platform, all paths are stored with forward slashes (UNIX-style).
|
||||||
func WalkEntryDir() ([]string, []string) {
|
func WalkEntryDir() ([]string, []string) {
|
||||||
// define file/directory containing slices so that they may be accessed by the anonymous WalkDir function
|
// define file/directory containing slices so that they may be accessed by the anonymous WalkDir function
|
||||||
var fileList []string
|
var fileList []string
|
||||||
@@ -49,7 +49,7 @@ func WalkEntryDir() ([]string, []string) {
|
|||||||
return fileList, dirList
|
return fileList, dirList
|
||||||
}
|
}
|
||||||
|
|
||||||
// joinErrorWithEXE joins and returns the two strings it is provided (in error format) with the executable name inserted between them
|
// joinErrorWithEXE is a utility function that joins and returns the two strings it is provided (in error format) with the executable name inserted between them.
|
||||||
func joinErrorWithEXE(firstHalf, secondHalf string) string {
|
func joinErrorWithEXE(firstHalf, secondHalf string) string {
|
||||||
return core.AnsiError + firstHalf + os.Args[0] + secondHalf + core.AnsiReset
|
return core.AnsiError + firstHalf + os.Args[0] + secondHalf + core.AnsiReset
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/rwinkhart/libmutton/core"
|
"github.com/rwinkhart/libmutton/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WalkEntryDir walks the entry directory and returns lists of all files and directories found (two separate lists)
|
// 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)
|
// Regardless of platform, all paths are stored with forward slashes (UNIX-style).
|
||||||
func WalkEntryDir() ([]string, []string) {
|
func WalkEntryDir() ([]string, []string) {
|
||||||
// define file/directory containing slices so that they may be accessed by the anonymous WalkDir function
|
// define file/directory containing slices so that they may be accessed by the anonymous WalkDir function
|
||||||
var fileList []string
|
var fileList []string
|
||||||
@@ -50,7 +50,7 @@ func WalkEntryDir() ([]string, []string) {
|
|||||||
return fileList, dirList
|
return fileList, dirList
|
||||||
}
|
}
|
||||||
|
|
||||||
// joinErrorWithEXE joins and returns the two strings it is provided (in error format) with the executable name inserted between them
|
// joinErrorWithEXE is a utility function that joins and returns the two strings it is provided (in error format) with the executable name inserted between them.
|
||||||
func joinErrorWithEXE(firstHalf, secondHalf string) string {
|
func joinErrorWithEXE(firstHalf, secondHalf string) string {
|
||||||
return core.AnsiError + firstHalf + os.Args[0][strings.LastIndex(os.Args[0], "\\")+1:] + secondHalf + core.AnsiReset
|
return core.AnsiError + firstHalf + os.Args[0][strings.LastIndex(os.Args[0], "\\")+1:] + secondHalf + core.AnsiReset
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -11,10 +11,10 @@ import (
|
|||||||
"github.com/rwinkhart/libmutton/core"
|
"github.com/rwinkhart/libmutton/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeviceIDGen generates a new client device ID and registers it with the server
|
// DeviceIDGen generates a new client device ID and registers it with the server.
|
||||||
// device IDs are only needed for online synchronization
|
// Device IDs are only needed for online synchronization.
|
||||||
// device IDs are guaranteed unique as the current UNIX time is appended to them
|
// Device IDs are guaranteed unique as the current UNIX time is appended to them.
|
||||||
// returns the remote EntryRoot and OS type (OS type is a bool: core.IsWindows)
|
// Returns: the remote EntryRoot and OS type indicator.
|
||||||
func DeviceIDGen() (string, string) {
|
func DeviceIDGen() (string, string) {
|
||||||
deviceIDPrefix, _ := os.Hostname()
|
deviceIDPrefix, _ := os.Hostname()
|
||||||
deviceIDSuffix := core.StringGen(rand.Intn(32)+48, true, 0.2, true) + "-" + strconv.FormatInt(time.Now().Unix(), 10)
|
deviceIDSuffix := core.StringGen(rand.Intn(32)+48, true, 0.2, true) + "-" + strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
|
|||||||
+4
-3
@@ -2,15 +2,16 @@ package sync
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
// inputKeyFilePassphrase prompts the user for a passphrase for an SSH key file
|
// inputKeyFilePassphrase prompts the user for a passphrase for an SSH key file.
|
||||||
// TODO support non-CLI implementations
|
// TODO support non-CLI implementations
|
||||||
func inputKeyFilePassphrase() []byte {
|
func inputKeyFilePassphrase() []byte {
|
||||||
fmt.Print("\nEnter passphrase for your SSH keyfile: ")
|
fmt.Print("\nEnter passphrase for your SSH keyfile: ")
|
||||||
passphrase, _ := terminal.ReadPassword(int(os.Stdin.Fd()))
|
passphrase, _ := term.ReadPassword(int(os.Stdin.Fd()))
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
return passphrase
|
return passphrase
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -9,9 +9,9 @@ import (
|
|||||||
"github.com/rwinkhart/libmutton/core"
|
"github.com/rwinkhart/libmutton/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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 FSSpace
|
// Lists in output are separated by FSSpace.
|
||||||
// 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(clientDeviceID string) {
|
func GetRemoteDataFromServer(clientDeviceID string) {
|
||||||
entryList, dirList := WalkEntryDir()
|
entryList, dirList := WalkEntryDir()
|
||||||
modList := getModTimes(entryList)
|
modList := getModTimes(entryList)
|
||||||
|
|||||||
Reference in New Issue
Block a user