better gitignore
CI / check (push) Has been cancelled

This commit is contained in:
2026-06-16 10:44:40 +02:00
parent d5dbf7187d
commit 7c69853e85
13 changed files with 171 additions and 86 deletions
+7 -4
View File
@@ -49,19 +49,22 @@ const THEME_TEMPLATE = `/* Helder theme — custom CSS applied OVER the built-in
/** Recently-opened files, newest first. Local machine state — git-ignored. */
const RECENT_FILE = 'recent.json'
const MAX_RECENT = 100
const GITIGNORE_BODY = `# Helder local, machine-specific state (do not commit)\n${RECENT_FILE}\n`
// The whole .helder folder is local, machine-specific state — ignore all of it.
const GITIGNORE_BODY = `# Helder — local, machine-specific state (do not commit).\n*\n`
let current: HelderConfig = DEFAULTS
let themeCss = ''
/** Create `.helder/.gitignore` (ignoring recent.json) only when it's missing. */
/** Ensure `.helder/.gitignore` ignores the entire folder; (re)write it when the
* file is missing or out of date (e.g. upgrading from the old recent-only one). */
async function ensureGitignore(dir: string): Promise<void> {
const path = join(dir, '.gitignore')
try {
await readFile(path, 'utf8')
if ((await readFile(path, 'utf8')) === GITIGNORE_BODY) return
} catch {
await writeFile(path, GITIGNORE_BODY)
/* missing — fall through to write */
}
await writeFile(path, GITIGNORE_BODY)
}
export async function getRecent(root: string): Promise<string[]> {
+8 -1
View File
@@ -1,4 +1,4 @@
import { readdir, readFile, stat, writeFile } from 'node:fs/promises'
import { readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
import { join, relative, sep } from 'node:path'
import { listFiles } from './search-service'
@@ -120,6 +120,13 @@ export async function writeProjectFile(root: string, rel: string, content: strin
await writeFile(join(root, rel), content, 'utf8')
}
/** Delete a project file or folder (relative path). Stays inside the project root. */
export async function deleteProjectFile(root: string, rel: string): Promise<void> {
const target = join(root, rel)
if (relative(root, target).startsWith('..')) return // guard against escaping the root
await rm(target, { recursive: true, force: true })
}
/**
* In-memory content index of all (small, text) files — powers content viewing.
* Primary: read the rg file list; fallback: walk. Capped for large repos.
+3 -1
View File
@@ -2,7 +2,7 @@ import { join, sep } from 'node:path'
import { app, dialog, shell, BrowserWindow, ipcMain, Menu } from 'electron'
import { watch, type FSWatcher } from 'chokidar'
import { addRecentProject, getName, getRecentProjects, getRoot, openDialog, setRoot } from './project'
import { readAll, readProjectFile, readTree, writeProjectFile } from './fs-service'
import { deleteProjectFile, readAll, readProjectFile, readTree, writeProjectFile } from './fs-service'
import { commit, discard, load, stage, unstage } from './git-service'
import { createPty, killAllPtys, killPty, ptyAvailable, resizePty, writePty } from './pty-service'
import { getConfig, getRecent, getThemeCss, resolveConfig, setRecent } from './config'
@@ -104,6 +104,8 @@ function registerIpc(): void {
ipcMain.handle('fs:files', () => { const r = getRoot(); return r ? readAll(r) : {} })
ipcMain.handle('fs:read', (_e, rel: string) => { const r = getRoot(); return r ? readProjectFile(r, rel) : '' })
ipcMain.handle('fs:write', (_e, rel: string, content: string) => { const r = getRoot(); if (r) return writeProjectFile(r, rel, content) })
ipcMain.handle('fs:delete', (_e, rel: string) => { const r = getRoot(); if (r) return deleteProjectFile(r, rel) })
ipcMain.handle('shell:reveal', (_e, rel: string) => { const r = getRoot(); if (r) shell.showItemInFolder(join(r, rel)) })
ipcMain.handle('git:load', () => { const r = getRoot(); return r ? load(r) : null })
ipcMain.handle('git:stage', (_e, paths: string[]) => { const r = getRoot(); if (r) return stage(r, paths) })