From 6e92ac394fc26c41c27dc812a28c540bb493bccd Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 11:41:26 +0100 Subject: [PATCH 01/14] feat: add new settings for dryRun --- src/settings.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/settings.ts b/src/settings.ts index 70b447f3..2aa1620b 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -294,6 +294,32 @@ export class GithubPublisherSettingsTab extends PluginSettingTab { await this.plugin.saveSettings(); }) ); + new Setting(this.settingsPage) + .setName("Dry run") + .setDesc("Disable GitHub push and all other action and only perform a dry-run to see what would be pushed") + .addToggle((toggle) => + toggle + .setValue(githubSettings.dryRun.enable) + .onChange(async (value) => { + githubSettings.dryRun.enable = value; + await this.plugin.saveSettings(); + this.renderSettingsPage(EnumbSettingsTabId.github); + }) + ); + if (githubSettings.dryRun.enable) { + new Setting(this.settingsPage) + .setName("Folder where file will be copied") + .setDesc("Use {{owner}}, {{repo}} and {{branch}} to dynamically create the folder name.") + .addText((text) => + text + .setPlaceholder("github-publisher") + .setValue(githubSettings.dryRun.folderName) + .onChange(async (value) => { + githubSettings.dryRun.folderName = value.trim(); + await this.plugin.saveSettings(); + }) + ); + } new Setting(this.settingsPage) .setClass("no-display") From 4c23a3a293ab3502a9b8b62738d7d159ffe08248 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 11:41:45 +0100 Subject: [PATCH 02/14] disable new branch when dryRun --- src/GitHub/branch.ts | 4 +++- src/commands/index.ts | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/GitHub/branch.ts b/src/GitHub/branch.ts index 39629591..020cbaf8 100644 --- a/src/GitHub/branch.ts +++ b/src/GitHub/branch.ts @@ -206,8 +206,10 @@ export class GithubBranch extends FilesManagement { * @returns {Promise} True if the update is successful */ async updateRepository( - repoFrontmatter: RepoFrontmatter | RepoFrontmatter[] + repoFrontmatter: RepoFrontmatter | RepoFrontmatter[], + dryRun = false ): Promise { + if (dryRun) return true; repoFrontmatter = Array.isArray(repoFrontmatter) ? repoFrontmatter : [repoFrontmatter]; diff --git a/src/commands/index.ts b/src/commands/index.ts index 6095139d..2f97379f 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -181,7 +181,8 @@ export async function shareOneNote( repo: repository }; if (!isValid) return false; - await PublisherManager.newBranch(repoFrontmatter); + if (!settings.github.dryRun.enable) + await PublisherManager.newBranch(repoFrontmatter); const publishSuccess = await PublisherManager.publish( file, true, @@ -206,7 +207,7 @@ export async function shareOneNote( } } const update = await PublisherManager.updateRepository( - repoFrontmatter + repoFrontmatter, settings.github.dryRun.enable ); if (update) { await publisherNotification( From 990897f41473f8db6ef967d6b3080c1fbd5e429a Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 11:43:55 +0100 Subject: [PATCH 03/14] remove usuless text --- src/GitHub/delete.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHub/delete.ts b/src/GitHub/delete.ts index 66d622e4..68e91311 100644 --- a/src/GitHub/delete.ts +++ b/src/GitHub/delete.ts @@ -283,7 +283,7 @@ async function checkIndexFiles( { owner: repoFrontmatter.owner, repo: repoFrontmatter.repo, - path: path, + path, } ); if (fileRequest.status === 200) { From 910875d799c6ef930f695d395d3ba99418e2789e Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 11:44:10 +0100 Subject: [PATCH 04/14] send the file to the folder when dryrun --- src/GitHub/upload.ts | 127 ++++++++++++++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 31 deletions(-) diff --git a/src/GitHub/upload.ts b/src/GitHub/upload.ts index 7911c8ee..8f9b94bb 100644 --- a/src/GitHub/upload.ts +++ b/src/GitHub/upload.ts @@ -4,8 +4,10 @@ import { Base64 } from "js-base64"; import { arrayBufferToBase64, MetadataCache, + normalizePath, Notice, TFile, + TFolder, Vault, } from "obsidian"; @@ -330,7 +332,7 @@ export default class Publisher { const embeddedUploaded = embeded.uploaded; embeddedUploaded.push(uploaded); - if (autoclean && repo.autoclean) { + if (autoclean && repo.autoclean && !this.settings.github.dryRun) { deleted = await deleteFromGithub( true, this.branchName, @@ -433,6 +435,7 @@ export default class Publisher { properties: MonoProperties, ) { const imageBin = await this.vault.readBinary(imageFile); + const repoFrontmatter = properties.frontmatter.repo; let image64 = arrayBufferToBase64(imageBin); if (imageFile.name.includes("excalidraw")) { const svg = await convertToHTMLSVG(imageFile, this.vault); @@ -446,6 +449,33 @@ export default class Publisher { this.settings, properties.frontmatter.general ); + if (this.settings.github.dryRun.enable) { + const folderName = this.settings.github.dryRun.folderName + .replace("{{repo}}", repoFrontmatter.repo) + .replace("{{branch}}", this.branchName) + .replace("{{owner}}", repoFrontmatter.owner); + const dryRunPath = normalizePath(`${folderName}/${path}`); + const isAlreadyExist = this.vault.getAbstractFileByPath(dryRunPath); + if (isAlreadyExist && isAlreadyExist instanceof TFile) { + const needToByUpdated = isAlreadyExist.stat.mtime > imageFile.stat.mtime; + if (needToByUpdated) { + this.vault.modifyBinary(isAlreadyExist, imageBin); + } + return { + isUpdated: needToByUpdated, + file: imageFile.name + }; + } + const folder = dryRunPath.split("/").slice(0, -1).join("/"); + const folderExists = this.vault.getAbstractFileByPath(folder); + if (!folderExists || !(folderExists instanceof TFolder)) + await this.vault.createFolder(folder); + await this.vault.createBinary(path, imageBin); + return { + isUpdated: true, + file: imageFile.name + }; + } return await this.upload(image64, path, "", properties.frontmatter.repo); } @@ -463,8 +493,35 @@ export default class Publisher { text: string, path: string, title: string = "", - repoFrontmatter: RepoFrontmatter + repoFrontmatter: RepoFrontmatter, ): Promise { + if (this.settings.github.dryRun.enable) { + //create a new file in the vault + const folderName = this.settings.github.dryRun.folderName + .replace("{{repo}}", repoFrontmatter.repo) + .replace("{{branch}}", this.branchName) + .replace("{{owner}}", repoFrontmatter.owner); + + const newPath = normalizePath(`${folderName}/${path}`); + const isAlreadyExist = this.vault.getAbstractFileByPath(newPath); + if (isAlreadyExist && isAlreadyExist instanceof TFile) { + //modify + await this.vault.modify(isAlreadyExist, text); + return { + isUpdated: true, + file: title + }; + } //create + const folder = newPath.split("/").slice(0, -1).join("/"); + const folderExists = this.vault.getAbstractFileByPath(folder); + if (!folderExists || !(folderExists instanceof TFolder)) + await this.vault.createFolder(folder); + await this.vault.create(newPath, text); + return { + isUpdated: false, + file: title + }; + } try { const contentBase64 = Base64.encode(text).toString(); return await this.upload( @@ -491,6 +548,7 @@ export default class Publisher { repoFrontmatter: RepoFrontmatter | RepoFrontmatter[] ): Promise { if (metadataExtractor) { + if (this.settings.github.dryRun.enable) return; for (const file of Object.values(metadataExtractor)) { if (file) { const contents = await this.vault.adapter.read(file); @@ -521,6 +579,7 @@ export default class Publisher { */ async workflowGestion(repoFrontmatter: RepoFrontmatter): Promise { + if (this.settings.github.dryRun.enable) return false; let finished = false; if (repoFrontmatter.workflowName.length === 0) { return false; @@ -579,42 +638,48 @@ export default class Publisher { properties.frontmatter.general ); const repoFrontmatter = properties.frontmatter; - try { - if (forcePushAttachment(file, this.settings)) { - newLinkedFiles.push(file); - continue; - } - //first search if the file exists - const response = await this.octokit.request( - "GET /repos/{owner}/{repo}/contents/{path}", - { - owner: repoFrontmatter.repo.owner, - repo: repoFrontmatter.repo.repo, - path: imagePath, - ref: this.branchName, - }); - if (response.status === 200) { - const reply = await this.octokit.request( - "GET /repos/{owner}/{repo}/commits", + if (this.settings.github.dryRun.enable) { + newLinkedFiles.push(file); + continue; + } + if (!this.settings.github.dryRun.enable) { + try { + if (forcePushAttachment(file, this.settings)) { + newLinkedFiles.push(file); + continue; + } + //first search if the file exists + const response = await this.octokit.request( + "GET /repos/{owner}/{repo}/contents/{path}", { owner: repoFrontmatter.repo.owner, repo: repoFrontmatter.repo.repo, path: imagePath, - sha: this.branchName, + ref: this.branchName, }); - if (reply.status === 200) { - const data = reply.data; - const lastEditedInRepo = data[0]?.commit?.committer?.date; - const lastEditedDate = lastEditedInRepo ? new Date(lastEditedInRepo) : undefined; - const lastEditedAttachment = new Date(file.stat.mtime); - //if the file in the vault is newer than the file in the repo, push it - if (lastEditedDate && lastEditedAttachment > lastEditedDate || !lastEditedDate) { - newLinkedFiles.push(file); - } else logs({ settings: this.settings }, i18next.t("error.alreadyExists", { file: file.name })); + if (response.status === 200) { + const reply = await this.octokit.request( + "GET /repos/{owner}/{repo}/commits", + { + owner: repoFrontmatter.repo.owner, + repo: repoFrontmatter.repo.repo, + path: imagePath, + sha: this.branchName, + }); + if (reply.status === 200) { + const data = reply.data; + const lastEditedInRepo = data[0]?.commit?.committer?.date; + const lastEditedDate = lastEditedInRepo ? new Date(lastEditedInRepo) : undefined; + const lastEditedAttachment = new Date(file.stat.mtime); + //if the file in the vault is newer than the file in the repo, push it + if (lastEditedDate && lastEditedAttachment > lastEditedDate || !lastEditedDate) { + newLinkedFiles.push(file); + } else logs({ settings: this.settings }, i18next.t("error.alreadyExists", { file: file.name })); + } } + } catch (e) { + newLinkedFiles.push(file); } - } catch (e) { - newLinkedFiles.push(file); } } else { newLinkedFiles.push(file); From 0a2e7d17a902556bfbf7313bcdb080c5f4bef10a Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 11:44:22 +0100 Subject: [PATCH 05/14] add dryRun ssettings in parseFrontmatter and global settings --- src/settings/interface.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/settings/interface.ts b/src/settings/interface.ts index fcfc74f4..a2e5825b 100644 --- a/src/settings/interface.ts +++ b/src/settings/interface.ts @@ -60,6 +60,10 @@ export interface GitHubPublisherSettings { branch: string; tokenPath: string; automaticallyMergePR: boolean; + dryRun: { + enable: boolean; + folderName: string; + } api: { tiersForApi: GithubTiersVersion; hostname: string; @@ -216,6 +220,10 @@ export const DEFAULT_SETTINGS: Partial = { repo: "", branch: "main", automaticallyMergePR: true, + dryRun: { + enable: false, + folderName: "github-publisher", + }, tokenPath: TOKEN_PATH, api: { tiersForApi: GithubTiersVersion.free, @@ -382,6 +390,10 @@ export interface RepoFrontmatter { automaticallyMergePR: boolean; verifiedRepo?: boolean; path?: Path; + dryRun: { + enable: boolean; + folderName: string; + } } export interface ListEditedFiles { From 714973d0568531049e53f89c5d473c2497ca0ae8 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 11:44:39 +0100 Subject: [PATCH 06/14] optimize the repoFrontmatter and add DryRun --- src/utils/parse_frontmatter.ts | 40 ++++++++-------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/src/utils/parse_frontmatter.ts b/src/utils/parse_frontmatter.ts index 519587be..1244b63d 100644 --- a/src/utils/parse_frontmatter.ts +++ b/src/utils/parse_frontmatter.ts @@ -144,11 +144,12 @@ export function getRepoFrontmatter( branch: github.branch, repo: github.repo, owner: github.user, - autoclean: settings.upload.autoclean.enable, + autoclean: settings.github.dryRun.enable ? false : settings.upload.autoclean.enable, workflowName: github.workflow.name, commitMsg: github.workflow.commitMessage, automaticallyMergePR: github.automaticallyMergePR, verifiedRepo: github.verifiedRepo ?? false, + dryRun: settings.github.dryRun }; if (settings.upload.behavior === FolderSettings.fixed) { repoFrontmatter.autoclean = false; @@ -220,15 +221,7 @@ function parseMultipleRepo( ) { for (const repo of frontmatter.multipleRepo) { if (typeof repo === "object") { - const repository: RepoFrontmatter = { - branch: repoFrontmatter.branch, - repo: repoFrontmatter.repo, - owner: repoFrontmatter.owner, - autoclean: false, - automaticallyMergePR: repoFrontmatter.automaticallyMergePR, - workflowName: repoFrontmatter.workflowName, - commitMsg: repoFrontmatter.commitMsg - }; + const repository: RepoFrontmatter = JSON.parse(JSON.stringify(repoFrontmatter)); if (repo.branch !== undefined) { repository.branch = repo.branch; } @@ -245,15 +238,7 @@ function parseMultipleRepo( } else { //is string const repoString = repo.split("/"); - const repository: RepoFrontmatter = { - branch: repoFrontmatter.branch, - repo: repoFrontmatter.repo, - owner: repoFrontmatter.owner, - autoclean: false, - automaticallyMergePR: repoFrontmatter.automaticallyMergePR, - workflowName: repoFrontmatter.workflowName, - commitMsg: repoFrontmatter.commitMsg - }; + const repository: RepoFrontmatter = JSON.parse(JSON.stringify(repoFrontmatter)); multipleRepo.push( repositoryStringSlice(repoString, repository) ); @@ -289,9 +274,9 @@ function multipleShortKeyRepo(frontmatter: FrontMatterCache, allRepo: Repository if (smartKey === "default") { multipleRepo.push(repoFrontmatter); } else { - const shortRepo = allRepo.filter((repo) => { + const shortRepo = allRepo.find((repo) => { return repo.smartKey.toLowerCase() === smartKey; - })[0]; + }); if (shortRepo) { let repo = { branch: shortRepo.branch, @@ -300,7 +285,8 @@ function multipleShortKeyRepo(frontmatter: FrontMatterCache, allRepo: Repository autoclean: repoFrontmatter.autoclean, automaticallyMergePR: shortRepo.automaticallyMergePR, workflowName: shortRepo.workflow.name, - commitMsg: shortRepo.workflow.commitMessage + commitMsg: shortRepo.workflow.commitMessage, + dryRun: repoFrontmatter.dryRun } as RepoFrontmatter; const parsedPath = parsePath(setting, shortRepo, repo); repo = Array.isArray(parsedPath) ? parsedPath[0] : parsedPath; @@ -329,15 +315,7 @@ function multipleShortKeyRepo(frontmatter: FrontMatterCache, allRepo: Repository */ function repositoryStringSlice(repo: string, repoFrontmatter: RepoFrontmatter): RepoFrontmatter { - const newRepo: RepoFrontmatter = { - branch: repoFrontmatter.branch, - repo: repoFrontmatter.repo, - owner: repoFrontmatter.owner, - autoclean: false, - automaticallyMergePR: repoFrontmatter.automaticallyMergePR, - workflowName: repoFrontmatter.workflowName, - commitMsg: repoFrontmatter.commitMsg - }; + const newRepo: RepoFrontmatter = JSON.parse(JSON.stringify(repoFrontmatter)); if (repo.length >= 4) { newRepo.branch = repo[2]; newRepo.repo = repo[1]; From 3d0e2a9f0797c9b4e34da59b6797bc9b0d45aa90 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 15:15:17 +0100 Subject: [PATCH 07/14] add dryRun clean settings based on autoclean --- src/utils/parse_frontmatter.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/utils/parse_frontmatter.ts b/src/utils/parse_frontmatter.ts index 1244b63d..e6de55e6 100644 --- a/src/utils/parse_frontmatter.ts +++ b/src/utils/parse_frontmatter.ts @@ -149,7 +149,10 @@ export function getRepoFrontmatter( commitMsg: github.workflow.commitMessage, automaticallyMergePR: github.automaticallyMergePR, verifiedRepo: github.verifiedRepo ?? false, - dryRun: settings.github.dryRun + dryRun: { + ...settings.github.dryRun, + autoclean: settings.upload.autoclean.enable && settings.github.dryRun.enable + } }; if (settings.upload.behavior === FolderSettings.fixed) { repoFrontmatter.autoclean = false; From e27793e7fc96d935756c45ef966abd5d47bb5d1c Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 15:15:23 +0100 Subject: [PATCH 08/14] allow autoclean with dryRun --- src/GitHub/delete.ts | 71 +++++++++++++++++++++++++++++++++++++-- src/settings/interface.ts | 1 + 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/src/GitHub/delete.ts b/src/GitHub/delete.ts index 68e91311..79f0961e 100644 --- a/src/GitHub/delete.ts +++ b/src/GitHub/delete.ts @@ -1,7 +1,7 @@ import { Octokit } from "@octokit/core"; import i18next from "i18next"; import { Base64 } from "js-base64"; -import { Notice, parseYaml } from "obsidian"; +import { MetadataCache, normalizePath, Notice, parseYaml, TFile, TFolder } from "obsidian"; import { Deleted, @@ -65,6 +65,7 @@ async function deleteFromGithubOneRepo( repoProperties: MonoRepoProperties, ): Promise { const repo = repoProperties.frontmatter; + if (repo.dryRun.autoclean) return cleanDryRun(silent, filesManagement, repoProperties); if (!repo.autoclean) return {success: false, deleted: [], undeleted: []}; const getAllFile = await filesManagement.getAllFileFromRepo( branchName, @@ -189,7 +190,7 @@ function excludedFileFromDelete( for (const excludedFile of autoCleanExcluded) { const isRegex = excludedFile.match(FIND_REGEX); const regex = isRegex ? new RegExp(isRegex[1], isRegex[2]) : null; - if (regex && regex.test(file)) { + if (regex?.test(file)) { return true; } else if ( file.trim().includes(excludedFile.trim()) && @@ -310,3 +311,69 @@ async function checkIndexFiles( } return false; } + +function cleanDryRun( + silent: boolean = false, + filesManagement: FilesManagement, repoProperties: MonoRepoProperties): Deleted { + const {vault, settings} = filesManagement; + const app = filesManagement.plugin.app; + const repo = repoProperties.frontmatter; + const dryRunFolderPath = normalizePath(repo.dryRun.folderName.replace("{{owner}}", repo.owner).replace("{{repo}}", repo.repo).replace("{{branch}}", repo.branch)); + const dryRunFolder = vault.getAbstractFileByPath(dryRunFolderPath); + if (!dryRunFolder || dryRunFolder instanceof TFile) return {success: false, deleted: [], undeleted: []}; + const dryRunFolderChildren = (dryRunFolder as TFolder).children; + const dryRunFiles = dryRunFolderChildren.filter((file) => { + return file instanceof TFile; + }); + const allSharedFiles = filesManagement.getAllFileWithPath(repoProperties.repo).map((file) => { + return { converted: file.converted, repo: file.repoFrontmatter }; + }); + let deletedSuccess = 0; + const result: Deleted = { + deleted: [], + undeleted: [], + success: false, + }; + for (const file of dryRunFiles) { + const isInObsidian = allSharedFiles.some( + (f) => f.converted === file.path + ); + const isMarkdownForAnotherRepo = file.path.trim().endsWith(".md") ? + !allSharedFiles.some( + (f) => { + let repoFrontmatter = f.repo; + if (Array.isArray(repoFrontmatter)) { + repoFrontmatter = repoFrontmatter.find((r) => JSON.stringify(r.repo) === JSON.stringify(repo.repo)); + } return f.converted === file.path && repoFrontmatter; + }) + : false; + const isNeedToBeDeleted = isInObsidian ? isMarkdownForAnotherRepo : true; + if (isNeedToBeDeleted) { + const indexFile = (file.path.contains(settings.upload.folderNote.rename)) ? indexFileDryRun(file as TFile, app.metadataCache) : false; + if (!indexFile) { + notif({settings}, `[DRYRUN] trying to delete file : ${file.path} from ${repo.owner}/${repo.repo}`); + vault.trash(file, false); + deletedSuccess++; + } + } + + } + const successMsg = i18next.t("deletion.noFile") ; + if (!silent) + new Notice(successMsg); + result.success = deletedSuccess === 0; + return result; +} + +function indexFileDryRun(file: TFile, metadataCache: MetadataCache):boolean { + const frontmatter = metadataCache.getFileCache(file)?.frontmatter; + if (frontmatter) { + const index = frontmatter.index; + const deleteFile = frontmatter.delete; + const share = frontmatter.share; + if (index === true || deleteFile === false || share === false) { + return true; + } + } + return false; +} \ No newline at end of file diff --git a/src/settings/interface.ts b/src/settings/interface.ts index a2e5825b..adb034aa 100644 --- a/src/settings/interface.ts +++ b/src/settings/interface.ts @@ -393,6 +393,7 @@ export interface RepoFrontmatter { dryRun: { enable: boolean; folderName: string; + autoclean: boolean; } } From dac77f3da93aa08f90cae079b8a6b6a9a16b0f8a Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 17:59:28 +0100 Subject: [PATCH 09/14] recursive delete in dryRun --- src/GitHub/delete.ts | 43 ++++++++++++++++++++++++------- src/GitHub/files.ts | 2 +- src/GitHub/upload.ts | 6 ++--- src/commands/index.ts | 18 ++++++++----- src/utils/data_validation_test.ts | 1 + 5 files changed, 49 insertions(+), 21 deletions(-) diff --git a/src/GitHub/delete.ts b/src/GitHub/delete.ts index 79f0961e..15ea44c9 100644 --- a/src/GitHub/delete.ts +++ b/src/GitHub/delete.ts @@ -1,7 +1,7 @@ import { Octokit } from "@octokit/core"; import i18next from "i18next"; import { Base64 } from "js-base64"; -import { MetadataCache, normalizePath, Notice, parseYaml, TFile, TFolder } from "obsidian"; +import { MetadataCache, normalizePath, Notice, parseYaml, TAbstractFile, TFile, TFolder, Vault } from "obsidian"; import { Deleted, @@ -318,12 +318,15 @@ function cleanDryRun( const {vault, settings} = filesManagement; const app = filesManagement.plugin.app; const repo = repoProperties.frontmatter; - const dryRunFolderPath = normalizePath(repo.dryRun.folderName.replace("{{owner}}", repo.owner).replace("{{repo}}", repo.repo).replace("{{branch}}", repo.branch)); + const dryRunFolderPath = normalizePath(repo.dryRun.folderName + .replace("{{owner}}", repo.owner) + .replace("{{repo}}", repo.repo) + .replace("{{branch}}", repo.branch)); const dryRunFolder = vault.getAbstractFileByPath(dryRunFolderPath); if (!dryRunFolder || dryRunFolder instanceof TFile) return {success: false, deleted: [], undeleted: []}; - const dryRunFolderChildren = (dryRunFolder as TFolder).children; - const dryRunFiles = dryRunFolderChildren.filter((file) => { - return file instanceof TFile; + const dryRunFiles:TFile[] = []; + Vault.recurseChildren(dryRunFolder as TFolder, (file: TAbstractFile) => { + if (!excludedFileFromDelete(normalizePath(file.path.replace(dryRunFolderPath, "")), settings) && (isAttachment(file.path) || file.path.match("md$")) && file instanceof TFile) dryRunFiles.push(file); }); const allSharedFiles = filesManagement.getAllFileWithPath(repoProperties.repo).map((file) => { return { converted: file.converted, repo: file.repoFrontmatter }; @@ -334,9 +337,11 @@ function cleanDryRun( undeleted: [], success: false, }; + const deletedFolder: TAbstractFile[] = []; for (const file of dryRunFiles) { + const convertedPath = normalizePath(file.path.replace(dryRunFolderPath, "")); const isInObsidian = allSharedFiles.some( - (f) => f.converted === file.path + (f) => f.converted === convertedPath ); const isMarkdownForAnotherRepo = file.path.trim().endsWith(".md") ? !allSharedFiles.some( @@ -344,21 +349,39 @@ function cleanDryRun( let repoFrontmatter = f.repo; if (Array.isArray(repoFrontmatter)) { repoFrontmatter = repoFrontmatter.find((r) => JSON.stringify(r.repo) === JSON.stringify(repo.repo)); - } return f.converted === file.path && repoFrontmatter; + } return f.converted === convertedPath && repoFrontmatter; }) : false; const isNeedToBeDeleted = isInObsidian ? isMarkdownForAnotherRepo : true; if (isNeedToBeDeleted) { - const indexFile = (file.path.contains(settings.upload.folderNote.rename)) ? indexFileDryRun(file as TFile, app.metadataCache) : false; + const indexFile = (convertedPath.contains(settings.upload.folderNote.rename)) ? indexFileDryRun(file as TFile, app.metadataCache) : false; if (!indexFile) { - notif({settings}, `[DRYRUN] trying to delete file : ${file.path} from ${repo.owner}/${repo.repo}`); + notif({settings}, `[DRYRUN] trying to delete file : ${file.path} from ${dryRunFolderPath}`); vault.trash(file, false); deletedSuccess++; + deletedFolder.push(file); } } + } + //recursive delete empty folder in dryRunFolder + //empty folder are folder with children.length === 0 + const dryRunFolders:TFolder[] = []; + Vault.recurseChildren(vault.getAbstractFileByPath(dryRunFolderPath) as TFolder, (file: TAbstractFile) => { + if (file instanceof TFolder) { + dryRunFolders.push(file); + } + }); + for (const folder of dryRunFolders.reverse()) { + const children = folder.children.filter((child) => !deletedFolder.includes(child)); + if (children.length === 0) { + deletedFolder.push(folder); + vault.trash(folder, false); + deletedSuccess++; + } } - const successMsg = i18next.t("deletion.noFile") ; + + const successMsg = deletedSuccess > 0 ? (i18next.t("deletion.success", {nb: deletedSuccess.toString()})) : i18next.t("deletion.noFile"); if (!silent) new Notice(successMsg); result.success = deletedSuccess === 0; diff --git a/src/GitHub/files.ts b/src/GitHub/files.ts index c2feff05..6de7fddb 100644 --- a/src/GitHub/files.ts +++ b/src/GitHub/files.ts @@ -89,7 +89,7 @@ export class FilesManagement extends Publisher { */ getAllFileWithPath(repo: Repository | null): ConvertedLink[] { - const files = this.vault.getFiles(); + const files = this.vault.getFiles().filter((x) => !x.path.startsWith(this.settings.github.dryRun.folderName)); const allFileWithPath: ConvertedLink[] = []; for (const file of files) { if (isAttachment(file.name)) { diff --git a/src/GitHub/upload.ts b/src/GitHub/upload.ts index 8f9b94bb..467a65e3 100644 --- a/src/GitHub/upload.ts +++ b/src/GitHub/upload.ts @@ -332,7 +332,7 @@ export default class Publisher { const embeddedUploaded = embeded.uploaded; embeddedUploaded.push(uploaded); - if (autoclean && repo.autoclean && !this.settings.github.dryRun) { + if ((autoclean && repo.autoclean) || repo.dryRun.autoclean) { deleted = await deleteFromGithub( true, this.branchName, @@ -452,7 +452,7 @@ export default class Publisher { if (this.settings.github.dryRun.enable) { const folderName = this.settings.github.dryRun.folderName .replace("{{repo}}", repoFrontmatter.repo) - .replace("{{branch}}", this.branchName) + .replace("{{branch}}", repoFrontmatter.branch) .replace("{{owner}}", repoFrontmatter.owner); const dryRunPath = normalizePath(`${folderName}/${path}`); const isAlreadyExist = this.vault.getAbstractFileByPath(dryRunPath); @@ -499,7 +499,7 @@ export default class Publisher { //create a new file in the vault const folderName = this.settings.github.dryRun.folderName .replace("{{repo}}", repoFrontmatter.repo) - .replace("{{branch}}", this.branchName) + .replace("{{branch}}", repoFrontmatter.branch) .replace("{{owner}}", repoFrontmatter.owner); const newPath = normalizePath(`${folderName}/${path}`); diff --git a/src/commands/index.ts b/src/commands/index.ts index 2f97379f..fb1ada6c 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -134,19 +134,23 @@ export async function purgeNotesRemote( monoRepo: MonoRepoProperties, ): Promise { try { + const noticeFragment = document.createDocumentFragment(); + noticeFragment.createSpan({ cls: ["obsidian-publisher", "notification"] }).innerHTML = i18next.t("informations.startingClean", { repo: monoRepo.frontmatter }); new Notice( - i18next.t("informations.startingClean", {repo: monoRepo.frontmatter}) + noticeFragment ); - const isValid = checkRepositoryValidityWithRepoFrontmatter(PublisherManager, monoRepo.frontmatter); + const isValid = await checkRepositoryValidityWithRepoFrontmatter(PublisherManager, monoRepo.frontmatter); if (!isValid) return false; - await PublisherManager.newBranch(monoRepo.frontmatter); + if (!PublisherManager.settings.github.dryRun.enable) + await PublisherManager.newBranch(monoRepo.frontmatter); const deleted = await deleteFromGithub( false, branchName, PublisherManager, monoRepo ); - await PublisherManager.updateRepository(monoRepo.frontmatter); + if (!PublisherManager.settings.github.dryRun.enable) + await PublisherManager.updateRepository(monoRepo.frontmatter); if (PublisherManager.settings.plugin.displayModalRepoEditing) new ListChangedFiles(PublisherManager.plugin.app, deleted).open(); } catch (e) { notif({settings: PublisherManager.settings, e: true}, e); @@ -276,7 +280,7 @@ export async function shareNewNote( ); const statusBarElement = plugin.addStatusBarItem(); - const isValid = checkRepositoryValidityWithRepoFrontmatter(PublisherManager, monoRepo.frontmatter, newlySharedNotes.length); + const isValid = await checkRepositoryValidityWithRepoFrontmatter(PublisherManager, monoRepo.frontmatter, newlySharedNotes.length); if (!isValid) return false; await PublisherManager.newBranch(monoRepo.frontmatter); await shareAllMarkedNotes( @@ -326,7 +330,7 @@ export async function shareAllEditedNotes( ); const statusBarElement = plugin.addStatusBarItem(); - const isValid = checkRepositoryValidityWithRepoFrontmatter(PublisherManager, monoRepo.frontmatter, newlySharedNotes.length); + const isValid = await checkRepositoryValidityWithRepoFrontmatter(PublisherManager, monoRepo.frontmatter, newlySharedNotes.length); if (!isValid) return false; await PublisherManager.newBranch(monoRepo.frontmatter); await shareAllMarkedNotes( @@ -372,7 +376,7 @@ export async function shareOnlyEdited( (i18next.t("informations.foundNoteToSend", {nbNotes: newlySharedNotes.length})) ); const statusBarElement = PublisherManager.plugin.addStatusBarItem(); - const isValid = checkRepositoryValidityWithRepoFrontmatter(PublisherManager, repoFrontmatter, newlySharedNotes.length); + const isValid = await checkRepositoryValidityWithRepoFrontmatter(PublisherManager, repoFrontmatter, newlySharedNotes.length); if (!isValid) return false; await PublisherManager.newBranch(repoFrontmatter); await shareAllMarkedNotes( diff --git a/src/utils/data_validation_test.ts b/src/utils/data_validation_test.ts index afaa3561..4100bd8d 100644 --- a/src/utils/data_validation_test.ts +++ b/src/utils/data_validation_test.ts @@ -318,6 +318,7 @@ export async function checkRepositoryValidityWithRepoFrontmatter( numberOfFile: number=1 ): Promise { const settings = PublisherManager.settings; + if (settings.github.dryRun.enable) return true; try { /** * verify for each repoFrontmatter if verifiedRepo is true From d8eb7c437c1dbd151feeb2589a8dc1aaa1584b80 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 18:43:00 +0100 Subject: [PATCH 10/14] adjust submenu when sharing a excluded file or from dryRun --- src/commands/file_menu.ts | 29 ++++++++++++----------- src/utils/data_validation_test.ts | 38 +++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/commands/file_menu.ts b/src/commands/file_menu.ts index a9aafe6e..7774fc77 100644 --- a/src/commands/file_menu.ts +++ b/src/commands/file_menu.ts @@ -3,7 +3,7 @@ import { Menu, MenuItem, Platform, TFile, TFolder} from "obsidian"; import GithubPublisher from "../main"; import {MonoRepoProperties, Repository} from "../settings/interface"; -import {defaultRepo, getRepoSharedKey, isShared, multipleSharedKey} from "../utils/data_validation_test"; +import {defaultRepo, getRepoSharedKey, isExcludedPath, isInDryRunFolder, isShared, multipleSharedKey} from "../utils/data_validation_test"; import { getRepoFrontmatter } from "../utils/parse_frontmatter"; import {shareAllMarkedNotes, shareOneNote} from "."; import {ChooseRepoToRun} from "./suggest_other_repo_commands_modal"; @@ -46,21 +46,24 @@ export async function shareFolderRepo(plugin: GithubPublisher, folder: TFolder, export function addSubMenuCommandsFolder(plugin: GithubPublisher, item: MenuItem, folder: TFolder, branchName: string, originalMenu: Menu): Menu { //@ts-ignore const subMenu = Platform.isDesktop ? item.setSubmenu() as Menu : originalMenu; - subMenu.addItem((subItem) => { - subItem - .setTitle(i18next.t("commands.shareViewFiles.multiple.on", { - smartKey: i18next.t("common.default").toUpperCase(), - doc: folder.name - })) - .setIcon("folder-up") - .onClick(async () => { - const repo = getRepoSharedKey(plugin.settings, undefined); - await shareFolderRepo(plugin, folder, branchName, repo); - }); - }); + if (!isExcludedPath(plugin.settings,folder, defaultRepo(plugin.settings))) { + subMenu.addItem((subItem) => { + subItem + .setTitle(i18next.t("commands.shareViewFiles.multiple.on", { + smartKey: i18next.t("common.default").toUpperCase(), + doc: folder.name + })) + .setIcon("folder-up") + .onClick(async () => { + const repo = getRepoSharedKey(plugin.settings, undefined); + await shareFolderRepo(plugin, folder, branchName, repo); + }); + }); + } const activatedRepoCommands = plugin.settings.github.otherRepo.filter((repo) => repo.createShortcuts); if (activatedRepoCommands.length > 0) { activatedRepoCommands.forEach((otherRepo) => { + if (isInDryRunFolder(plugin.settings, otherRepo, folder)) return; subMenu.addItem((item) => { item.setTitle( i18next.t("commands.shareViewFiles.multiple.on", { diff --git a/src/utils/data_validation_test.ts b/src/utils/data_validation_test.ts index 4100bd8d..f8c2ebe0 100644 --- a/src/utils/data_validation_test.ts +++ b/src/utils/data_validation_test.ts @@ -1,6 +1,6 @@ import { Octokit } from "@octokit/core"; import i18next from "i18next"; -import {FrontMatterCache, Notice, TFile} from "obsidian"; +import {FrontMatterCache, normalizePath,Notice, TFile, TFolder} from "obsidian"; import GithubPublisher from "src/main"; import {GithubBranch} from "../GitHub/branch"; @@ -31,10 +31,10 @@ export function isInternalShared( if (properties.repository?.shareAll?.enable) { const excludedFileName = properties.repository.shareAll.excludedFileName; - return !file.basename.startsWith(excludedFileName); + return !file.basename.startsWith(excludedFileName) && !isInDryRunFolder(properties.settings, properties.repository, file); } if (!frontmatter) return false; - if (isExcludedPath(properties.settings, file)) return false; + if (isExcludedPath(properties.settings, file, properties.repository)) return false; const shareKey = properties.repository?.shareKey || properties.settings.plugin.shareKey; logs({settings: properties.settings}, "shareKey", shareKey, "frontmatter", frontmatter[shareKey]); if (frontmatter[shareKey] == null || frontmatter[shareKey] === undefined || ["false", "0", "no"].includes(frontmatter[shareKey].toString().toLowerCase())) return false; @@ -80,7 +80,7 @@ export function isShared( const otherRepoWithShareAll = settings.github.otherRepo.filter((repo) => repo.shareAll?.enable); if (!settings.plugin.shareAll?.enable && otherRepoWithShareAll.length === 0) { const shareKey = otherRepo ? otherRepo.shareKey : settings.plugin.shareKey; - if ( meta == null || !meta[shareKey] || meta[shareKey] == null || isExcludedPath(settings, file) || meta[shareKey] === undefined || ["false", "0", "no"].includes(meta[shareKey].toString().toLowerCase())) { + if ( meta == null || !meta[shareKey] || meta[shareKey] == null || isExcludedPath(settings, file, otherRepo) || meta[shareKey] === undefined || ["false", "0", "no"].includes(meta[shareKey].toString().toLowerCase())) { return false; } const shareKeyInFrontmatter:string = meta[shareKey].toString().toLowerCase(); @@ -88,8 +88,8 @@ export function isShared( } else if (settings.plugin.shareAll?.enable || otherRepoWithShareAll.length > 0) { const allExcludedFileName = otherRepoWithShareAll.map((repo) => repo.shareAll!.excludedFileName); allExcludedFileName.push(settings.plugin.shareAll!.excludedFileName); - if (allExcludedFileName.some(prefix => !file.basename.startsWith(prefix)) && !isExcludedPath(settings, file)) { - return true; + if (allExcludedFileName.some(prefix => !file.basename.startsWith(prefix))) { + return !isExcludedPath(settings, file, otherRepo); } } return false; @@ -100,16 +100,22 @@ export function isShared( * @param file {TFile} * @returns boolean */ -function isExcludedPath(settings: GitHubPublisherSettings, file: TFile):boolean { +export function isExcludedPath(settings: GitHubPublisherSettings, file: TFile | TFolder, repository: Repository | null):boolean { const excludedFolder = settings.plugin.excludedFolder; + if (settings.plugin.shareAll?.enable || repository?.shareAll?.enable) { + const excludedFromShare = repository?.shareAll?.excludedFileName ?? settings.plugin.shareAll?.excludedFileName; + if (excludedFromShare && file.name.startsWith(excludedFromShare)) { + return true; + } + } for (const folder of excludedFolder) { const isRegex = folder.match(FIND_REGEX); const regex = isRegex ? new RegExp(isRegex[1], isRegex[2]) : null; - if ((regex && regex.test(file.path)) || file.path.contains(folder.trim())) { + if ((regex?.test(file.path)) || file.path.contains(folder.trim())) { return true; } } - return false; + return isInDryRunFolder(settings, repository, file); } @@ -423,4 +429,18 @@ export function isFolderNote(properties: MultiProperties) { return filename === model; } return false; +} + +export function isInDryRunFolder(settings: GitHubPublisherSettings, repo: Repository | null, file: TFile | TFolder) { + if (!settings.github.dryRun.enable) return false; + const variables = { + owner: repo?.user ?? settings.github.user, + repo: repo?.repo ?? settings.github.repo, + branch: repo?.branch ?? settings.github.branch, + }; + const folder = settings.github.dryRun.folderName + .replace("{{owner}}", variables.owner) + .replace("{{repo}}", variables.repo) + .replace("{{branch}}", variables.branch); + return file.path.startsWith(normalizePath(folder)); } \ No newline at end of file From ab1aa55af22abfe2d73c54e4099deab71e912c38 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 19:16:19 +0100 Subject: [PATCH 11/14] remove redundant ternary --- src/utils/parse_frontmatter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/parse_frontmatter.ts b/src/utils/parse_frontmatter.ts index e6de55e6..8b086c63 100644 --- a/src/utils/parse_frontmatter.ts +++ b/src/utils/parse_frontmatter.ts @@ -144,7 +144,7 @@ export function getRepoFrontmatter( branch: github.branch, repo: github.repo, owner: github.user, - autoclean: settings.github.dryRun.enable ? false : settings.upload.autoclean.enable, + autoclean: !settings.github.dryRun.enable && settings.upload.autoclean.enable, workflowName: github.workflow.name, commitMsg: github.workflow.commitMessage, automaticallyMergePR: github.automaticallyMergePR, From e7af4478a0801b651a8b48c34036640d5dda3c72 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 19:22:07 +0100 Subject: [PATCH 12/14] use spread operator for cloning the object --- src/utils/parse_frontmatter.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils/parse_frontmatter.ts b/src/utils/parse_frontmatter.ts index 8b086c63..116c096f 100644 --- a/src/utils/parse_frontmatter.ts +++ b/src/utils/parse_frontmatter.ts @@ -224,7 +224,7 @@ function parseMultipleRepo( ) { for (const repo of frontmatter.multipleRepo) { if (typeof repo === "object") { - const repository: RepoFrontmatter = JSON.parse(JSON.stringify(repoFrontmatter)); + const repository: RepoFrontmatter = structuredClone(repoFrontmatter); if (repo.branch !== undefined) { repository.branch = repo.branch; } @@ -241,7 +241,7 @@ function parseMultipleRepo( } else { //is string const repoString = repo.split("/"); - const repository: RepoFrontmatter = JSON.parse(JSON.stringify(repoFrontmatter)); + const repository: RepoFrontmatter = structuredClone(repoFrontmatter); multipleRepo.push( repositoryStringSlice(repoString, repository) ); @@ -318,8 +318,8 @@ function multipleShortKeyRepo(frontmatter: FrontMatterCache, allRepo: Repository */ function repositoryStringSlice(repo: string, repoFrontmatter: RepoFrontmatter): RepoFrontmatter { - const newRepo: RepoFrontmatter = JSON.parse(JSON.stringify(repoFrontmatter)); - if (repo.length >= 4) { + const newRepo: RepoFrontmatter = structuredClone(repoFrontmatter); + if (repo.length === 4) { newRepo.branch = repo[2]; newRepo.repo = repo[1]; newRepo.owner = repo[0]; From f4704ec68f594773394999d67814f037c3d01b81 Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 19:31:13 +0100 Subject: [PATCH 13/14] translate dryRun setting --- src/i18n/locales/en.json | 10 ++++++++++ src/i18n/locales/fr.json | 10 ++++++++++ src/settings.ts | 8 ++++---- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json index becadf52..9290f65d 100644 --- a/src/i18n/locales/en.json +++ b/src/i18n/locales/en.json @@ -294,6 +294,16 @@ "desc": "If you use a different branch than \"main\"", "title": "Main branch" }, + "dryRun": { + "enable": { + "desc": "Disable GitHub push and all other action and only perform a dry-run to see what would be pushed or deleted in the repository.", + "title": "Test mode" + }, + "folder": { + "desc": "Use {{owner}}, {{repo}} and {{branch}} to dynamically name the folder.", + "title": "Folder where the repository will be simulated" + } + }, "ghToken": { "button": { "configDir": ": The configuration folder of Obsidian", diff --git a/src/i18n/locales/fr.json b/src/i18n/locales/fr.json index 9035dcd1..a06932d4 100644 --- a/src/i18n/locales/fr.json +++ b/src/i18n/locales/fr.json @@ -293,6 +293,16 @@ "desc": "Dans le cas où vous souhaitez utiliser une branche différente de \"main\".", "title": "Branche principale" }, + "dryRun": { + "enable": { + "desc": "Désactiver le push GitHub et toutes les autres actions et effectuer seulement une simulation pour voir ce qui serait transféré ou supprimé dans le dépôt.", + "title": "Mode de test" + }, + "folder": { + "desc": "Use {{owner}}, {{repo}} and {{branch}} to dynamically name the folder.", + "title": "Dossier où le dépôt sera simulé" + } + }, "ghToken": { "button": { "configDir": " : Le dossier de configuration d'Obsidian", diff --git a/src/settings.ts b/src/settings.ts index 2aa1620b..f6a8cf4b 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -295,8 +295,8 @@ export class GithubPublisherSettingsTab extends PluginSettingTab { }) ); new Setting(this.settingsPage) - .setName("Dry run") - .setDesc("Disable GitHub push and all other action and only perform a dry-run to see what would be pushed") + .setName(i18next.t("settings.github.dryRun.enable.title")) + .setDesc(i18next.t("settings.github.dryRun.enable.desc")) .addToggle((toggle) => toggle .setValue(githubSettings.dryRun.enable) @@ -308,8 +308,8 @@ export class GithubPublisherSettingsTab extends PluginSettingTab { ); if (githubSettings.dryRun.enable) { new Setting(this.settingsPage) - .setName("Folder where file will be copied") - .setDesc("Use {{owner}}, {{repo}} and {{branch}} to dynamically create the folder name.") + .setName(i18next.t("settings.github.dryRun.folder.title")) + .setDesc(i18next.t("settings.github.dryRun.folder.desc")) .addText((text) => text .setPlaceholder("github-publisher") From 23b6142bc602bdb1b1a9e6714f6582680cd52aaf Mon Sep 17 00:00:00 2001 From: Mara Date: Sun, 21 Jan 2024 19:33:51 +0100 Subject: [PATCH 14/14] nested statement is redundant and can be removed --- src/GitHub/upload.ts | 67 ++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/GitHub/upload.ts b/src/GitHub/upload.ts index 467a65e3..21d764e7 100644 --- a/src/GitHub/upload.ts +++ b/src/GitHub/upload.ts @@ -332,7 +332,7 @@ export default class Publisher { const embeddedUploaded = embeded.uploaded; embeddedUploaded.push(uploaded); - if ((autoclean && repo.autoclean) || repo.dryRun.autoclean) { + if (autoclean || repo.dryRun.autoclean) { deleted = await deleteFromGithub( true, this.branchName, @@ -643,47 +643,48 @@ export default class Publisher { continue; } if (!this.settings.github.dryRun.enable) { - try { - if (forcePushAttachment(file, this.settings)) { - newLinkedFiles.push(file); - continue; - } - //first search if the file exists - const response = await this.octokit.request( - "GET /repos/{owner}/{repo}/contents/{path}", + newLinkedFiles.push(file); + continue; + } + try { + if (forcePushAttachment(file, this.settings)) { + newLinkedFiles.push(file); + continue; + } + //first search if the file exists + const response = await this.octokit.request( + "GET /repos/{owner}/{repo}/contents/{path}", + { + owner: repoFrontmatter.repo.owner, + repo: repoFrontmatter.repo.repo, + path: imagePath, + ref: this.branchName, + }); + if (response.status === 200) { + const reply = await this.octokit.request( + "GET /repos/{owner}/{repo}/commits", { owner: repoFrontmatter.repo.owner, repo: repoFrontmatter.repo.repo, path: imagePath, - ref: this.branchName, + sha: this.branchName, }); - if (response.status === 200) { - const reply = await this.octokit.request( - "GET /repos/{owner}/{repo}/commits", - { - owner: repoFrontmatter.repo.owner, - repo: repoFrontmatter.repo.repo, - path: imagePath, - sha: this.branchName, - }); - if (reply.status === 200) { - const data = reply.data; - const lastEditedInRepo = data[0]?.commit?.committer?.date; - const lastEditedDate = lastEditedInRepo ? new Date(lastEditedInRepo) : undefined; - const lastEditedAttachment = new Date(file.stat.mtime); - //if the file in the vault is newer than the file in the repo, push it - if (lastEditedDate && lastEditedAttachment > lastEditedDate || !lastEditedDate) { - newLinkedFiles.push(file); - } else logs({ settings: this.settings }, i18next.t("error.alreadyExists", { file: file.name })); - } + if (reply.status === 200) { + const data = reply.data; + const lastEditedInRepo = data[0]?.commit?.committer?.date; + const lastEditedDate = lastEditedInRepo ? new Date(lastEditedInRepo) : undefined; + const lastEditedAttachment = new Date(file.stat.mtime); + //if the file in the vault is newer than the file in the repo, push it + if (lastEditedDate && lastEditedAttachment > lastEditedDate || !lastEditedDate) { + newLinkedFiles.push(file); + } else logs({ settings: this.settings }, i18next.t("error.alreadyExists", { file: file.name })); } - } catch (e) { - newLinkedFiles.push(file); } + } catch (e) { + newLinkedFiles.push(file); } - } else { - newLinkedFiles.push(file); } + } return newLinkedFiles; }