Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "commitollama",
"description": "AI Commits with ollama",
"publisher": "Commitollama",
"version": "3.0.0",
"version": "3.0.1",
"repository": {
"type": "git",
"url": "https://github.com/anjerodev/commitollama.git"
Expand Down
26 changes: 26 additions & 0 deletions src/diffFallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export function buildDiffFallbackSummary(file: string, diff: string): string {
const lines = diff.split('\n')
const addedLines = lines
.filter((line) => line.startsWith('+') && !line.startsWith('+++'))
.map((line) => line.slice(1).trim())
.filter(Boolean)
const removedCount = lines.filter(
(line) => line.startsWith('-') && !line.startsWith('---'),
).length

if (addedLines.length > 0) {
const preview = addedLines.slice(0, 2).join('; ')
const clipped =
preview.length > 80 ? `${preview.slice(0, 77)}...` : preview
if (removedCount > 0) {
return `Update ${file}: add ${addedLines.length} line(s), remove ${removedCount} line(s) — ${clipped}`
}
return `Update ${file}: add ${addedLines.length} line(s) — ${clipped}`
}

if (removedCount > 0) {
return `Update ${file}: remove ${removedCount} line(s)`
}

return `Update ${file}`
}
5 changes: 4 additions & 1 deletion src/scheduler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as vscode from 'vscode'
import { summaryCache } from './cache'
import { isLowQualitySummary } from './commitQuality'
import { config } from './config'
import { logExtensionError } from './security/log'
import { summarizeFileDiff } from './summarizer'
Expand Down Expand Up @@ -101,7 +102,9 @@ export class BackgroundScanner {
}

const summary = await summarizeFileDiff(workingDiff)
summaryCache.set(uri.fsPath, hash, summary)
if (!isLowQualitySummary(summary)) {
summaryCache.set(uri.fsPath, hash, summary)
}
} catch (error) {
logExtensionError(`backgroundScan ${uri.fsPath}`, error)
}
Expand Down
32 changes: 32 additions & 0 deletions src/test/diffFallback.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as assert from 'node:assert'
import { buildDiffFallbackSummary } from '../diffFallback'

suite('diff fallback', () => {
test('Should summarize added lines from a unified diff', () => {
const diff = [
'--- a/src/foo.ts',
'+++ b/src/foo.ts',
'@@ -1,2 +1,3 @@',
' const x = 1',
'+const y = 2',
' return x',
].join('\n')

const summary = buildDiffFallbackSummary('src/foo.ts', diff)
assert.match(summary, /add 1 line/)
assert.match(summary, /const y = 2/)
})

test('Should summarize removed lines', () => {
const diff = [
'--- a/src/foo.ts',
'+++ b/src/foo.ts',
'@@ -1,2 +1,1 @@',
'-const y = 2',
' const x = 1',
].join('\n')

const summary = buildDiffFallbackSummary('src/foo.ts', diff)
assert.match(summary, /remove 1 line/)
})
})
76 changes: 52 additions & 24 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { relative } from 'node:path'
import * as vscode from 'vscode'
import { summaryCache } from './cache'
import { isLowQualitySummary } from './commitQuality'
import { buildDiffFallbackSummary } from './diffFallback'
import { type ChangeSummary, getCommitMessage } from './generator'
import { ensureModelSelected } from './modelSelection'
import { formatExtensionError, logExtensionError } from './security/log'
Expand All @@ -23,39 +25,62 @@ export function setConfig<K extends keyof ExtensionConfig>(
.update(key, value, vscode.ConfigurationTarget.Workspace)
}

function getRepoRelativePath(repo: Repository, uri: vscode.Uri): string {
const rootPath = repo.rootUri.fsPath
if (uri.fsPath.startsWith(rootPath)) {
return relative(rootPath, uri.fsPath).replace(/\\/g, '/')
}
return vscode.workspace.asRelativePath(uri, false)
}

export async function getSummaryUriDiff(
repo: Repository,
uri: vscode.Uri,
): Promise<string> {
const path = vscode.workspace.asRelativePath(uri)
const path = getRepoRelativePath(repo, uri)
return repo.diffIndexWithHEAD(path)
}

async function resolveSummary(
file: string,
cacheKey: string,
diff: string,
diffHash: string,
): Promise<string> {
const cached = summaryCache.get(cacheKey)
if (cached?.diffHash === diffHash && !isLowQualitySummary(cached.summary)) {
return cached.summary
}

try {
const summary = await summarizeFileDiff(diff)
if (!isLowQualitySummary(summary)) {
summaryCache.set(cacheKey, diffHash, summary)
return summary
}
} catch (error) {
logExtensionError('summarizeStagedChange', error)
}

return buildDiffFallbackSummary(file, diff)
}

async function summarizeStagedChange(
repo: Repository,
uri: vscode.Uri,
): Promise<ChangeSummary | null> {
const path = vscode.workspace.asRelativePath(uri)
const path = getRepoRelativePath(repo, uri)
const diff = await repo.diffIndexWithHEAD(path)
if (!diff || diff.trim() === '') {
return null
}

const hash = summaryCache.computeHash(diff)
const cached = summaryCache.get(uri.fsPath)

let summary: string
if (cached && cached.diffHash === hash) {
summary = cached.summary
} else {
summary = await summarizeFileDiff(diff)
summaryCache.set(uri.fsPath, hash, summary)
}

if (isLowQualitySummary(summary)) {
return null
}

const summary = await resolveSummary(
path,
uri.fsPath,
diff,
summaryCache.computeHash(diff),
)
return { file: path, summary }
}

Expand Down Expand Up @@ -95,13 +120,16 @@ export async function createCommitMessage(repo: Repository) {
if (summaries.length === 0) {
const fullDiff = await repo.diff(true)
if (fullDiff?.trim()) {
const summary = await summarizeFileDiff(fullDiff)
if (!isLowQualitySummary(summary)) {
summaries.push({
file: 'staged changes',
summary,
})
}
const summary = await resolveSummary(
'staged changes',
'staged changes',
fullDiff,
summaryCache.computeHash(fullDiff),
)
summaries.push({
file: 'staged changes',
summary,
})
}
}

Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"module": "commonjs",
"target": "ES2021",
"lib": ["ES2021", "DOM"],
"typeRoots": ["./node_modules/@types"],
"types": ["node", "mocha"],
"skipLibCheck": true,
"noEmit": true,
Expand Down
Loading