From c36735dbdef0190d25e89fd8bf75152b276fb08f Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 20 Feb 2026 04:01:39 +0000 Subject: [PATCH] fix: ensure torch init adds .gitignore with node_modules Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- src/ops.mjs | 24 ++++++++++++++ test/ops-gitignore.test.mjs | 65 +++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 test/ops-gitignore.test.mjs diff --git a/src/ops.mjs b/src/ops.mjs index 68a7f49..9af381b 100644 --- a/src/ops.mjs +++ b/src/ops.mjs @@ -304,6 +304,29 @@ function configureTorch(cwd, paths, installDir, namespace, relays, hashtag) { console.log(`Saved configuration to ${path.relative(cwd, configPath)}`); } +function ensureGitIgnore(targetDir) { + const gitIgnorePath = path.join(targetDir, '.gitignore'); + let content = ''; + const exists = fs.existsSync(gitIgnorePath); + + if (exists) { + content = fs.readFileSync(gitIgnorePath, 'utf8'); + } + + const lines = content.split('\n').map((l) => l.trim()); + const hasNodeModules = lines.some((l) => l === 'node_modules' || l === '/node_modules' || l === 'node_modules/'); + + if (!hasNodeModules) { + const prefix = exists && content.length > 0 && !content.endsWith('\n') ? '\n' : ''; + fs.appendFileSync(gitIgnorePath, `${prefix}node_modules\n`, 'utf8'); + if (exists) { + console.log(`Updated ${path.relative(process.cwd(), gitIgnorePath)}: added node_modules`); + } else { + console.log(`Created ${path.relative(process.cwd(), gitIgnorePath)} with node_modules`); + } + } +} + function injectHostScriptsIfNeeded(paths, installDir) { // 7. Inject Scripts into Host Package.json // If we are NOT installing to '.', the host package.json is in paths.root @@ -327,6 +350,7 @@ export async function cmdInit(force = false, cwd = process.cwd(), mockAnswers = installAppAssets(paths.torchDir, installDir); installTorchAssets(paths, installDir); + ensureGitIgnore(paths.torchDir); configureTorch(cwd, paths, installDir, namespace, relays, hashtag); createDashboardLinkFile(paths, namespace, relays, hashtag); injectHostScriptsIfNeeded(paths, installDir); diff --git a/test/ops-gitignore.test.mjs b/test/ops-gitignore.test.mjs new file mode 100644 index 0000000..1743783 --- /dev/null +++ b/test/ops-gitignore.test.mjs @@ -0,0 +1,65 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { test } from 'node:test'; +import assert from 'node:assert'; +import { cmdInit } from '../src/ops.mjs'; + +test('ops.mjs: cmdInit creates .gitignore with node_modules', async (t) => { + const tmpDir = fs.mkdtempSync(path.join(process.cwd(), 'test-gitignore-')); + + // Clean up afterwards + t.after(() => { + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + const mockAnswers = { + installDir: 'torch', + namespace: 'test-ns', + hashtag: 'test-hash', + relays: ['wss://relay.damus.io'], + }; + + // Run init + // We silence console logs to keep test output clean, if possible, but it's fine. + await cmdInit(false, tmpDir, mockAnswers); + + const gitIgnorePath = path.join(tmpDir, 'torch', '.gitignore'); + + if (fs.existsSync(gitIgnorePath)) { + const content = fs.readFileSync(gitIgnorePath, 'utf8'); + assert.match(content, /node_modules/, '.gitignore should contain node_modules'); + } else { + assert.fail('.gitignore was not created'); + } +}); + +test('ops.mjs: cmdInit appends to existing .gitignore', async (t) => { + const tmpDir = fs.mkdtempSync(path.join(process.cwd(), 'test-gitignore-existing-')); + + // Clean up afterwards + t.after(() => { + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + const torchDir = path.join(tmpDir, 'torch'); + fs.mkdirSync(torchDir, { recursive: true }); + + // Create existing .gitignore without node_modules + fs.writeFileSync(path.join(torchDir, '.gitignore'), 'existing-pattern\n', 'utf8'); + + const mockAnswers = { + installDir: 'torch', + namespace: 'test-ns', + hashtag: 'test-hash', + relays: ['wss://relay.damus.io'], + }; + + // Run init (force=true because directory exists) + await cmdInit(true, tmpDir, mockAnswers); + + const gitIgnorePath = path.join(torchDir, '.gitignore'); + const content = fs.readFileSync(gitIgnorePath, 'utf8'); + + assert.match(content, /existing-pattern/, 'Should preserve existing content'); + assert.match(content, /node_modules/, 'Should append node_modules'); +});