git-coco 0.4.0 → 0.5.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/dist/index.esm.mjs +89 -26
- package/dist/index.esm.mjs.map +1 -1
- package/dist/index.js +89 -26
- package/dist/lib/config/types.d.ts +6 -0
- package/dist/lib/simple-git/getCommitLogCurrentBranch.d.ts +9 -0
- package/dist/lib/simple-git/getCurrentBranchName.d.ts +5 -0
- package/dist/lib/simple-git/getRepo.d.ts +2 -0
- package/dist/stats.html +1 -1
- package/package.json +2 -2
package/dist/index.esm.mjs
CHANGED
|
@@ -19,8 +19,8 @@ import { minimatch } from 'minimatch';
|
|
|
19
19
|
import * as fs from 'fs';
|
|
20
20
|
import * as os from 'os';
|
|
21
21
|
import * as ini from 'ini';
|
|
22
|
-
import { simpleGit } from 'simple-git';
|
|
23
22
|
import { editor, select } from '@inquirer/prompts';
|
|
23
|
+
import { simpleGit } from 'simple-git';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Extract the path from a file path string.
|
|
@@ -606,6 +606,7 @@ function loadEnvConfig(config) {
|
|
|
606
606
|
ignoredExtensions: process.env.COCO_IGNORED_EXTENSIONS
|
|
607
607
|
? process.env.COCO_IGNORED_EXTENSIONS.split(',')
|
|
608
608
|
: undefined,
|
|
609
|
+
defaultBranch: process.env.COCO_DEFAULT_BRANCH || undefined,
|
|
609
610
|
};
|
|
610
611
|
config = { ...config, ...removeUndefined(envConfig) };
|
|
611
612
|
return config;
|
|
@@ -634,6 +635,7 @@ function loadGitConfig(config) {
|
|
|
634
635
|
summarizePrompt: gitConfigParsed.coco?.summarizePrompt || config.summarizePrompt,
|
|
635
636
|
ignoredFiles: gitConfigParsed.coco?.ignoredFiles || config.ignoredFiles,
|
|
636
637
|
ignoredExtensions: gitConfigParsed.coco?.ignoredExtensions || config.ignoredExtensions,
|
|
638
|
+
defaultBranch: gitConfigParsed.coco?.defaultBranch || config.defaultBranch,
|
|
637
639
|
};
|
|
638
640
|
}
|
|
639
641
|
return config;
|
|
@@ -679,6 +681,8 @@ function loadIgnore(config) {
|
|
|
679
681
|
* @returns {Config} Updated config
|
|
680
682
|
**/
|
|
681
683
|
function loadProjectConfig(config) {
|
|
684
|
+
// TODO: Add validation based of JSON schema?
|
|
685
|
+
// @see https://github.com/acornejo/jjv
|
|
682
686
|
if (fs.existsSync('.coco.config.json')) {
|
|
683
687
|
const projectConfig = JSON.parse(fs.readFileSync('.coco.config.json', 'utf-8'));
|
|
684
688
|
config = { ...config, ...projectConfig };
|
|
@@ -716,6 +720,7 @@ const DEFAULT_CONFIG = {
|
|
|
716
720
|
mode: 'stdout',
|
|
717
721
|
ignoredFiles: ['package-lock.json'],
|
|
718
722
|
ignoredExtensions: ['.map', '.lock'],
|
|
723
|
+
defaultBranch: 'main',
|
|
719
724
|
};
|
|
720
725
|
/**
|
|
721
726
|
* Load application config
|
|
@@ -1016,9 +1021,21 @@ const handleResult = async (result, { mode, git }) => {
|
|
|
1016
1021
|
process.exit(0);
|
|
1017
1022
|
};
|
|
1018
1023
|
|
|
1019
|
-
const
|
|
1020
|
-
|
|
1024
|
+
const getRepo = () => {
|
|
1025
|
+
let git;
|
|
1026
|
+
try {
|
|
1027
|
+
git = simpleGit();
|
|
1028
|
+
}
|
|
1029
|
+
catch (e) {
|
|
1030
|
+
console.log('Error initializing git repo', e);
|
|
1031
|
+
process.exit(1);
|
|
1032
|
+
}
|
|
1033
|
+
return git;
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1021
1036
|
async function handler$1(argv) {
|
|
1037
|
+
const tokenizer = getTokenizer();
|
|
1038
|
+
const git = getRepo();
|
|
1022
1039
|
const options = loadConfig(argv);
|
|
1023
1040
|
const logger = new Logger(options);
|
|
1024
1041
|
const key = getApiKeyForModel(options.model, options);
|
|
@@ -1032,14 +1049,14 @@ async function handler$1(argv) {
|
|
|
1032
1049
|
});
|
|
1033
1050
|
const INTERACTIVE = isInteractive(options);
|
|
1034
1051
|
async function factory() {
|
|
1035
|
-
const changes = await getChanges({ git
|
|
1052
|
+
const changes = await getChanges({ git });
|
|
1036
1053
|
return changes.staged;
|
|
1037
1054
|
}
|
|
1038
1055
|
async function parser(changes) {
|
|
1039
1056
|
return await fileChangeParser({
|
|
1040
1057
|
changes,
|
|
1041
1058
|
commit: '--staged',
|
|
1042
|
-
options: { tokenizer, git
|
|
1059
|
+
options: { tokenizer, git, model, logger },
|
|
1043
1060
|
});
|
|
1044
1061
|
}
|
|
1045
1062
|
const commitMsg = await generateAndReviewLoop({
|
|
@@ -1058,7 +1075,7 @@ async function handler$1(argv) {
|
|
|
1058
1075
|
});
|
|
1059
1076
|
},
|
|
1060
1077
|
noResult: async () => {
|
|
1061
|
-
await noResult({ git
|
|
1078
|
+
await noResult({ git, logger });
|
|
1062
1079
|
process.exit(0);
|
|
1063
1080
|
},
|
|
1064
1081
|
options: {
|
|
@@ -1071,7 +1088,7 @@ async function handler$1(argv) {
|
|
|
1071
1088
|
const MODE = (INTERACTIVE && 'interactive') || (options.commit && 'interactive') || options?.mode || 'stdout';
|
|
1072
1089
|
handleResult(commitMsg, {
|
|
1073
1090
|
mode: MODE,
|
|
1074
|
-
git
|
|
1091
|
+
git,
|
|
1075
1092
|
});
|
|
1076
1093
|
}
|
|
1077
1094
|
|
|
@@ -1152,15 +1169,9 @@ const CHANGELOG_PROMPT = new PromptTemplate({
|
|
|
1152
1169
|
|
|
1153
1170
|
async function getCommitLogRange(from, to, { noMerges, git }) {
|
|
1154
1171
|
try {
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
'--pretty=format:%s',
|
|
1159
|
-
// Include '--no-merges' here if you want to exclude merge commits.
|
|
1160
|
-
noMerges ? '--no-merges' : null,
|
|
1161
|
-
].filter(Boolean)); // filter(Boolean) removes any null values from the array
|
|
1162
|
-
const messages = output.split('\n').filter(Boolean);
|
|
1163
|
-
return messages;
|
|
1172
|
+
const logOptions = { from: `${from}^1`, to, '--no-merges': noMerges };
|
|
1173
|
+
const commitLog = await git.log(logOptions);
|
|
1174
|
+
return commitLog.all.map(({ message, date, body, author_name }) => `[${date}] ${message}\n${body}\n - ${author_name}`);
|
|
1164
1175
|
}
|
|
1165
1176
|
catch (error) {
|
|
1166
1177
|
// If there's an error, handle it appropriately
|
|
@@ -1169,10 +1180,56 @@ async function getCommitLogRange(from, to, { noMerges, git }) {
|
|
|
1169
1180
|
}
|
|
1170
1181
|
}
|
|
1171
1182
|
|
|
1172
|
-
|
|
1183
|
+
async function getCurrentBranchName({ git }) {
|
|
1184
|
+
return await git.revparse(['--abbrev-ref', 'HEAD']);
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
async function getCommitLogCurrentBranch({ git, logger, comparisonBranch = 'main', comparisonRemote = 'origin', }) {
|
|
1188
|
+
try {
|
|
1189
|
+
// Get the current branch name
|
|
1190
|
+
const branch = await getCurrentBranchName({ git });
|
|
1191
|
+
// Check if the current branch has any commits
|
|
1192
|
+
const hasCommits = (await git.raw(['rev-list', '--count', branch])) !== '0';
|
|
1193
|
+
if (!hasCommits) {
|
|
1194
|
+
logger?.log('No commits on the current branch.');
|
|
1195
|
+
return [];
|
|
1196
|
+
}
|
|
1197
|
+
// Get the list of commits that are unique to the current branch
|
|
1198
|
+
let uniqueCommits;
|
|
1199
|
+
if (comparisonBranch === branch) {
|
|
1200
|
+
// If the comparison branch is the same as the current branch, we compare against the remote.
|
|
1201
|
+
uniqueCommits = (await git.raw(['rev-list', `${comparisonRemote}/${comparisonBranch}..${branch}`]))
|
|
1202
|
+
.split('\n')
|
|
1203
|
+
.filter(Boolean)
|
|
1204
|
+
.reverse();
|
|
1205
|
+
}
|
|
1206
|
+
else {
|
|
1207
|
+
// Your existing code for different branches
|
|
1208
|
+
uniqueCommits = (await git.raw(['rev-list', `${comparisonBranch}..${branch}`]))
|
|
1209
|
+
.split('\n')
|
|
1210
|
+
.filter(Boolean)
|
|
1211
|
+
.reverse();
|
|
1212
|
+
}
|
|
1213
|
+
logger?.verbose(`Found ${uniqueCommits.length} unique commits on "${branch}"`, { color: 'blue' });
|
|
1214
|
+
const firstCommit = uniqueCommits[0];
|
|
1215
|
+
const lastCommit = uniqueCommits[uniqueCommits.length - 1];
|
|
1216
|
+
if (!firstCommit || !lastCommit) {
|
|
1217
|
+
logger?.log('Unable to determine first and last commit on the current branch', { color: 'yellow' });
|
|
1218
|
+
return [];
|
|
1219
|
+
}
|
|
1220
|
+
// Retrieve commit log with messages
|
|
1221
|
+
return await getCommitLogRange(firstCommit, lastCommit, { git, noMerges: true });
|
|
1222
|
+
}
|
|
1223
|
+
catch (error) {
|
|
1224
|
+
logger?.log('Encountered an error getting commit log from current branch', { color: 'red' });
|
|
1225
|
+
}
|
|
1226
|
+
return [];
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1173
1229
|
async function handler(argv) {
|
|
1174
1230
|
const options = loadConfig(argv);
|
|
1175
1231
|
const logger = new Logger(options);
|
|
1232
|
+
const git = getRepo();
|
|
1176
1233
|
const key = getApiKeyForModel(options.model, options);
|
|
1177
1234
|
if (!key) {
|
|
1178
1235
|
logger.log(`No API Key found. 🗝️🚪`, { color: 'red' });
|
|
@@ -1183,14 +1240,17 @@ async function handler(argv) {
|
|
|
1183
1240
|
maxConcurrency: 10,
|
|
1184
1241
|
});
|
|
1185
1242
|
const INTERACTIVE = isInteractive(options);
|
|
1186
|
-
const [from, to] = options.range?.split(':');
|
|
1187
|
-
if (!from || !to) {
|
|
1188
|
-
logger.log(`Invalid range provided. Expected format is <from>:<to>`, { color: 'red' });
|
|
1189
|
-
process.exit(1);
|
|
1190
|
-
}
|
|
1191
1243
|
async function factory() {
|
|
1192
|
-
|
|
1193
|
-
|
|
1244
|
+
if (options.range) {
|
|
1245
|
+
const [from, to] = options.range?.split(':');
|
|
1246
|
+
if (!from || !to) {
|
|
1247
|
+
logger.log(`Invalid range provided. Expected format is <from>:<to>`, { color: 'red' });
|
|
1248
|
+
process.exit(1);
|
|
1249
|
+
}
|
|
1250
|
+
return await getCommitLogRange(from, to, { git, noMerges: true });
|
|
1251
|
+
}
|
|
1252
|
+
logger.verbose(`No range provided. Defaulting to current branch`, { color: 'yellow' });
|
|
1253
|
+
return await getCommitLogCurrentBranch({ git, logger });
|
|
1194
1254
|
}
|
|
1195
1255
|
async function parser(messages) {
|
|
1196
1256
|
const result = messages.join('\n');
|
|
@@ -1213,7 +1273,11 @@ async function handler(argv) {
|
|
|
1213
1273
|
});
|
|
1214
1274
|
},
|
|
1215
1275
|
noResult: async () => {
|
|
1216
|
-
|
|
1276
|
+
if (options.range) {
|
|
1277
|
+
logger.log(`No commits found in the provided range.`, { color: 'red' });
|
|
1278
|
+
process.exit(0);
|
|
1279
|
+
}
|
|
1280
|
+
logger.log(`No commits found in the current branch.`, { color: 'red' });
|
|
1217
1281
|
process.exit(0);
|
|
1218
1282
|
},
|
|
1219
1283
|
options: {
|
|
@@ -1238,7 +1302,6 @@ const options = {
|
|
|
1238
1302
|
type: 'string',
|
|
1239
1303
|
alias: 'r',
|
|
1240
1304
|
description: 'Commit range e.g `HEAD~2:HEAD`',
|
|
1241
|
-
demandOption: true,
|
|
1242
1305
|
},
|
|
1243
1306
|
model: { type: 'string', description: 'LLM/Model-Name' },
|
|
1244
1307
|
openAIApiKey: {
|