All checks were successful
CI / test (push) Successful in 17s
The askpass bridge bound a Unix-domain socket to a vault filesystem path (net.createServer().listen(...sock)). That is invalid on Windows, where Node's listen() expects a named pipe, so publish aborted with 'listen EACCES: permission denied ...askpass.sock' before git ever ran — even when the user's git could authenticate. The bridge was non-portable in general (Windows named pipes; the helper script needs a node binary on PATH). Remove the bridge and let the user's system git handle credentials via its native helpers (Git Credential Manager / osxkeychain / libsecret) for https and ssh-agent for ssh — the 'store nothing' model we already chose. GIT_TERMINAL_PROMPT=0 stays so git fails fast instead of hanging, and publish errors now include a credential/identity hint. Deletes askpass.ts and its test (3 tests); suite 32/32, tsc clean, build OK. Co-Authored-By: Claude
95 lines
3.5 KiB
TypeScript
95 lines
3.5 KiB
TypeScript
import { Notice, Plugin, TFile } from "obsidian";
|
|
import { DEFAULT_SETTINGS, JekyllPublishSettings } from "./settings";
|
|
import { JekyllPublishSettingTab } from "./SettingsTab";
|
|
import { ModalResult, PublishModal } from "./PublishModal";
|
|
import { ChildProcessGitClient } from "./git";
|
|
import { publish } from "./publish";
|
|
|
|
export default class JekyllPublishPlugin extends Plugin {
|
|
settings!: JekyllPublishSettings;
|
|
|
|
async onload() {
|
|
await this.loadSettings();
|
|
this.addSettingTab(new JekyllPublishSettingTab(this.app, this));
|
|
this.addCommand({
|
|
id: "publish-current-note",
|
|
name: "Publish current note to Jekyll",
|
|
checkCallback: (checking) => {
|
|
const file = this.app.workspace.getActiveFile();
|
|
if (!file) return false;
|
|
if (!checking) void this.openPublishModal(file);
|
|
return true;
|
|
},
|
|
});
|
|
}
|
|
|
|
async loadSettings() {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
|
}
|
|
async saveSettings() {
|
|
await this.saveData(this.settings);
|
|
}
|
|
|
|
private async openPublishModal(file: TFile) {
|
|
const noteText = await this.app.vault.read(file);
|
|
new PublishModal(this.app, this.settings, noteText, file.basename, (r) =>
|
|
void this.runPublish(noteText, r)
|
|
).open();
|
|
}
|
|
|
|
private async runPublish(noteText: string, r: ModalResult) {
|
|
if (!this.settings.remoteUrl.trim()) {
|
|
new Notice("Jekyll Publish: set a remote URL in settings first.");
|
|
return;
|
|
}
|
|
try {
|
|
// Credentials are handled entirely by the user's system git: its
|
|
// configured credential helper (Git Credential Manager on Windows,
|
|
// osxkeychain on macOS, libsecret on Linux) for https:// URLs, or the
|
|
// ssh-agent / key for ssh:// URLs. The plugin stores nothing and sets
|
|
// GIT_TERMINAL_PROMPT=0 (in ChildProcessGitClient) so git fails fast
|
|
// with a clear message instead of hanging when no helper is available.
|
|
const git = new ChildProcessGitClient();
|
|
const result = await publish(
|
|
{ noteText, ...r },
|
|
this.settings,
|
|
git,
|
|
(linktext) => this.resolveImage(linktext)
|
|
);
|
|
const warn = result.unresolved.length
|
|
? ` (${result.unresolved.length} image(s) unresolved)`
|
|
: "";
|
|
new Notice(`Published ${result.postPath} with ${result.imageCount} image(s)${warn}`);
|
|
} catch (e) {
|
|
new Notice(`Publish failed: ${withCredentialHint((e as Error).message)}`, 12000);
|
|
}
|
|
}
|
|
|
|
private async resolveImage(linktext: string): Promise<Buffer | null> {
|
|
const dest = this.app.metadataCache.getFirstLinkpathDest(linktext, "");
|
|
if (!dest) return null;
|
|
const ab = await this.app.vault.readBinary(dest);
|
|
return Buffer.from(ab);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* When git fails for an authentication reason, append guidance pointing the
|
|
* user at their system credential helper / ssh setup, since the plugin
|
|
* deliberately does not store or prompt for credentials itself.
|
|
*/
|
|
function withCredentialHint(message: string): string {
|
|
const authPattern =
|
|
/could not read (Username|Password)|terminal prompts disabled|Authentication failed|Permission denied|access denied|fatal: Authentication|no email was given|Author identity unknown/i;
|
|
if (authPattern.test(message)) {
|
|
return (
|
|
`${message}\n\n` +
|
|
"Git could not authenticate or identify you. For an https:// URL, set up a " +
|
|
"git credential helper (e.g. Git Credential Manager). For an ssh:// URL, make " +
|
|
"sure your SSH key/agent is configured. You can also set an author name/email " +
|
|
"in the plugin settings."
|
|
);
|
|
}
|
|
return message;
|
|
}
|