git-smart-flow 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -0
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/bin/git-smart-flow.js +2 -0
- package/bin/gsf.js +2 -0
- package/bin/gsfc.js +3 -0
- package/bin/gsfm.js +3 -0
- package/bin/gsfp.js +3 -0
- package/bin/gsfpr.js +3 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +214 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/aliases.d.ts +2 -0
- package/dist/commands/aliases.js +37 -0
- package/dist/commands/aliases.js.map +1 -0
- package/dist/commands/branch.d.ts +2 -0
- package/dist/commands/branch.js +414 -0
- package/dist/commands/branch.js.map +1 -0
- package/dist/commands/commit-message.d.ts +7 -0
- package/dist/commands/commit-message.js +95 -0
- package/dist/commands/commit-message.js.map +1 -0
- package/dist/commands/commit.d.ts +3 -0
- package/dist/commands/commit.js +597 -0
- package/dist/commands/commit.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +88 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +246 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/info.d.ts +2 -0
- package/dist/commands/info.js +155 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/install-hooks.d.ts +2 -0
- package/dist/commands/install-hooks.js +66 -0
- package/dist/commands/install-hooks.js.map +1 -0
- package/dist/commands/log.d.ts +2 -0
- package/dist/commands/log.js +101 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/menu.d.ts +2 -0
- package/dist/commands/menu.js +297 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/commands/merge.d.ts +6 -0
- package/dist/commands/merge.js +128 -0
- package/dist/commands/merge.js.map +1 -0
- package/dist/commands/pr.d.ts +2 -0
- package/dist/commands/pr.js +731 -0
- package/dist/commands/pr.js.map +1 -0
- package/dist/commands/push.d.ts +7 -0
- package/dist/commands/push.js +225 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/reflog.d.ts +2 -0
- package/dist/commands/reflog.js +162 -0
- package/dist/commands/reflog.js.map +1 -0
- package/dist/commands/repo-init.d.ts +2 -0
- package/dist/commands/repo-init.js +466 -0
- package/dist/commands/repo-init.js.map +1 -0
- package/dist/commands/revert.d.ts +7 -0
- package/dist/commands/revert.js +694 -0
- package/dist/commands/revert.js.map +1 -0
- package/dist/commands/setup.d.ts +2 -0
- package/dist/commands/setup.js +86 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/stash.d.ts +2 -0
- package/dist/commands/stash.js +130 -0
- package/dist/commands/stash.js.map +1 -0
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.js +335 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/tag.d.ts +2 -0
- package/dist/commands/tag.js +163 -0
- package/dist/commands/tag.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.js +203 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/config/config.d.ts +10 -0
- package/dist/config/config.js +126 -0
- package/dist/config/config.js.map +1 -0
- package/dist/git/ai-context-builder.d.ts +11 -0
- package/dist/git/ai-context-builder.js +112 -0
- package/dist/git/ai-context-builder.js.map +1 -0
- package/dist/git/convention-detector.d.ts +3 -0
- package/dist/git/convention-detector.js +211 -0
- package/dist/git/convention-detector.js.map +1 -0
- package/dist/git/ensure-repo.d.ts +7 -0
- package/dist/git/ensure-repo.js +141 -0
- package/dist/git/ensure-repo.js.map +1 -0
- package/dist/git/gitignore.d.ts +8 -0
- package/dist/git/gitignore.js +261 -0
- package/dist/git/gitignore.js.map +1 -0
- package/dist/git/remote-setup.d.ts +2 -0
- package/dist/git/remote-setup.js +129 -0
- package/dist/git/remote-setup.js.map +1 -0
- package/dist/git/repo.d.ts +73 -0
- package/dist/git/repo.js +308 -0
- package/dist/git/repo.js.map +1 -0
- package/dist/git/validate.d.ts +36 -0
- package/dist/git/validate.js +113 -0
- package/dist/git/validate.js.map +1 -0
- package/dist/providers/base.provider.d.ts +10 -0
- package/dist/providers/base.provider.js +40 -0
- package/dist/providers/base.provider.js.map +1 -0
- package/dist/providers/claude.provider.d.ts +14 -0
- package/dist/providers/claude.provider.js +85 -0
- package/dist/providers/claude.provider.js.map +1 -0
- package/dist/providers/copilot.provider.d.ts +12 -0
- package/dist/providers/copilot.provider.js +88 -0
- package/dist/providers/copilot.provider.js.map +1 -0
- package/dist/providers/heuristic.provider.d.ts +9 -0
- package/dist/providers/heuristic.provider.js +163 -0
- package/dist/providers/heuristic.provider.js.map +1 -0
- package/dist/providers/ollama.provider.d.ts +14 -0
- package/dist/providers/ollama.provider.js +83 -0
- package/dist/providers/ollama.provider.js.map +1 -0
- package/dist/providers/openai.provider.d.ts +14 -0
- package/dist/providers/openai.provider.js +84 -0
- package/dist/providers/openai.provider.js.map +1 -0
- package/dist/providers/provider.factory.d.ts +5 -0
- package/dist/providers/provider.factory.js +51 -0
- package/dist/providers/provider.factory.js.map +1 -0
- package/dist/security/scanner.d.ts +13 -0
- package/dist/security/scanner.js +138 -0
- package/dist/security/scanner.js.map +1 -0
- package/dist/types/index.d.ts +146 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ux/components/BranchTree.d.ts +8 -0
- package/dist/ux/components/BranchTree.js +57 -0
- package/dist/ux/components/BranchTree.js.map +1 -0
- package/dist/ux/components/CommitProposal.d.ts +13 -0
- package/dist/ux/components/CommitProposal.js +127 -0
- package/dist/ux/components/CommitProposal.js.map +1 -0
- package/dist/ux/components/DiagnosticReport.d.ts +18 -0
- package/dist/ux/components/DiagnosticReport.js +19 -0
- package/dist/ux/components/DiagnosticReport.js.map +1 -0
- package/dist/ux/components/ErrorBox.d.ts +7 -0
- package/dist/ux/components/ErrorBox.js +9 -0
- package/dist/ux/components/ErrorBox.js.map +1 -0
- package/dist/ux/components/FileSelector.d.ts +14 -0
- package/dist/ux/components/FileSelector.js +87 -0
- package/dist/ux/components/FileSelector.js.map +1 -0
- package/dist/ux/components/Logo.d.ts +6 -0
- package/dist/ux/components/Logo.js +21 -0
- package/dist/ux/components/Logo.js.map +1 -0
- package/dist/ux/components/RepoContext.d.ts +8 -0
- package/dist/ux/components/RepoContext.js +17 -0
- package/dist/ux/components/RepoContext.js.map +1 -0
- package/dist/ux/components/SecurityAlert.d.ts +9 -0
- package/dist/ux/components/SecurityAlert.js +16 -0
- package/dist/ux/components/SecurityAlert.js.map +1 -0
- package/dist/ux/components/StatusDashboard.d.ts +14 -0
- package/dist/ux/components/StatusDashboard.js +36 -0
- package/dist/ux/components/StatusDashboard.js.map +1 -0
- package/dist/ux/components/SuccessBox.d.ts +7 -0
- package/dist/ux/components/SuccessBox.js +9 -0
- package/dist/ux/components/SuccessBox.js.map +1 -0
- package/dist/ux/components/ValidationReport.d.ts +16 -0
- package/dist/ux/components/ValidationReport.js +19 -0
- package/dist/ux/components/ValidationReport.js.map +1 -0
- package/dist/ux/components/WarningBox.d.ts +7 -0
- package/dist/ux/components/WarningBox.js +9 -0
- package/dist/ux/components/WarningBox.js.map +1 -0
- package/dist/ux/display.d.ts +21 -0
- package/dist/ux/display.js +96 -0
- package/dist/ux/display.js.map +1 -0
- package/dist/ux/hooks/useActivation.d.ts +8 -0
- package/dist/ux/hooks/useActivation.js +16 -0
- package/dist/ux/hooks/useActivation.js.map +1 -0
- package/dist/ux/hooks/useSpinner.d.ts +2 -0
- package/dist/ux/hooks/useSpinner.js +13 -0
- package/dist/ux/hooks/useSpinner.js.map +1 -0
- package/dist/ux/menu.d.ts +7 -0
- package/dist/ux/menu.js +56 -0
- package/dist/ux/menu.js.map +1 -0
- package/dist/ux/prompt.d.ts +7 -0
- package/dist/ux/prompt.js +361 -0
- package/dist/ux/prompt.js.map +1 -0
- package/dist/ux/renderer.d.ts +9 -0
- package/dist/ux/renderer.js +45 -0
- package/dist/ux/renderer.js.map +1 -0
- package/dist/ux/spinner.d.ts +6 -0
- package/dist/ux/spinner.js +42 -0
- package/dist/ux/spinner.js.map +1 -0
- package/dist/ux/statusbar.d.ts +2 -0
- package/dist/ux/statusbar.js +44 -0
- package/dist/ux/statusbar.js.map +1 -0
- package/dist/ux/theme.d.ts +37 -0
- package/dist/ux/theme.js +55 -0
- package/dist/ux/theme.js.map +1 -0
- package/package.json +125 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
import { existsSync, chmodSync, mkdirSync, writeFileSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { spawnSync } from 'child_process';
|
|
4
|
+
import { getConfig, loadLocalConfig, saveLocalConfig } from '../config/config.js';
|
|
5
|
+
import { detectProjectType, getTemplate, hasGitignore, PROJECT_TYPE_LABELS, readGitignore, writeGitignore, } from '../git/gitignore.js';
|
|
6
|
+
import { runRemoteSetup } from '../git/remote-setup.js';
|
|
7
|
+
import { getCurrentBranch, getGitUserConfig, isGitRepo, setDefaultBranch, setGitUserConfig, } from '../git/repo.js';
|
|
8
|
+
import { blank, divider, error, info, keyValue, section, success, warning } from '../ux/display.js';
|
|
9
|
+
import { confirmPrompt, inputPrompt, selectPrompt } from '../ux/prompt.js';
|
|
10
|
+
// ── Status helpers ─────────────────────────────────────────────────────────
|
|
11
|
+
function hooksInstalled(cwd) {
|
|
12
|
+
return {
|
|
13
|
+
commitMsg: existsSync(join(cwd, '.git', 'hooks', 'commit-msg')),
|
|
14
|
+
prePush: existsSync(join(cwd, '.git', 'hooks', 'pre-push')),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function getRemotes(cwd) {
|
|
18
|
+
const r = spawnSync('git', ['remote'], { cwd, encoding: 'utf-8' });
|
|
19
|
+
return r.status === 0 ? r.stdout.trim().split('\n').filter(Boolean) : [];
|
|
20
|
+
}
|
|
21
|
+
function isGhAvailable() {
|
|
22
|
+
return spawnSync('gh', ['--version'], { encoding: 'utf-8' }).status === 0;
|
|
23
|
+
}
|
|
24
|
+
function isGhAuthenticated() {
|
|
25
|
+
return spawnSync('gh', ['auth', 'status'], { encoding: 'utf-8' }).status === 0;
|
|
26
|
+
}
|
|
27
|
+
function fetchGithubIdentity() {
|
|
28
|
+
if (!isGhAvailable() || !isGhAuthenticated())
|
|
29
|
+
return null;
|
|
30
|
+
const name = spawnSync('gh', ['api', 'user', '--jq', '.name'], {
|
|
31
|
+
encoding: 'utf-8',
|
|
32
|
+
}).stdout?.trim();
|
|
33
|
+
const email = spawnSync('gh', ['api', 'user', '--jq', '.email'], {
|
|
34
|
+
encoding: 'utf-8',
|
|
35
|
+
}).stdout?.trim();
|
|
36
|
+
if (!name || name === 'null')
|
|
37
|
+
return null;
|
|
38
|
+
return { name, email: !email || email === 'null' ? '' : email };
|
|
39
|
+
}
|
|
40
|
+
// ── Status overview ────────────────────────────────────────────────────────
|
|
41
|
+
function printStatus(cwd) {
|
|
42
|
+
const config = getConfig();
|
|
43
|
+
const identity = getGitUserConfig(cwd);
|
|
44
|
+
const globalIdentity = getGitUserConfig();
|
|
45
|
+
const branch = getCurrentBranch(cwd);
|
|
46
|
+
const remotes = getRemotes(cwd);
|
|
47
|
+
const hooks = hooksInstalled(cwd);
|
|
48
|
+
const gitignorePresent = hasGitignore(cwd);
|
|
49
|
+
const protected_ = config.git.protectedBranches;
|
|
50
|
+
section('Current Repository Status');
|
|
51
|
+
keyValue('Branch', branch);
|
|
52
|
+
if (identity.name && identity.email) {
|
|
53
|
+
success(`Identity (local): ${identity.name} <${identity.email}>`);
|
|
54
|
+
}
|
|
55
|
+
else if (globalIdentity.name && globalIdentity.email) {
|
|
56
|
+
warning(`Identity: using global (${globalIdentity.name} <${globalIdentity.email}>)`);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
error('Identity: not configured');
|
|
60
|
+
}
|
|
61
|
+
if (gitignorePresent) {
|
|
62
|
+
success('.gitignore: present');
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
warning('.gitignore: missing');
|
|
66
|
+
}
|
|
67
|
+
if (remotes.length > 0) {
|
|
68
|
+
success(`Remote(s): ${remotes.join(', ')}`);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
warning('Remote: none configured');
|
|
72
|
+
}
|
|
73
|
+
const hooksOk = hooks.commitMsg && hooks.prePush;
|
|
74
|
+
const hooksPartial = hooks.commitMsg || hooks.prePush;
|
|
75
|
+
if (hooksOk) {
|
|
76
|
+
success('Git hooks: commit-msg + pre-push installed');
|
|
77
|
+
}
|
|
78
|
+
else if (hooksPartial) {
|
|
79
|
+
warning(`Git hooks: partial (commit-msg: ${hooks.commitMsg ? '✔' : '✘'} pre-push: ${hooks.prePush ? '✔' : '✘'})`);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
info('Git hooks: not installed');
|
|
83
|
+
}
|
|
84
|
+
success(`Protected branches (local): ${protected_.join(', ')}`);
|
|
85
|
+
blank();
|
|
86
|
+
}
|
|
87
|
+
// ── Main command ───────────────────────────────────────────────────────────
|
|
88
|
+
export async function runRepoInit() {
|
|
89
|
+
const cwd = process.cwd();
|
|
90
|
+
if (!isGitRepo(cwd)) {
|
|
91
|
+
warning('Not a Git repository.');
|
|
92
|
+
const init = await confirmPrompt('Initialize a Git repository here first?', true);
|
|
93
|
+
if (!init)
|
|
94
|
+
return;
|
|
95
|
+
spawnSync('git', ['init'], { cwd });
|
|
96
|
+
success('Git repository initialized.');
|
|
97
|
+
blank();
|
|
98
|
+
}
|
|
99
|
+
section('Repository Setup Wizard');
|
|
100
|
+
printStatus(cwd);
|
|
101
|
+
let running = true;
|
|
102
|
+
while (running) {
|
|
103
|
+
const choice = await selectPrompt('What do you want to configure?', [
|
|
104
|
+
'Configure Git identity',
|
|
105
|
+
'Create / update .gitignore',
|
|
106
|
+
'Set up remote repository',
|
|
107
|
+
'Install Git hooks (commit-msg, pre-push)',
|
|
108
|
+
'Configure protected branches',
|
|
109
|
+
'Rename / set default branch',
|
|
110
|
+
'Run all steps',
|
|
111
|
+
'Done',
|
|
112
|
+
]);
|
|
113
|
+
blank();
|
|
114
|
+
switch (choice) {
|
|
115
|
+
case 'Configure Git identity':
|
|
116
|
+
await stepIdentity(cwd);
|
|
117
|
+
break;
|
|
118
|
+
case 'Create / update .gitignore':
|
|
119
|
+
await stepGitignore(cwd);
|
|
120
|
+
break;
|
|
121
|
+
case 'Set up remote repository':
|
|
122
|
+
await runRemoteSetup(cwd);
|
|
123
|
+
break;
|
|
124
|
+
case 'Install Git hooks (commit-msg, pre-push)':
|
|
125
|
+
await stepHooks(cwd);
|
|
126
|
+
break;
|
|
127
|
+
case 'Configure protected branches':
|
|
128
|
+
await stepProtectedBranches(cwd);
|
|
129
|
+
break;
|
|
130
|
+
case 'Rename / set default branch':
|
|
131
|
+
await stepDefaultBranch(cwd);
|
|
132
|
+
break;
|
|
133
|
+
case 'Run all steps':
|
|
134
|
+
await stepDefaultBranch(cwd);
|
|
135
|
+
await stepIdentity(cwd);
|
|
136
|
+
await stepGitignore(cwd);
|
|
137
|
+
await runRemoteSetup(cwd);
|
|
138
|
+
await stepHooks(cwd);
|
|
139
|
+
await stepProtectedBranches(cwd);
|
|
140
|
+
running = false;
|
|
141
|
+
break;
|
|
142
|
+
default:
|
|
143
|
+
running = false;
|
|
144
|
+
}
|
|
145
|
+
if (running && choice !== 'Run all steps') {
|
|
146
|
+
blank();
|
|
147
|
+
printStatus(cwd);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
divider();
|
|
151
|
+
success('Repository setup complete.');
|
|
152
|
+
divider();
|
|
153
|
+
}
|
|
154
|
+
// ── Steps ──────────────────────────────────────────────────────────────────
|
|
155
|
+
async function stepDefaultBranch(cwd) {
|
|
156
|
+
section('Default Branch Name');
|
|
157
|
+
const current = getCurrentBranch(cwd);
|
|
158
|
+
info(`Current branch: ${current}`);
|
|
159
|
+
blank();
|
|
160
|
+
const choice = await selectPrompt('Branch name:', [
|
|
161
|
+
'main (recommended)',
|
|
162
|
+
'master',
|
|
163
|
+
'develop',
|
|
164
|
+
'Custom…',
|
|
165
|
+
'Keep current — skip',
|
|
166
|
+
]);
|
|
167
|
+
if (choice.startsWith('Keep'))
|
|
168
|
+
return;
|
|
169
|
+
let name = 'main';
|
|
170
|
+
if (choice.startsWith('master'))
|
|
171
|
+
name = 'master';
|
|
172
|
+
else if (choice.startsWith('develop'))
|
|
173
|
+
name = 'develop';
|
|
174
|
+
else if (choice.startsWith('Custom')) {
|
|
175
|
+
name = await inputPrompt('Branch name', current);
|
|
176
|
+
if (!name.trim())
|
|
177
|
+
return;
|
|
178
|
+
name = name.trim();
|
|
179
|
+
}
|
|
180
|
+
if (name === current) {
|
|
181
|
+
info('Already on that branch name.');
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
setDefaultBranch(name, cwd);
|
|
185
|
+
// Also try git branch -m for repos that already have commits
|
|
186
|
+
spawnSync('git', ['branch', '-m', current, name], { cwd });
|
|
187
|
+
success(`Branch renamed to "${name}".`);
|
|
188
|
+
blank();
|
|
189
|
+
}
|
|
190
|
+
async function stepIdentity(cwd) {
|
|
191
|
+
section('Git Identity');
|
|
192
|
+
const local = getGitUserConfig(cwd);
|
|
193
|
+
const global = getGitUserConfig();
|
|
194
|
+
const ghIdentity = fetchGithubIdentity();
|
|
195
|
+
if (local.name && local.email) {
|
|
196
|
+
info(`Local identity: ${local.name} <${local.email}>`);
|
|
197
|
+
const change = await confirmPrompt('Change it?', false);
|
|
198
|
+
if (!change)
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const options = [];
|
|
202
|
+
if (ghIdentity) {
|
|
203
|
+
const emailNote = ghIdentity.email
|
|
204
|
+
? ghIdentity.email
|
|
205
|
+
: '(email private — will use GitHub noreply address)';
|
|
206
|
+
options.push(`Use GitHub account: ${ghIdentity.name} <${emailNote}>`);
|
|
207
|
+
}
|
|
208
|
+
if (global.name && global.email) {
|
|
209
|
+
options.push(`Use global git config: ${global.name} <${global.email}>`);
|
|
210
|
+
}
|
|
211
|
+
options.push('Enter manually');
|
|
212
|
+
const choice = options.length === 1
|
|
213
|
+
? (options[0] ?? '')
|
|
214
|
+
: await selectPrompt('Choose identity source:', options);
|
|
215
|
+
let name = '';
|
|
216
|
+
let email = '';
|
|
217
|
+
if (choice.startsWith('Use GitHub account') && ghIdentity) {
|
|
218
|
+
name = ghIdentity.name;
|
|
219
|
+
if (ghIdentity.email) {
|
|
220
|
+
email = ghIdentity.email;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
// Fetch noreply email from GitHub
|
|
224
|
+
const login = spawnSync('gh', ['api', 'user', '--jq', '.login'], {
|
|
225
|
+
encoding: 'utf-8',
|
|
226
|
+
}).stdout?.trim();
|
|
227
|
+
const id = spawnSync('gh', ['api', 'user', '--jq', '.id'], {
|
|
228
|
+
encoding: 'utf-8',
|
|
229
|
+
}).stdout?.trim();
|
|
230
|
+
if (login && id) {
|
|
231
|
+
email = `${id}+${login}@users.noreply.github.com`;
|
|
232
|
+
info(`Using GitHub noreply email: ${email}`);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
email = await inputPrompt('Email (your email was private)', '');
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else if (choice.startsWith('Use global git config') && global.name && global.email) {
|
|
240
|
+
name = global.name;
|
|
241
|
+
email = global.email;
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
name = await inputPrompt('Your name', global.name || '');
|
|
245
|
+
email = await inputPrompt('Your email', global.email || '');
|
|
246
|
+
}
|
|
247
|
+
if (name.trim() && email.trim()) {
|
|
248
|
+
setGitUserConfig(name.trim(), email.trim(), cwd);
|
|
249
|
+
success(`Identity set: ${name.trim()} <${email.trim()}>`);
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
warning('Identity not changed.');
|
|
253
|
+
}
|
|
254
|
+
blank();
|
|
255
|
+
}
|
|
256
|
+
async function stepGitignore(cwd) {
|
|
257
|
+
section('.gitignore');
|
|
258
|
+
const detected = detectProjectType(cwd);
|
|
259
|
+
const existing = hasGitignore(cwd);
|
|
260
|
+
if (existing) {
|
|
261
|
+
const current = readGitignore(cwd);
|
|
262
|
+
info('.gitignore already exists.');
|
|
263
|
+
console.log('\n First lines:');
|
|
264
|
+
current
|
|
265
|
+
.split('\n')
|
|
266
|
+
.slice(0, 8)
|
|
267
|
+
.forEach((l) => console.log(' ' + l));
|
|
268
|
+
blank();
|
|
269
|
+
const action = await selectPrompt('What do you want to do?', [
|
|
270
|
+
`Append ${PROJECT_TYPE_LABELS[detected]} template (detected)`,
|
|
271
|
+
'Replace with a template',
|
|
272
|
+
'Skip — keep as is',
|
|
273
|
+
]);
|
|
274
|
+
if (action.startsWith('Skip'))
|
|
275
|
+
return;
|
|
276
|
+
if (action.startsWith('Append')) {
|
|
277
|
+
const template = getTemplate(detected);
|
|
278
|
+
writeGitignore(current.trimEnd() + '\n\n# --- git-smart-flow ---\n' + template, cwd);
|
|
279
|
+
success('.gitignore updated.');
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
// Fall through to template selection below
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
info(`Detected project type: ${PROJECT_TYPE_LABELS[detected]}`);
|
|
286
|
+
}
|
|
287
|
+
const typeLabels = [
|
|
288
|
+
{ key: detected, label: `${PROJECT_TYPE_LABELS[detected]} (detected)` },
|
|
289
|
+
{ key: 'node', label: 'Node.js / TypeScript / JavaScript' },
|
|
290
|
+
{ key: 'python', label: 'Python' },
|
|
291
|
+
{ key: 'java', label: 'Java / Kotlin (Maven / Gradle)' },
|
|
292
|
+
{ key: 'go', label: 'Go' },
|
|
293
|
+
{ key: 'rust', label: 'Rust' },
|
|
294
|
+
{ key: 'generic', label: 'Generic (editor files, env, logs)' },
|
|
295
|
+
{ key: 'generic', label: 'Skip' },
|
|
296
|
+
];
|
|
297
|
+
const unique = typeLabels.filter((v, i, a) => a.findIndex((x) => x.label === v.label) === i);
|
|
298
|
+
const labelStrings = unique.map((t) => t.label);
|
|
299
|
+
const choice = await selectPrompt('Choose template:', labelStrings);
|
|
300
|
+
if (choice === 'Skip')
|
|
301
|
+
return;
|
|
302
|
+
const matched = unique.find((t) => t.label === choice);
|
|
303
|
+
const chosenType = matched?.key ?? detected;
|
|
304
|
+
writeGitignore(getTemplate(chosenType), cwd);
|
|
305
|
+
success(`.gitignore ${existing ? 'replaced' : 'created'} (${PROJECT_TYPE_LABELS[chosenType]} template).`);
|
|
306
|
+
blank();
|
|
307
|
+
}
|
|
308
|
+
const COMMIT_MSG_HOOK = `#!/usr/bin/env bash
|
|
309
|
+
# git-smart-flow: commit-msg hook — validates Conventional Commits format
|
|
310
|
+
COMMIT_MSG=$(cat "$1")
|
|
311
|
+
if echo "$COMMIT_MSG" | grep -qE "^Merge "; then exit 0; fi
|
|
312
|
+
if ! echo "$COMMIT_MSG" | grep -qE "^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\\\\(.+\\\\))?!?: .+"; then
|
|
313
|
+
echo "✘ Commit message does not follow Conventional Commits."
|
|
314
|
+
echo " Expected: <type>(<scope>): <description>"
|
|
315
|
+
echo " Example: feat(auth): add login validation"
|
|
316
|
+
exit 1
|
|
317
|
+
fi
|
|
318
|
+
exit 0
|
|
319
|
+
`;
|
|
320
|
+
const PRE_PUSH_HOOK = `#!/usr/bin/env bash
|
|
321
|
+
# git-smart-flow: pre-push hook — warns before pushing to protected branches
|
|
322
|
+
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --abbrev-ref HEAD)
|
|
323
|
+
PROTECTED="main master develop"
|
|
324
|
+
for P in $PROTECTED; do
|
|
325
|
+
if [ "$BRANCH" = "$P" ]; then
|
|
326
|
+
printf "\\n⚠ Pushing to protected branch: %s\\n" "$BRANCH"
|
|
327
|
+
printf "Are you sure? [y/N] "
|
|
328
|
+
read -r REPLY
|
|
329
|
+
if [ "$REPLY" != "y" ] && [ "$REPLY" != "Y" ]; then
|
|
330
|
+
echo "Push cancelled."
|
|
331
|
+
exit 1
|
|
332
|
+
fi
|
|
333
|
+
fi
|
|
334
|
+
done
|
|
335
|
+
exit 0
|
|
336
|
+
`;
|
|
337
|
+
async function stepHooks(cwd) {
|
|
338
|
+
section('Git Hooks');
|
|
339
|
+
const hooks = hooksInstalled(cwd);
|
|
340
|
+
info(`commit-msg hook: ${hooks.commitMsg ? 'installed ✔' : 'not installed'}`);
|
|
341
|
+
info(`pre-push hook: ${hooks.prePush ? 'installed ✔' : 'not installed'}`);
|
|
342
|
+
blank();
|
|
343
|
+
const choices = [];
|
|
344
|
+
if (!hooks.commitMsg || !hooks.prePush)
|
|
345
|
+
choices.push('Install all hooks');
|
|
346
|
+
if (hooks.commitMsg || hooks.prePush)
|
|
347
|
+
choices.push('Reinstall / overwrite all hooks');
|
|
348
|
+
if (!hooks.commitMsg)
|
|
349
|
+
choices.push('Install commit-msg only (validates Conventional Commits)');
|
|
350
|
+
if (!hooks.prePush)
|
|
351
|
+
choices.push('Install pre-push only (warns on protected branch push)');
|
|
352
|
+
choices.push('Skip');
|
|
353
|
+
const choice = await selectPrompt('Git hooks action:', choices);
|
|
354
|
+
if (choice === 'Skip')
|
|
355
|
+
return;
|
|
356
|
+
const hooksDir = join(cwd, '.git', 'hooks');
|
|
357
|
+
if (!existsSync(hooksDir))
|
|
358
|
+
mkdirSync(hooksDir, { recursive: true });
|
|
359
|
+
const installCommitMsg = choice.includes('commit-msg') || choice.includes('all');
|
|
360
|
+
const installPrePush = choice.includes('pre-push') || choice.includes('all');
|
|
361
|
+
if (installCommitMsg) {
|
|
362
|
+
const p = join(hooksDir, 'commit-msg');
|
|
363
|
+
writeFileSync(p, COMMIT_MSG_HOOK, 'utf-8');
|
|
364
|
+
chmodSync(p, '755');
|
|
365
|
+
success('commit-msg hook installed.');
|
|
366
|
+
}
|
|
367
|
+
if (installPrePush) {
|
|
368
|
+
const p = join(hooksDir, 'pre-push');
|
|
369
|
+
writeFileSync(p, PRE_PUSH_HOOK, 'utf-8');
|
|
370
|
+
chmodSync(p, '755');
|
|
371
|
+
success('pre-push hook installed.');
|
|
372
|
+
}
|
|
373
|
+
blank();
|
|
374
|
+
info('Hooks run automatically on commit and push.');
|
|
375
|
+
info('To bypass in an emergency: git commit --no-verify');
|
|
376
|
+
blank();
|
|
377
|
+
}
|
|
378
|
+
async function stepProtectedBranches(cwd) {
|
|
379
|
+
section('Protected Branches (local gsf config)');
|
|
380
|
+
const config = getConfig();
|
|
381
|
+
const current = config.git.protectedBranches;
|
|
382
|
+
info(`Currently protected: ${current.join(', ')}`);
|
|
383
|
+
blank();
|
|
384
|
+
info('gsf will warn and require confirmation before committing or pushing to these branches.');
|
|
385
|
+
info('Note: server-side branch protection rules must be set in your GitHub/GitLab repo settings.');
|
|
386
|
+
blank();
|
|
387
|
+
const change = await confirmPrompt('Edit the protected branches list?', false);
|
|
388
|
+
if (!change)
|
|
389
|
+
return;
|
|
390
|
+
const raw = await inputPrompt('Protected branches (comma-separated)', current.join(', '));
|
|
391
|
+
const branches = raw
|
|
392
|
+
.split(',')
|
|
393
|
+
.map((b) => b.trim())
|
|
394
|
+
.filter(Boolean);
|
|
395
|
+
if (branches.length === 0) {
|
|
396
|
+
info('No changes made.');
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
// Save to local config so it applies only to this repo
|
|
400
|
+
const local = loadLocalConfig(cwd) ?? {};
|
|
401
|
+
const updated = {
|
|
402
|
+
...local,
|
|
403
|
+
git: {
|
|
404
|
+
...(local.git ?? {}),
|
|
405
|
+
protectedBranches: branches,
|
|
406
|
+
},
|
|
407
|
+
};
|
|
408
|
+
saveLocalConfig(updated, cwd);
|
|
409
|
+
success(`Protected branches updated: ${branches.join(', ')}`);
|
|
410
|
+
info('Saved to .git-smart-flow.json (local config for this repo).');
|
|
411
|
+
blank();
|
|
412
|
+
// Offer GitHub branch protection guidance
|
|
413
|
+
const remotes = getRemotes(cwd);
|
|
414
|
+
if (remotes.length > 0 && isGhAvailable() && isGhAuthenticated()) {
|
|
415
|
+
const ghProtect = await confirmPrompt('Also set branch protection rules on GitHub via gh CLI?', false);
|
|
416
|
+
if (ghProtect) {
|
|
417
|
+
setGitHubBranchProtection(cwd, branches);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
else if (remotes.length > 0) {
|
|
421
|
+
blank();
|
|
422
|
+
info('To add server-side branch protection on GitHub:');
|
|
423
|
+
console.log(' Settings → Branches → Add rule → enter branch name → enable "Require pull request reviews"');
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
function setGitHubBranchProtection(cwd, branches) {
|
|
427
|
+
// Detect repo from remote
|
|
428
|
+
const remoteUrl = spawnSync('git', ['remote', 'get-url', 'origin'], {
|
|
429
|
+
cwd,
|
|
430
|
+
encoding: 'utf-8',
|
|
431
|
+
}).stdout?.trim();
|
|
432
|
+
if (!remoteUrl) {
|
|
433
|
+
warning('Could not detect GitHub repo from origin remote.');
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const match = remoteUrl.match(/github\.com[:/]([^/]+\/[^/.]+)/);
|
|
437
|
+
if (!match) {
|
|
438
|
+
warning('Origin does not look like a GitHub repository.');
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
const repo = match[1];
|
|
442
|
+
for (const branch of branches) {
|
|
443
|
+
info(`Setting protection for "${branch}" on ${repo}...`);
|
|
444
|
+
const result = spawnSync('gh', [
|
|
445
|
+
'api',
|
|
446
|
+
`repos/${repo}/branches/${branch}/protection`,
|
|
447
|
+
'--method',
|
|
448
|
+
'PUT',
|
|
449
|
+
'--field',
|
|
450
|
+
'required_status_checks=null',
|
|
451
|
+
'--field',
|
|
452
|
+
'enforce_admins=false',
|
|
453
|
+
'--field',
|
|
454
|
+
'required_pull_request_reviews[required_approving_review_count]=1',
|
|
455
|
+
'--field',
|
|
456
|
+
'restrictions=null',
|
|
457
|
+
], { cwd, encoding: 'utf-8' });
|
|
458
|
+
if (result.status === 0) {
|
|
459
|
+
success(`Branch protection enabled for "${branch}" on GitHub.`);
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
warning(`Could not set protection for "${branch}" — branch may not exist on remote yet.`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
//# sourceMappingURL=repo-init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-init.js","sourceRoot":"","sources":["../../src/commands/repo-init.ts"],"names":[],"mappings":"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"}
|