Skip to content

Commit 5f89cdc

Browse files
committed
✨ Add logging and caching configuration options to enhance debugging and performance
The commit introduces new configuration options for logging and caching in OpenCommit. Users can now enable/disable logging and caching, and customize the directories for storing logs and cache files. This improves debugging capabilities, performance optimization, and pre-commit hook integration. The changes include updates to the README.md documentation, configuration handling in config.ts, and enhancements to the commit cache and logger utilities.
1 parent f7972d1 commit 5f89cdc

File tree

4 files changed

+128
-24
lines changed

4 files changed

+128
-24
lines changed

README.md

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ OCO_LANGUAGE=<locale, scroll to the bottom to see options>
118118
OCO_MESSAGE_TEMPLATE_PLACEHOLDER=<message template placeholder, default: '$msg'>
119119
OCO_PROMPT_MODULE=<either conventional-commit or @commitlint, default: conventional-commit>
120120
OCO_ONE_LINE_COMMIT=<one line commit message, default: false>
121+
OCO_ENABLE_LOGGING=<boolean, enable/disable logging, default: true>
122+
OCO_ENABLE_CACHE=<boolean, enable/disable commit message caching, default: true>
123+
OCO_CACHE_DIR=<custom directory for storing commit message cache>
124+
OCO_LOG_DIR=<custom directory for storing log files>
121125
```
122126

123127
Global configs are same as local configs, but they are stored in the global `~/.opencommit` config file and set with `oco config set` command, e.g. `oco config set OCO_MODEL=gpt-4o`.
@@ -205,6 +209,52 @@ oco config set OCO_LANGUAGE=française
205209
The default language setting is **English**
206210
All available languages are currently listed in the [i18n](https://github.com/di-sukharev/opencommit/tree/master/src/i18n) folder
207211

212+
### Logging and Caching Configuration
213+
214+
OpenCommit provides options to control logging and caching behavior. These features help with debugging, performance optimization, and pre-commit hook integration.
215+
216+
#### Logging Configuration
217+
218+
You can enable/disable logging and customize the log directory:
219+
220+
```sh
221+
# Disable logging
222+
oco config set OCO_ENABLE_LOGGING=false
223+
224+
# Set custom log directory
225+
oco config set OCO_LOG_DIR=/path/to/custom/logs
226+
```
227+
228+
By default:
229+
- Logs are stored in `~/.cache/opencommit/logs/` directory
230+
- Logs include commit generation process, errors, and pre-commit hook results
231+
- Each log entry is timestamped and categorized by level (INFO, ERROR, etc.)
232+
233+
#### Caching Configuration
234+
235+
OpenCommit caches commit messages to improve performance and provide better suggestions, especially useful during pre-commit hook operations:
236+
237+
```sh
238+
# Disable commit message caching
239+
oco config set OCO_ENABLE_CACHE=false
240+
241+
# Set custom cache directory
242+
oco config set OCO_CACHE_DIR=/path/to/custom/cache
243+
```
244+
245+
By default:
246+
- Caching is enabled
247+
- Cache files are stored in `~/.cache/opencommit/` directory
248+
- Cache entries expire after 7 days
249+
- Each repository has its own cache file
250+
- Cache includes successful commit messages and their associated file changes
251+
- Cache is automatically cleared after successful commits
252+
- Cache helps speed up pre-commit hook operations by reusing recent commit messages
253+
254+
The cache system is cross-platform compatible and follows XDG Base Directory specifications on Linux systems.
255+
256+
> Note: When using pre-commit hooks, logging and caching are particularly useful for debugging issues and improving performance. The log files contain detailed information about hook execution and any failures that might occur.
257+
208258
### Push to git (gonna be deprecated)
209259

210260
A prompt for pushing to git is on by default but if you would like to turn it off just use:
@@ -280,7 +330,7 @@ git commit -m "${generatedMessage}" --no-verify
280330
To include a message in the generated message, you can utilize the template function, for instance:
281331

282332
```sh
283-
oco '#205: $msg
333+
oco '#205: $msg'
284334
```
285335

286336
> opencommit examines placeholders in the parameters, allowing you to append additional information before and after the placeholders, such as the relevant Issue or Pull Request. Similarly, you have the option to customize the OCO_MESSAGE_TEMPLATE_PLACEHOLDER configuration item, for example, simplifying it to $m!"
@@ -306,7 +356,7 @@ This line is responsible for replacing the placeholder in the `messageTemplate`
306356

307357
#### Usage
308358

309-
For instance, using the command `oco '$msg #205`, users can leverage this feature. The provided code represents the backend mechanics of such commands, ensuring that the placeholder is replaced with the appropriate commit message.
359+
For instance, using the command `oco '$msg #205'`, users can leverage this feature. The provided code represents the backend mechanics of such commands, ensuring that the placeholder is replaced with the appropriate commit message.
310360

311361
#### Committing with the Message
312362

src/commands/config.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,11 @@ export enum CONFIG_KEYS {
2525
OCO_ONE_LINE_COMMIT = 'OCO_ONE_LINE_COMMIT',
2626
OCO_TEST_MOCK_TYPE = 'OCO_TEST_MOCK_TYPE',
2727
OCO_API_URL = 'OCO_API_URL',
28-
OCO_GITPUSH = 'OCO_GITPUSH' // todo: deprecate
28+
OCO_GITPUSH = 'OCO_GITPUSH',
29+
OCO_ENABLE_LOGGING = 'OCO_ENABLE_LOGGING',
30+
OCO_ENABLE_CACHE = 'OCO_ENABLE_CACHE',
31+
OCO_CACHE_DIR = 'OCO_CACHE_DIR',
32+
OCO_LOG_DIR = 'OCO_LOG_DIR'
2933
}
3034

3135
export enum CONFIG_MODES {
@@ -383,6 +387,10 @@ export type ConfigType = {
383387
[CONFIG_KEYS.OCO_GITPUSH]: boolean;
384388
[CONFIG_KEYS.OCO_ONE_LINE_COMMIT]: boolean;
385389
[CONFIG_KEYS.OCO_TEST_MOCK_TYPE]: string;
390+
[CONFIG_KEYS.OCO_ENABLE_LOGGING]?: boolean;
391+
[CONFIG_KEYS.OCO_ENABLE_CACHE]?: boolean;
392+
[CONFIG_KEYS.OCO_CACHE_DIR]?: string;
393+
[CONFIG_KEYS.OCO_LOG_DIR]?: string;
386394
};
387395

388396
export const defaultConfigPath = pathJoin(homedir(), '.opencommit');
@@ -429,7 +437,11 @@ export const DEFAULT_CONFIG = {
429437
OCO_ONE_LINE_COMMIT: false,
430438
OCO_TEST_MOCK_TYPE: 'commit-message',
431439
OCO_WHY: false,
432-
OCO_GITPUSH: true // todo: deprecate
440+
OCO_GITPUSH: true,
441+
OCO_ENABLE_LOGGING: true,
442+
OCO_ENABLE_CACHE: true,
443+
OCO_CACHE_DIR: '',
444+
OCO_LOG_DIR: ''
433445
};
434446

435447
const initGlobalConfig = (configPath: string = defaultConfigPath) => {
@@ -468,7 +480,11 @@ const getEnvConfig = (envPath: string) => {
468480
OCO_ONE_LINE_COMMIT: parseConfigVarValue(process.env.OCO_ONE_LINE_COMMIT),
469481
OCO_TEST_MOCK_TYPE: process.env.OCO_TEST_MOCK_TYPE,
470482

471-
OCO_GITPUSH: parseConfigVarValue(process.env.OCO_GITPUSH) // todo: deprecate
483+
OCO_GITPUSH: parseConfigVarValue(process.env.OCO_GITPUSH),
484+
OCO_ENABLE_LOGGING: parseConfigVarValue(process.env.OCO_ENABLE_LOGGING),
485+
OCO_ENABLE_CACHE: parseConfigVarValue(process.env.OCO_ENABLE_CACHE),
486+
OCO_CACHE_DIR: parseConfigVarValue(process.env.OCO_CACHE_DIR),
487+
OCO_LOG_DIR: parseConfigVarValue(process.env.OCO_LOG_DIR)
472488
};
473489
};
474490

src/utils/commitCache.ts

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { join } from 'path';
33
import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync } from 'fs';
44
import { execa } from 'execa';
55
import { createHash } from 'crypto';
6+
import { getConfig } from '../commands/config';
67

78
export interface CommitCacheData {
89
message: string;
@@ -12,8 +13,18 @@ export interface CommitCacheData {
1213
}
1314

1415
export class CommitCache {
15-
private static readonly XDG_CACHE_HOME = process.env.XDG_CACHE_HOME || join(homedir(), '.cache');
16-
private static readonly CACHE_DIR = join(CommitCache.XDG_CACHE_HOME, 'opencommit');
16+
private static readonly DEFAULT_CACHE_HOME = process.env.XDG_CACHE_HOME || join(homedir(), '.cache');
17+
private static readonly DEFAULT_CACHE_DIR = join(CommitCache.DEFAULT_CACHE_HOME, 'opencommit');
18+
19+
private static getCacheDir(): string {
20+
const config = getConfig();
21+
return config.OCO_CACHE_DIR || CommitCache.DEFAULT_CACHE_DIR;
22+
}
23+
24+
private static isCacheEnabled(): boolean {
25+
const config = getConfig();
26+
return config.OCO_ENABLE_CACHE !== false;
27+
}
1728

1829
private static async getRepoRoot(): Promise<string> {
1930
try {
@@ -26,12 +37,15 @@ export class CommitCache {
2637

2738
private static getCacheFilePath(repoPath: string): string {
2839
const repoHash = createHash('md5').update(repoPath).digest('hex');
29-
return join(this.CACHE_DIR, `${repoHash}_commit_cache.json`);
40+
return join(this.getCacheDir(), `${repoHash}_commit_cache.json`);
3041
}
3142

3243
private static ensureCacheDir() {
33-
if (!existsSync(this.CACHE_DIR)) {
34-
mkdirSync(this.CACHE_DIR, { recursive: true });
44+
if (!this.isCacheEnabled()) return;
45+
46+
const cacheDir = this.getCacheDir();
47+
if (!existsSync(cacheDir)) {
48+
mkdirSync(cacheDir, { recursive: true });
3549
}
3650
}
3751

@@ -46,6 +60,8 @@ export class CommitCache {
4660
}
4761

4862
static async saveCommitMessage(message: string) {
63+
if (!this.isCacheEnabled()) return;
64+
4965
this.ensureCacheDir();
5066
const repoPath = await this.getRepoRoot();
5167
const files = await this.getStagedFiles();
@@ -60,6 +76,8 @@ export class CommitCache {
6076
}
6177

6278
static async getLastCommitMessage(): Promise<CommitCacheData | null> {
79+
if (!this.isCacheEnabled()) return null;
80+
6381
try {
6482
const repoPath = await this.getRepoRoot();
6583
const cacheFilePath = this.getCacheFilePath(repoPath);
@@ -75,19 +93,14 @@ export class CommitCache {
7593

7694
const cacheData = JSON.parse(cacheContent) as CommitCacheData;
7795

78-
// Verify if the cache is for the current repository
7996
if (cacheData.repoPath !== repoPath) {
8097
return null;
8198
}
8299

83-
// Get current staged files
84100
const currentFiles = await this.getStagedFiles();
85-
86-
// Compare file lists (order doesn't matter)
87101
const cachedFileSet = new Set(cacheData.files);
88102
const currentFileSet = new Set(currentFiles);
89103

90-
// Check if the file sets are equal
91104
if (cachedFileSet.size !== currentFileSet.size) {
92105
return null;
93106
}
@@ -106,6 +119,8 @@ export class CommitCache {
106119
}
107120

108121
static async clearCache() {
122+
if (!this.isCacheEnabled()) return;
123+
109124
try {
110125
const repoPath = await this.getRepoRoot();
111126
const cacheFilePath = this.getCacheFilePath(repoPath);
@@ -118,19 +133,22 @@ export class CommitCache {
118133
}
119134

120135
static async cleanupOldCaches() {
136+
if (!this.isCacheEnabled()) return;
137+
121138
try {
122-
if (!existsSync(this.CACHE_DIR)) {
139+
const cacheDir = this.getCacheDir();
140+
if (!existsSync(cacheDir)) {
123141
return;
124142
}
125143

126-
const files = readdirSync(this.CACHE_DIR);
144+
const files = readdirSync(cacheDir);
127145
const now = Date.now();
128146
const maxAge = 7 * 24 * 60 * 60 * 1000; // 7 days
129147

130148
for (const file of files) {
131149
if (!file.endsWith('_commit_cache.json')) continue;
132150

133-
const filePath = join(this.CACHE_DIR, file);
151+
const filePath = join(cacheDir, file);
134152
try {
135153
const content = readFileSync(filePath, 'utf-8');
136154
if (!content.trim()) continue;

src/utils/logger.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,32 @@ import { join } from 'path';
33
import { existsSync, mkdirSync, appendFileSync } from 'fs';
44
import { format } from 'util';
55
import chalk from 'chalk';
6+
import { getConfig } from '../commands/config';
67

78
export class Logger {
8-
private static readonly LOG_DIR = join(homedir(), '.cache', 'opencommit', 'logs');
9-
private static readonly LOG_FILE = join(Logger.LOG_DIR, 'opencommit.log');
9+
private static readonly DEFAULT_LOG_DIR = join(homedir(), '.cache', 'opencommit', 'logs');
10+
private static readonly DEFAULT_LOG_FILE = join(Logger.DEFAULT_LOG_DIR, 'opencommit.log');
11+
12+
private static getLogDir(): string {
13+
const config = getConfig();
14+
return config.OCO_LOG_DIR || Logger.DEFAULT_LOG_DIR;
15+
}
16+
17+
private static getLogFile(): string {
18+
return join(this.getLogDir(), 'opencommit.log');
19+
}
20+
21+
private static isLoggingEnabled(): boolean {
22+
const config = getConfig();
23+
return config.OCO_ENABLE_LOGGING !== false;
24+
}
1025

1126
private static ensureLogDir() {
12-
if (!existsSync(Logger.LOG_DIR)) {
13-
mkdirSync(Logger.LOG_DIR, { recursive: true });
27+
if (!this.isLoggingEnabled()) return;
28+
29+
const logDir = this.getLogDir();
30+
if (!existsSync(logDir)) {
31+
mkdirSync(logDir, { recursive: true });
1432
}
1533
}
1634

@@ -24,11 +42,13 @@ export class Logger {
2442
}
2543

2644
private static writeToLog(level: string, message: string) {
45+
if (!this.isLoggingEnabled()) return;
46+
2747
this.ensureLogDir();
2848
const timestamp = this.getTimestamp();
2949
const cleanMessage = this.stripAnsi(message);
3050
const logEntry = `[${timestamp}] [${level}] ${cleanMessage}\n`;
31-
appendFileSync(this.LOG_FILE, logEntry);
51+
appendFileSync(this.getLogFile(), logEntry);
3252
}
3353

3454
private static formatMultilineMessage(message: string): string {
@@ -94,6 +114,6 @@ export class Logger {
94114
}
95115

96116
static getLogPath(): string {
97-
return this.LOG_FILE;
117+
return this.isLoggingEnabled() ? this.getLogFile() : 'Logging is disabled';
98118
}
99119
}

0 commit comments

Comments
 (0)