mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-09-02 07:07:26 -04:00
Add entry refresh feature; fix ClampTrailingWhitespace ignoring the initial trim
This commit is contained in:
+3
-3
@@ -13,16 +13,16 @@ func GetOldEntryData(targetLocation string, field int) ([]string, error) {
|
|||||||
back.TargetIsFile(targetLocation, true, 2)
|
back.TargetIsFile(targetLocation, true, 2)
|
||||||
|
|
||||||
// read old entry data
|
// read old entry data
|
||||||
unencryptedEntry, err := crypt.DecryptFileToSlice(targetLocation)
|
decryptedEntry, err := crypt.DecryptFileToSlice(targetLocation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("unable to decrypt entry: " + err.Error())
|
return nil, errors.New("unable to decrypt entry: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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), nil
|
return ensureSliceLength(decryptedEntry, field), nil
|
||||||
} else {
|
} else {
|
||||||
return unencryptedEntry, nil
|
return decryptedEntry, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+65
-7
@@ -8,26 +8,83 @@ import (
|
|||||||
"github.com/rwinkhart/go-boilerplate/back"
|
"github.com/rwinkhart/go-boilerplate/back"
|
||||||
"github.com/rwinkhart/libmutton/crypt"
|
"github.com/rwinkhart/libmutton/crypt"
|
||||||
"github.com/rwinkhart/libmutton/global"
|
"github.com/rwinkhart/libmutton/global"
|
||||||
|
"github.com/rwinkhart/libmutton/synccommon"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WriteEntry writes entryData to an encrypted file at targetLocation.
|
// WriteEntry writes entryData to an encrypted file at targetLocation.
|
||||||
func WriteEntry(targetLocation string, entryData []byte) error {
|
func WriteEntry(targetLocation string, decBytes []byte) error {
|
||||||
encBytes := crypt.EncryptBytes(entryData)
|
err := os.WriteFile(targetLocation, crypt.EncryptBytes(decBytes), 0600)
|
||||||
err := os.WriteFile(targetLocation, encBytes, 0600)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to write to file: " + err.Error())
|
return errors.New("unable to write to file: " + err.Error())
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EntryRefresh re-encrypts all libmutton entries with a new passphrase
|
||||||
|
// and optimizes each entry to ensure they are as slim as possible.
|
||||||
|
// This includes stripping trailing whitespace/newlines/carriage returns
|
||||||
|
// from each field and running each note through ClampTrailingWhitespace
|
||||||
|
// to ensure each note line is optimized as possible without breaking
|
||||||
|
// Markdown formatting.
|
||||||
|
func EntryRefresh(oldRCWPassphrase, newRCWPassphrase []byte, removeOldDir bool) error {
|
||||||
|
// ensure global.EntryRoot+"-new" and global.EntryRoot-"old" do not exist
|
||||||
|
dirEnds := []string{"-new", "-old"}
|
||||||
|
for i, dirEnd := range dirEnds {
|
||||||
|
if i == 1 && !removeOldDir {
|
||||||
|
if _, err := os.Stat(global.EntryRoot + dirEnd); !os.IsNotExist(err) {
|
||||||
|
return errors.New("unable to refresh entries: \"" + global.EntryRoot + "-new\" already exists")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
os.RemoveAll(global.EntryRoot + "-new")
|
||||||
|
}
|
||||||
|
|
||||||
|
// create output directory structure (global.EntryRoot + "-new"/*)
|
||||||
|
entries, folders, err := synccommon.WalkEntryDir()
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("unable to walk entry directory: " + err.Error())
|
||||||
|
}
|
||||||
|
for _, folder := range folders {
|
||||||
|
fullPath := global.EntryRoot + "-new" + strings.ReplaceAll(folder, "/", global.PathSeparator)
|
||||||
|
err := os.MkdirAll(fullPath, 0700)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("unable to create temporary directory \"" + fullPath + "\": " + err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrypt, optimize, and re-encrypt each entry
|
||||||
|
for _, entry := range entries {
|
||||||
|
decryptedEntry, err := crypt.DecryptFileToSlice(global.TargetLocationFormat(entry))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// strip trailing whitespace...
|
||||||
|
fieldsMain := decryptedEntry[:4]
|
||||||
|
fieldsNote := back.RemoveTrailingEmptyStrings(decryptedEntry[4:])
|
||||||
|
// ...from each non-note field
|
||||||
|
for i, line := range fieldsMain {
|
||||||
|
fieldsMain[i] = strings.TrimRight(line, " \t\r\n")
|
||||||
|
}
|
||||||
|
// ...and from each note line (preserve Markdown formatting)
|
||||||
|
ClampTrailingWhitespace(fieldsNote)
|
||||||
|
|
||||||
|
// re-combine fields
|
||||||
|
decryptedEntry = append(fieldsMain, fieldsNote...)
|
||||||
|
|
||||||
|
// write the entry to the new directory
|
||||||
|
WriteEntry(global.EntryRoot+"-new"+strings.ReplaceAll(entry, "/", global.PathSeparator), []byte(strings.Join(decryptedEntry, "\n")))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ClampTrailingWhitespace strips trailing newlines, carriage returns, and tabs from each line in a note.
|
// ClampTrailingWhitespace strips trailing newlines, carriage returns, and tabs from each line in a note.
|
||||||
// Additionally, it removes single trailing spaces and truncates multiple trailing spaces to two (for Markdown formatting).
|
// Additionally, it removes single trailing spaces and truncates multiple trailing spaces to two (for Markdown formatting).
|
||||||
func ClampTrailingWhitespace(note []string) {
|
func ClampTrailingWhitespace(note []string) {
|
||||||
for i, line := range note {
|
for i, line := range note {
|
||||||
// remove trailing tabs, carriage returns, and newlines
|
// remove trailing tabs, carriage returns, and newlines
|
||||||
note[i] = strings.TrimRight(line, "\t\r\n")
|
line = strings.TrimRight(line, "\t\r\n")
|
||||||
|
|
||||||
// determine the number of trailing spaces
|
// determine the number of trailing spaces in the trimmed line
|
||||||
var endSpacesCount int
|
var endSpacesCount int
|
||||||
for j := len(line) - 1; j >= 0; j-- {
|
for j := len(line) - 1; j >= 0; j-- {
|
||||||
if line[j] != ' ' {
|
if line[j] != ' ' {
|
||||||
@@ -39,9 +96,10 @@ func ClampTrailingWhitespace(note []string) {
|
|||||||
// remove single spaces, truncate multiple spaces (leave two for Markdown formatting)
|
// remove single spaces, truncate multiple spaces (leave two for Markdown formatting)
|
||||||
switch endSpacesCount {
|
switch endSpacesCount {
|
||||||
case 0:
|
case 0:
|
||||||
// do nothing
|
// no trailing spaces
|
||||||
|
note[i] = line
|
||||||
case 1:
|
case 1:
|
||||||
// remove the trailing space
|
// remove the single trailing space
|
||||||
note[i] = strings.TrimRight(line, " ")
|
note[i] = strings.TrimRight(line, " ")
|
||||||
default:
|
default:
|
||||||
// truncate the trailing spaces to two
|
// truncate the trailing spaces to two
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ func GenDeviceIDList() ([]fs.DirEntry, error) {
|
|||||||
// create a slice of all registered devices
|
// create a slice of all registered devices
|
||||||
deviceIDList, err := os.ReadDir(ConfigDir + PathSeparator + "devices")
|
deviceIDList, err := os.ReadDir(ConfigDir + PathSeparator + "devices")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("unable to read the devices directory: " + err.Error())
|
return nil, errors.New("unable to read devices directory: " + err.Error())
|
||||||
}
|
}
|
||||||
return deviceIDList, nil
|
return deviceIDList, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,12 +17,12 @@ import (
|
|||||||
func GetRemoteDataFromServer(clientDeviceID string) error {
|
func GetRemoteDataFromServer(clientDeviceID string) error {
|
||||||
entryList, dirList, err := synccommon.WalkEntryDir()
|
entryList, dirList, err := synccommon.WalkEntryDir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to walk the entry directory: " + err.Error())
|
return errors.New("unable to walk entry directory: " + err.Error())
|
||||||
}
|
}
|
||||||
modList := synccommon.GetModTimes(entryList)
|
modList := synccommon.GetModTimes(entryList)
|
||||||
deletionsList, err := os.ReadDir(global.ConfigDir + global.PathSeparator + "deletions")
|
deletionsList, err := os.ReadDir(global.ConfigDir + global.PathSeparator + "deletions")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to read the deletions directory: " + err.Error())
|
return errors.New("unable to read deletions directory: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// print the current UNIX timestamp to stdout
|
// print the current UNIX timestamp to stdout
|
||||||
|
|||||||
Reference in New Issue
Block a user