diff --git a/package-lock.json b/package-lock.json index ea02ec2..b868de3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "settings-repository", - "version": "2.0.1", + "version": "2.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "settings-repository", - "version": "2.0.1", + "version": "2.0.2", "license": "GPL-2.0-only", "devDependencies": { "@types/adm-zip": "0.5.8", diff --git a/package.json b/package.json index cdc7cdc..5b8dfe1 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "theme": "dark" }, "publisher": "Katsute", - "version": "2.0.1", + "version": "2.0.2", "private": true, "engines": { "vscode": "^1.110.0" diff --git a/src/command/auth.ts b/src/command/auth.ts index 6c176de..687a935 100644 --- a/src/command/auth.ts +++ b/src/command/auth.ts @@ -22,12 +22,14 @@ import * as fs from "fs"; import * as os from "os"; import { isNull, isValidJson } from "../lib/is"; +import * as config from "../config"; import * as logger from "../logger"; import * as files from "../lib/files"; import { Crypt } from "../lib/encrypt"; import * as extension from "../extension"; import { Distribution } from "../distribution"; import { CommandQuickPickItem } from "../lib/quickpick"; +import simpleGit from "simple-git"; // @@ -52,6 +54,11 @@ const crypt: Crypt = new Crypt(os.hostname()); // +const parseRepo: (repo: string, cred: credentials) => string = (repo: string, cred: credentials) => { + const part: string[] = repo.split("://"); + return `${part[0]}://${cred.login}:${cred.auth}@${part.slice(1).join("://")}`; +} + export const mask: (s: string, c: credentials) => string = (s: string, c: credentials) => { return s.replace(new RegExp(c.auth, "gm"), "***"); } @@ -78,9 +85,27 @@ export const authenticate: () => void = () => { if(value.trim().length === 0) return "Token can not be blank"; } - }).then((password?: string) => { + }).then(async (password?: string) => { if(!password) return; + const repo: string = config.get("repository"); + + if(repo){ + const cred: credentials = { login: username, auth: password }; + const remote: string = parseRepo(repo, cred); + + const err = await simpleGit().listRemote([remote]) + .then(() => { + logger.info(`Credentials are valid for ${repo}`); + }) + .catch(e => { + logger.error(`Failed to verify credentials for ${repo}:\n ${mask(String(e?.message ?? e), cred)}`, true); + return e; + }); + + if(err) return; + } + const dist: Distribution = extension.distribution(); logger.info(`Updated authentication: ${username}`); @@ -91,7 +116,8 @@ export const authenticate: () => void = () => { "login": "${username}", "auth": "${crypt.encrypt(password)}" }`, - "utf-8"); + "utf-8" + ); }); }); } diff --git a/src/command/local.ts b/src/command/local.ts index 57f5cdf..2cc3a38 100644 --- a/src/command/local.ts +++ b/src/command/local.ts @@ -31,5 +31,5 @@ export const item: CommandQuickPickItem = { } export const command: vscode.Disposable = vscode.commands.registerCommand("settings-repository.overwriteLocal", () => { - config.get("repository") && pull(config.get("repository")); + config.get("repository") && pull(config.get("repository"), config.get("branch")); }); \ No newline at end of file diff --git a/src/command/remote.ts b/src/command/remote.ts index be81f2b..c300ce0 100644 --- a/src/command/remote.ts +++ b/src/command/remote.ts @@ -31,5 +31,5 @@ export const item: CommandQuickPickItem = { } export const command: vscode.Disposable = vscode.commands.registerCommand("settings-repository.overwriteRemote", () => { - config.get("repository") && push(config.get("repository")); + config.get("repository") && push(config.get("repository"), config.get("branch")); }); \ No newline at end of file diff --git a/src/extension.ts b/src/extension.ts index 3cc3266..ecd6423 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -68,16 +68,16 @@ export const activate: (context: vscode.ExtensionContext) => void = (context: vs logger.debug(`branch: ${config.get("branch")}`); logger.debug(`autoSync: ${config.get("autoSync")}`); logger.debug(`includeHostnameInCommitMessage: ${config.get("includeHostnameInCommitMessage")}`); - logger.debug(`authenticated: ${!!auth.authorization()}`); + logger.debug(`has credentials: ${!!auth.authorization()}`); if(config.get("autoSync") === true && config.get("autoSyncMode") !== "Export Only") - config.get("repository") && pull(config.get("repository"), true); + config.get("repository") && pull(config.get("repository"), config.get("branch"), true); } // must be async, otherwise vscode closes without waiting export const deactivate: () => Promise = async () => { if(config.get("autoSync") === true && config.get("autoSyncMode") !== "Import Only") - config.get("repository") && await push(config.get("repository"), true); + config.get("repository") && await push(config.get("repository"), config.get("branch"), true); } export const notify: () => void = () => { diff --git a/src/sync/git.ts b/src/sync/git.ts index 09dd2ca..aebd4e6 100644 --- a/src/sync/git.ts +++ b/src/sync/git.ts @@ -47,13 +47,16 @@ const parseRepo: (repo: string, cred: auth.credentials) => string = (repo: strin return `${part[0]}://${cred.login}:${cred.auth}@${part.slice(1).join("://")}`; } -export const pull: (repo: string, skipNotify?: boolean) => void = async (repo: string, skipNotify: boolean = false) => { +export const pull: (repo: string, branch?: string, skipNotify?: boolean) => Promise = async (repo: string, branch: string = "main", skipNotify: boolean = false) => { if(isNull(repo)) return; const dist: Distribution = extension.distribution(); const cred: auth.credentials | undefined = auth.authorization(); - if(!cred) return skipNotify || auth.authenticate(); + if(!cred) { + skipNotify || auth.authenticate(); + return; + } // init directory @@ -65,13 +68,11 @@ export const pull: (repo: string, skipNotify?: boolean) => void = async (repo: s const remote: string = parseRepo(repo, cred); - const branch: string = config.get("branch") ?? "main"; - // callback const gitback: (err: GitError | null) => void = (err: GitError | null) => { if(err){ - logger.error(`Failed to pull from ${config.get("repository")}:\n ${auth.mask(err.message, cred)}`, true); + logger.error(`Failed to pull from ${repo}@${branch}:\n ${auth.mask(err.message, cred)}`, true); cleanup(temp); } }; @@ -80,7 +81,7 @@ export const pull: (repo: string, skipNotify?: boolean) => void = async (repo: s statusbar.setActive(true); - logger.info(`Preparing to import settings from ${config.get("repository")}@${branch}`); + logger.info(`Preparing to import settings from ${repo}@${branch}`); logger.debug(`Git clone ${auth.mask(remote, cred)}`); // forced delay so git repo can get up-to-date after a fast reload/restart @@ -148,7 +149,7 @@ export const pull: (repo: string, skipNotify?: boolean) => void = async (repo: s logger.warn("Snippets not found"); } - logger.info(`Imported settings from ${config.get("repository")}@${branch}`, true); + logger.info(`Imported settings from ${repo}@${branch}`, true); cleanup(temp); @@ -156,13 +157,13 @@ export const pull: (repo: string, skipNotify?: boolean) => void = async (repo: s } }); }catch(error: any){ - logger.error(`Push failed: ${auth.mask(error, cred)}`, true); + logger.error(`Pull failed: ${auth.mask(String(error?.message ?? error), cred)}`, true); }finally{ cleanup(temp); } } -export const push: (repo: string, ignoreBadAuth?: boolean) => Promise = async (repo: string, ignoreBadAuth: boolean = false) => { +export const push: (repo: string, branch?: string, ignoreBadAuth?: boolean) => Promise = async (repo: string, branch: string = "main", ignoreBadAuth: boolean = false) => { if(isNull(repo)) return; const dist: Distribution = extension.distribution(); @@ -180,13 +181,11 @@ export const push: (repo: string, ignoreBadAuth?: boolean) => Promise = as const remote: string = parseRepo(repo, cred); - const branch: string = config.get("branch") ?? "main"; - // callback const gitback: (err: GitError | null) => void = (err: GitError | null) => { if(err){ - logger.error(`Failed to push to ${config.get("repository")}:\n ${auth.mask(err.message, cred)}`, true); + logger.error(`Failed to push to ${repo}@${branch}:\n ${auth.mask(err.message, cred)}`, true); cleanup(temp); } }; @@ -195,7 +194,7 @@ export const push: (repo: string, ignoreBadAuth?: boolean) => Promise = as statusbar.setActive(true); - logger.info(`Preparing to export settings to ${config.get("repository")}@${branch}`); + logger.info(`Preparing to export settings to ${repo}@${branch}`); logger.debug(`Git clone ${auth.mask(remote, cred)}`); logger.debug(`includeHostnameInCommit: ${config.get("includeHostnameInCommitMessage")}`); @@ -257,7 +256,7 @@ export const push: (repo: string, ignoreBadAuth?: boolean) => Promise = as } }catch(error: any){ if(error){ - logger.error(`Push failed: ${auth.mask(error, cred)}`, true); + logger.error(`Push failed: ${auth.mask(String(error), cred)}`, true); cleanup(temp); } } @@ -271,12 +270,12 @@ export const push: (repo: string, ignoreBadAuth?: boolean) => Promise = as .push(["-u", "origin", "HEAD"], (err: GitError | null) => { gitback(err); if(!err){ - logger.info(`Pushed settings to ${config.get("repository")}@${branch}`, true); + logger.info(`Pushed settings to ${repo}@${branch}`, true); cleanup(temp); } }); }catch(error: any){ - logger.error(`Push failed: ${auth.mask(error, cred)}`, true); + logger.error(`Push failed: ${auth.mask(String(error?.message ?? error), cred)}`, true); }finally{ cleanup(temp); }