Skip to content

Commit

Permalink
Merge branch 'develop' of github.com:JackGruber/joplin-plugin-backup …
Browse files Browse the repository at this point in the history
…into develop
  • Loading branch information
JackGruber committed Dec 3, 2023
2 parents 6f55285 + cce465a commit de8f5fc
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 88 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A plugin to extend Joplin with a manual and automatic backup function.
<!-- markdownlint-disable MD028 -->
<!-- markdownlint-disable MD007 -->

<img src=img/main.jpg>
<img src=img/main.png>

<!-- prettier-ignore-start -->
<!-- TOC depthfrom:2 orderedlist:false -->
Expand Down
4 changes: 3 additions & 1 deletion __test__/backup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import * as path from "path";
import { when } from "jest-when";
import { sevenZip } from "../src/sevenZip";
import joplin from "api";
import { I18n } from "i18n";

function getTestPaths(): any {
const testPath: any = {};
Expand Down Expand Up @@ -58,6 +57,7 @@ describe("Backup", function () {
when(spyOnGlobalValue)
.mockImplementation(() => Promise.resolve("no mockImplementation"))
.calledWith("profileDir").mockImplementation(() => Promise.resolve(testPath.joplinProfile))
.calledWith("locale").mockImplementation(() => Promise.resolve("en_US"))
.calledWith("templateDir").mockImplementation(() => Promise.resolve(testPath.templates));

await createTestStructure();
Expand All @@ -81,6 +81,8 @@ describe("Backup", function () {
spyOnShowError = jest
.spyOn(backup, "showError")
.mockImplementation(() => {});

await backup.confLocale(path.join(__dirname, "..", "src", "locales"));
});

afterEach(async () => {
Expand Down
Binary file removed img/main.jpg
Binary file not shown.
Binary file added img/main.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 24 additions & 23 deletions src/Backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class Backup {
retryInDefaultLocale: true,
syncFiles: true,
directory: localesDir,
objectNotation: true,
});
i18n.setLocale(joplinLocale);
this.log.verbose("localesDir: " + localesDir);
Expand Down Expand Up @@ -117,7 +118,7 @@ class Backup {
await joplin.settings.setValue("backupVersion", version);
} catch (e) {
await this.showError(
i18n.__("error.PluginUpgrade", checkVersion, e.message)
i18n.__("msg.error.PluginUpgrade", checkVersion, e.message)
);
}
}
Expand Down Expand Up @@ -177,7 +178,7 @@ class Backup {
this.password = null;

await this.showMsg(
await this.getTranslation("error.passwordDoubleQuotes")
await this.getTranslation("msg.error.passwordDoubleQuotes")
);
} else {
this.passwordEnabled = true;
Expand Down Expand Up @@ -282,15 +283,15 @@ class Backup {
try {
fs.mkdirSync(this.backupBasePath);
} catch (e) {
await this.showError(i18n.__("error.folderCreation", e.message));
await this.showError(i18n.__("msg.error.folderCreation", e.message));
}
}
}

if (path.normalize(profileDir) === this.backupBasePath) {
this.backupBasePath = null;
await this.showError(
i18n.__("error.backupPathJoplinDir", path.normalize(profileDir))
i18n.__("msg.error.backupPathJoplinDir", path.normalize(profileDir))
);
}
}
Expand All @@ -317,7 +318,7 @@ class Backup {
) {
this.backupSetName = "{YYYYMMDDHHmm}";
await this.showError(
i18n.__("error.BackupSetNotSupportedChars", '\\/:*?"<>|')
i18n.__("msg.error.BackupSetNotSupportedChars", '\\/:*?"<>|')
);
}

Expand Down Expand Up @@ -454,13 +455,13 @@ class Backup {
await this.logSettings(showDoneMsg);

if (this.backupBasePath === null) {
await this.showError(i18n.__("error.ConfigureBackupPath"));
await this.showError(i18n.__("msg.error.ConfigureBackupPath"));
return;
}

if (fs.existsSync(this.backupBasePath)) {
if ((await this.checkPassword()) === -1) {
await this.showError(i18n.__("error.PasswordMatch"));
await this.showError(i18n.__("msg.error.PasswordMissMatch"));
return;
} else {
this.log.info("Enable password protection: " + this.passwordEnabled);
Expand Down Expand Up @@ -495,7 +496,7 @@ class Backup {
this.suppressErrorMsgUntil = 0;

if (showDoneMsg === true) {
await this.showMsg(i18n.__("backup.Completed"));
await this.showMsg(i18n.__("msg.backup.completed"));
}
} else {
const now = new Date();
Expand All @@ -511,7 +512,7 @@ class Backup {
this.log.info("Error dialog suppressed");
} else {
await this.showError(
i18n.__("error.BackupPathDontExist", this.backupBasePath)
i18n.__("msg.error.BackupPathDontExist", this.backupBasePath)
);

if (showDoneMsg === false) {
Expand All @@ -532,7 +533,7 @@ class Backup {
);

if (showDoneMsg === true) {
await this.showError(i18n.__("error.BackupAlreadyRunning"));
await this.showError(i18n.__("msg.error.BackupAlreadyRunning"));
}
}
}
Expand Down Expand Up @@ -726,7 +727,7 @@ class Backup {
try {
fs.mkdirSync(exportPath);
} catch (e) {
await this.showError(i18n.__("error.folderCreation", +e.message));
await this.showError(i18n.__("msg.error.folderCreation", e.message));
}
}
await this.exportNotebooks(notebooks.ids, exportPath, this.exportFormat);
Expand Down Expand Up @@ -793,7 +794,7 @@ class Backup {
file
);
} catch (e) {
await this.showError(i18n.__("error.Backup", format, +e.message));
await this.showError(i18n.__("msg.error.Backup", format, e.message));
throw e;
}
}
Expand Down Expand Up @@ -912,7 +913,7 @@ class Backup {
fs.emptyDirSync(dir);
return dir;
} catch (e) {
await this.showError(i18n.__("error.folderCreation:", e.message));
await this.showError(i18n.__("msg.error.folderCreation:", e.message));
throw e;
}
}
Expand Down Expand Up @@ -977,7 +978,7 @@ class Backup {
return true;
} catch (e) {
await this.showError(
i18n.__("error.fileCopy", "backupFolder", e.message)
i18n.__("msg.error.fileCopy", "backupFolder", e.message)
);
throw e;
}
Expand Down Expand Up @@ -1038,7 +1039,7 @@ class Backup {
fs.moveSync(src, backupDestination);
} catch (e) {
await this.showError(
i18n.__("error.fileCopy", "moveFinishedBackup", e.message)
i18n.__("msg.error.fileCopy", "moveFinishedBackup", e.message)
);
throw e;
}
Expand All @@ -1054,7 +1055,7 @@ class Backup {
fs.moveSync(zipFile, backupDestination);
} catch (e) {
await this.showError(
i18n.__("error.fileCopy", "moveFinishedBackup", e.message)
i18n.__("msg.error.fileCopy", "moveFinishedBackup", e.message)
);
throw e;
}
Expand All @@ -1071,7 +1072,7 @@ class Backup {
});
} catch (e) {
await this.showError(
i18n.__("error.fileCopy", "moveFinishedBackup", e.message)
i18n.__("msg.error.fileCopy", "moveFinishedBackup", e.message)
);
this.log.error(
path.join(this.activeBackupPath, file) + " => " + dst
Expand All @@ -1087,7 +1088,7 @@ class Backup {
});
} catch (e) {
await this.showError(
i18n.__("error.fileCopy", "moveFinishedBackup", e.message)
i18n.__("msg.error.fileCopy", "moveFinishedBackup", e.message)
);
throw e;
}
Expand All @@ -1113,7 +1114,7 @@ class Backup {
fs.removeSync(path.join(backupPath, file));
} catch (e) {
await this.showError(
i18n.__("error.deleteFile", "clearBackupTarget", e.message)
i18n.__("msg.error.deleteFile", "clearBackupTarget", e.message)
);
throw e;
}
Expand All @@ -1124,7 +1125,7 @@ class Backup {
fs.removeSync(path.join(backupPath, "notes"));
} catch (e) {
await this.showError(
i18n.__("error.deleteFile", "clearBackupTarget", e.message)
i18n.__("msg.error.deleteFile", "clearBackupTarget", e.message)
);
throw e;
}
Expand All @@ -1133,7 +1134,7 @@ class Backup {
fs.removeSync(path.join(backupPath, "templates"));
} catch (e) {
await this.showError(
i18n.__("error.deleteFile", "clearBackupTarget", e.message)
i18n.__("msg.error.deleteFile", "clearBackupTarget", e.message)
);
throw e;
}
Expand All @@ -1142,7 +1143,7 @@ class Backup {
fs.removeSync(path.join(backupPath, "profile"));
} catch (e) {
await this.showError(
i18n.__("error.deleteFile", "clearBackupTarget", e.message)
i18n.__("msg.error.deleteFile", "clearBackupTarget", e.message)
);
throw e;
}
Expand Down Expand Up @@ -1185,7 +1186,7 @@ class Backup {
}
} catch (e) {
await this.showError(
i18n.__("error.deleteFile", "deleteOldBackupSets", e.message)
i18n.__("msg.error.deleteFile", "deleteOldBackupSets", e.message)
);
throw e;
}
Expand Down
136 changes: 90 additions & 46 deletions src/locales/en_US.json
Original file line number Diff line number Diff line change
@@ -1,48 +1,92 @@
{
"settings.path": "Backup path",
"settings.exportPath": "Temporary export path",
"settings.exportPath.description": "Temporary path for note export from Joplin, before they are copyed to backup destination",
"settings.backupRetention": "Keep x backups",
"settings.backupRetention.description": "If more than one version is configured, folders are created in the Backup Path acording to backupSetName setting",
"settings.backupInterval": "Backup interval in hours",
"settings.backupInterval.description": "0 = disable automatic backup",
"settings.onlyOnChange": "Only on change",
"settings.onlyOnChange.description": "Creates a backup at the specified backup interval only if there was a change",
"settings.usePassword": "Password protected backups",
"settings.usePassword.description": "Protect the backups via encrypted archive",
"settings.password": "Password",
"settings.password.description": "If a password has been entered, the backups are protected with a password",
"settings.passwordRepeat": "Password (Repeat)",
"settings.passwordRepeat.description": "Repeat password to validate",
"settings.fileLogLevel": "Loglevel",
"settings.createSubfolder": "Create Subfolder",
"settings.createSubfolder.description": "Create a subfolder in the the configured `Backup path`. Deactivate only if there is no other data in the `Backup path`!",
"settings.zipArchive": "Create archive",
"settings.zipArchive.description": "If a password protected backups is set, an archive is always created",
"settings.compressionLevel": "Compression level",
"settings.compressionLevel.description": "Compression level for archive",
"settings.backupSetName": "Backup set name",
"settings.backupSetName.description": "Name of the backup set if multiple backups are to be keep",
"settings.backupPlugins": "Backup plugins",
"settings.backupPlugins.description": "Backup plugin jpl files (No plugin settings!)",
"settings.exportFormat": "Export format",
"settings.exportFormat.description": "Backup format for the notes",
"settings.singleJex": "Single JEX",
"settings.singleJex.description": "Create only one JEX file for all notebooks (Recommended to prevent the loss of internal note links and folder structure)",
"settings.execFinishCmd": "Command on Backup finish",
"settings.execFinishCmd.description": "Execute command when backup is finished",
"backup.Completed": "Backup completed",
"error.PluginUpgrade": "Upgrade error %s: %s",
"error.folderCreation": "Error on folder creation: %s",
"error.ConfigureBackupPath": "Please configure backup path in Joplin Tools > Options > Backup",
"error.error.PasswordMatch": "Passwords do not match!",
"error.BackupPathDontExist": "The Backup path '%s' does not exist!",
"error.BackupAlreadyRunning": "A backup is already running!",
"error.Backup": "Backup error for %s: %s",
"error.fileCopy": "Error on file/folder copy in %s: %s",
"error.deleteFile": "Error on file/folder delete in %s: %s",
"error.backupPathJoplinDir": "The backup path is the Joplin profile directory (%s) without subfolders, this is not allowed!",
"command.createBackup": "Create backup",
"error.BackupSetNotSupportedChars": "Backup set name does contain not allowed characters ( %s )!",
"error.passwordDoubleQuotes": "Password contains \" (double quotes), these are not allowed because of a bug. Password protection for the backup is deactivated!"
"msg": {
"backup": {
"completed": "Backup completed"
},
"error": {
"PluginUpgrade": "Upgrade error %s: %s",
"folderCreation": "Error on folder creation: %s",
"ConfigureBackupPath": "Please configure backup path in Joplin Tools > Options > Backup",
"PasswordMissMatch": "Passwords do not match!",
"BackupPathDontExist": "The Backup path '%s' does not exist!",
"BackupAlreadyRunning": "A backup is already running!",
"Backup": "Backup error for %s: %s",
"fileCopy": "Error on file/folder copy in %s: %s",
"deleteFile": "Error on file/folder delete in %s: %s",
"backupPathJoplinDir": "The backup path is the Joplin profile directory (%s) without subfolders, this is not allowed!",
"BackupSetNotSupportedChars": "Backup set name does contain not allowed characters ( %s )!",
"passwordDoubleQuotes": "Password contains \" (double quotes), these are not allowed because of a bug. Password protection for the backup is deactivated!"
}
},
"settings": {
"path": {
"label": "Backup path"
},
"exportPath": {
"label": "Temporary export path",
"description": "Temporary path for note export from Joplin, before they are copyed to backup destination"
},
"backupRetention": {
"label": "Keep x backups",
"description": "If more than one version is configured, folders are created in the Backup Path acording to backupSetName setting"
},
"backupInterval": {
"label": "Backup interval in hours",
"description": "0 = disable automatic backup"
},
"onlyOnChange": {
"label": "Only on change",
"description": "Creates a backup at the specified backup interval only if there was a change"
},
"usePassword": {
"label": "Password protected backups",
"description": "Protect the backups via encrypted archive"
},
"password": {
"label": "Password",
"description": "If a password has been entered, the backups are protected with a password"
},
"passwordRepeat": {
"label": "Password (Repeat)",
"description": "Repeat password to validate"
},
"fileLogLevel": {
"label": "Loglevel"
},
"createSubfolder": {
"label": "Create Subfolder",
"description": "Create a subfolder in the the configured `Backup path`. Deactivate only if there is no other data in the `Backup path`!"
},
"zipArchive": {
"label": "Create archive",
"description": "If a password protected backups is set, an archive is always created"
},
"compressionLevel": {
"label": "Compression level",
"description": "Compression level for archive"
},
"backupSetName": {
"label": "Backup set name",
"description": "Name of the backup set if multiple backups are to be keep"
},
"backupPlugins": {
"label": "Backup plugins",
"description": "Backup plugin jpl files (No plugin settings!)"
},
"exportFormat": {
"label": "Export format",
"description": "Backup format for the notes"
},
"singleJex": {
"label": "Single JEX",
"description": "Create only one JEX file for all notebooks (Recommended to prevent the loss of internal note links and folder structure)"
},
"execFinishCmd": {
"label": "Command on Backup finish",
"description": "Execute command when backup is finished"
}
},
"command": {
"createBackup": "Create backup"
}
}
Loading

0 comments on commit de8f5fc

Please sign in to comment.