git-blame-ignore 1.0.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/.eslintrc.js +18 -0
- package/.eslintrc.json +25 -0
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +170 -0
- package/dist/cli.js.map +1 -0
- package/dist/file-manager.d.ts +16 -0
- package/dist/file-manager.d.ts.map +1 -0
- package/dist/file-manager.js +135 -0
- package/dist/file-manager.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +222 -0
- package/dist/index.js.map +1 -0
- package/dist/scanner.d.ts +19 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +137 -0
- package/dist/scanner.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +220 -0
- package/dist/src/index.js.map +1 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/jest.config.js +16 -0
- package/package.json +50 -0
- package/src/cli.ts +198 -0
- package/src/file-manager.ts +150 -0
- package/src/index.ts +241 -0
- package/src/scanner.ts +159 -0
- package/src/types.ts +23 -0
- package/test/scanner.test.ts +57 -0
- package/tests/index.test.ts +67 -0
- package/tsconfig.json +25 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
parser: '@typescript-eslint/parser',
|
|
3
|
+
plugins: ['@typescript-eslint'],
|
|
4
|
+
extends: [
|
|
5
|
+
'eslint:recommended',
|
|
6
|
+
],
|
|
7
|
+
env: {
|
|
8
|
+
node: true,
|
|
9
|
+
es2020: true,
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
'@typescript-eslint/no-unused-vars': 'error',
|
|
13
|
+
'no-unused-vars': 'off',
|
|
14
|
+
'@typescript-eslint/no-explicit-any': 'warn',
|
|
15
|
+
'prefer-const': 'error',
|
|
16
|
+
'no-var': 'error',
|
|
17
|
+
},
|
|
18
|
+
};
|
package/.eslintrc.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"parser": "@typescript-eslint/parser",
|
|
3
|
+
"extends": [
|
|
4
|
+
"eslint:recommended",
|
|
5
|
+
"@typescript-eslint/recommended"
|
|
6
|
+
],
|
|
7
|
+
"plugins": ["@typescript-eslint"],
|
|
8
|
+
"parserOptions": {
|
|
9
|
+
"ecmaVersion": 2020,
|
|
10
|
+
"sourceType": "module"
|
|
11
|
+
},
|
|
12
|
+
"env": {
|
|
13
|
+
"node": true,
|
|
14
|
+
"es2020": true,
|
|
15
|
+
"jest": true
|
|
16
|
+
},
|
|
17
|
+
"rules": {
|
|
18
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
19
|
+
"@typescript-eslint/no-explicit-any": "warn",
|
|
20
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
21
|
+
"@typescript-eslint/no-non-null-assertion": "warn",
|
|
22
|
+
"no-console": "warn",
|
|
23
|
+
"prefer-const": "error"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sulthonzh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# git-blame-ignore
|
|
2
|
+
|
|
3
|
+
CLI that auto-detects bulk-change commits (prettier, lint autofix, mass renames) and manages your `.git-blame-ignore-revs` file — so `git blame` stays useful.
|
|
4
|
+
|
|
5
|
+
## 🎯 Problem
|
|
6
|
+
|
|
7
|
+
After running prettier, eslint --fix, or mass renames, `git blame` becomes useless for affected files — every line shows the formatting commit instead of who actually wrote the code. Git has `.git-blame-ignore-revs` natively, but:
|
|
8
|
+
|
|
9
|
+
- **Manual SHA hunting** — you have to find the commit SHA yourself
|
|
10
|
+
- **No auto-detection** — nobody wants to scan git log for bulk commits
|
|
11
|
+
- **File management is tedious** — add/remove/list entries manually
|
|
12
|
+
|
|
13
|
+
## ✨ Features
|
|
14
|
+
|
|
15
|
+
- **Auto-detection** - Scans git history for bulk-change commits using smart heuristics
|
|
16
|
+
- **Interactive management** - Easy `init` wizard to scan and select commits
|
|
17
|
+
- **Command-line interface** - Simple commands for all operations
|
|
18
|
+
- **GitHub compatible** - Works with GitHub's native `.git-blame-ignore-revs` support
|
|
19
|
+
- **Validation** - Checks that all SHAs are valid commits
|
|
20
|
+
|
|
21
|
+
## 🚀 Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install -g git-blame-ignore
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 📖 Usage
|
|
28
|
+
|
|
29
|
+
### Interactive Setup
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git-blame-ignore init
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Scans for bulk-change commits and lets you select which ones to ignore interactively.
|
|
36
|
+
|
|
37
|
+
### Commands
|
|
38
|
+
|
|
39
|
+
#### Scan for bulk commits (dry run)
|
|
40
|
+
```bash
|
|
41
|
+
git-blame-ignore scan
|
|
42
|
+
# Output:
|
|
43
|
+
# 🔍 Found 3 bulk-change commits:
|
|
44
|
+
# 1. a1b2c3d [85/100] Run prettier on all files
|
|
45
|
+
# 📁 47 files changed, 📝 2,841 lines changed
|
|
46
|
+
# 📅 2026-05-20 | Whitespace: 92%
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Add a specific commit
|
|
50
|
+
```bash
|
|
51
|
+
git-blame-ignore add a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### List current entries
|
|
55
|
+
```bash
|
|
56
|
+
git-blame-ignore list
|
|
57
|
+
# Output:
|
|
58
|
+
# 📋 .git-blame-ignore-revs (3 entries):
|
|
59
|
+
# 1. a1b2c3d - Run prettier on all files
|
|
60
|
+
# 📅 2026-05-20
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Remove an entry
|
|
64
|
+
```bash
|
|
65
|
+
git-blame-ignore remove a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
#### Validate entries
|
|
69
|
+
```bash
|
|
70
|
+
git-blame-ignore check
|
|
71
|
+
# Output:
|
|
72
|
+
# ✅ Valid entries: 3
|
|
73
|
+
# ❌ Invalid entries: 0
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 🔧 How It Works
|
|
77
|
+
|
|
78
|
+
### Detection Algorithm
|
|
79
|
+
|
|
80
|
+
The tool uses a scoring system to identify bulk-change commits:
|
|
81
|
+
|
|
82
|
+
- **Files changed**: 20+ files = +30 points, 50+ files = +50 points
|
|
83
|
+
- **Message matching**: "prettier", "format", "lint", "rename" = +20 points each
|
|
84
|
+
- **Whitespace ratio**: >80% whitespace changes = +20 points
|
|
85
|
+
- **Lines per file**: <5 lines per file = +10 points (indicates formatting)
|
|
86
|
+
|
|
87
|
+
Commits with a score ≥ 40 are suggested for ignoring.
|
|
88
|
+
|
|
89
|
+
### File Format
|
|
90
|
+
|
|
91
|
+
Creates and manages `.git-blame-ignore-revs` in the standard format:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
# a1b2c3d4 Run prettier on all files (auto-detected by git-blame-ignore)
|
|
95
|
+
a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u
|
|
96
|
+
|
|
97
|
+
# e4f5g6h7 eslint --fix (auto-detected by git-blame-ignore)
|
|
98
|
+
e4f5g6h7i8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 🏗️ Development
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Clone and install
|
|
105
|
+
git clone https://github.com/sulthonzh/git-blame-ignore.git
|
|
106
|
+
cd git-blame-ignore
|
|
107
|
+
npm install
|
|
108
|
+
|
|
109
|
+
# Run in development mode
|
|
110
|
+
npm run dev
|
|
111
|
+
|
|
112
|
+
# Build for production
|
|
113
|
+
npm run build
|
|
114
|
+
|
|
115
|
+
# Run tests
|
|
116
|
+
npm test
|
|
117
|
+
|
|
118
|
+
# Lint code
|
|
119
|
+
npm run lint
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 📄 License
|
|
123
|
+
|
|
124
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
125
|
+
|
|
126
|
+
## 🔗 Related
|
|
127
|
+
|
|
128
|
+
- [Git blame documentation](https://git-scm.com/docs/git-blame)
|
|
129
|
+
- [GitHub blame ignore documentation](https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignoring-commits-in-git-blame)
|
|
130
|
+
- [git-blame-ignore-revs file format](https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt)
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class GitBlameIgnoreCLI {
|
|
2
|
+
private scanner;
|
|
3
|
+
private fileManager;
|
|
4
|
+
constructor();
|
|
5
|
+
init(): Promise<void>;
|
|
6
|
+
scan(limit?: number): Promise<void>;
|
|
7
|
+
add(sha: string): Promise<void>;
|
|
8
|
+
list(): Promise<void>;
|
|
9
|
+
remove(sha: string): Promise<void>;
|
|
10
|
+
check(): Promise<void>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAMA,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,WAAW,CAA4B;;IAOzC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAyDrB,IAAI,CAAC,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAkCvC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW/B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BrB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAwC7B"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GitBlameIgnoreCLI = void 0;
|
|
7
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
8
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
9
|
+
const scanner_1 = require("./scanner");
|
|
10
|
+
const file_manager_1 = require("./file-manager");
|
|
11
|
+
class GitBlameIgnoreCLI {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.scanner = new scanner_1.BulkCommitScanner();
|
|
14
|
+
this.fileManager = new file_manager_1.GitBlameIgnoreFileManager();
|
|
15
|
+
}
|
|
16
|
+
async init() {
|
|
17
|
+
console.log(chalk_1.default.blue('🔍 git-blame-ignore init - Interactive Setup Wizard'));
|
|
18
|
+
console.log(chalk_1.default.gray('Scanning for bulk-change commits...\n'));
|
|
19
|
+
try {
|
|
20
|
+
const commits = await this.scanner.scan();
|
|
21
|
+
if (commits.length === 0) {
|
|
22
|
+
console.log(chalk_1.default.yellow('🤔 No bulk-change commits found that meet the criteria.'));
|
|
23
|
+
console.log(chalk_1.default.gray('Try running formatting tools like prettier or eslint --fix first.'));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
console.log(chalk_1.default.green(`✅ Found ${commits.length} bulk-change commits:\n`));
|
|
27
|
+
// Display commits
|
|
28
|
+
commits.forEach((commit, index) => {
|
|
29
|
+
const scoreColor = commit.bulkScore >= 70 ? chalk_1.default.green : commit.bulkScore >= 50 ? chalk_1.default.yellow : chalk_1.default.red;
|
|
30
|
+
console.log(`${index + 1}. ${commit.sha.substring(0, 7)} ${scoreColor(`[${commit.bulkScore}/100]`)} ${commit.message}`);
|
|
31
|
+
console.log(` 📁 ${commit.filesChanged} files changed, 📝 ${commit.linesChanged} lines changed`);
|
|
32
|
+
console.log(` 📅 ${commit.date}\n`);
|
|
33
|
+
});
|
|
34
|
+
// Ask user to select commits
|
|
35
|
+
const answers = await inquirer_1.default.prompt([
|
|
36
|
+
{
|
|
37
|
+
type: 'checkbox',
|
|
38
|
+
name: 'commits',
|
|
39
|
+
message: 'Which commits would you like to add to .git-blame-ignore-revs?',
|
|
40
|
+
choices: commits.map((commit) => ({
|
|
41
|
+
name: `${commit.sha.substring(0, 7)} - ${commit.message} (${commit.filesChanged} files)`,
|
|
42
|
+
value: commit.sha,
|
|
43
|
+
short: commit.sha.substring(0, 7)
|
|
44
|
+
})),
|
|
45
|
+
pageSize: 10
|
|
46
|
+
}
|
|
47
|
+
]);
|
|
48
|
+
if (answers.commits.length === 0) {
|
|
49
|
+
console.log(chalk_1.default.yellow('❌ No commits selected. Exiting.'));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Add selected commits
|
|
53
|
+
for (const sha of answers.commits) {
|
|
54
|
+
await this.fileManager.add(sha);
|
|
55
|
+
}
|
|
56
|
+
console.log(chalk_1.default.green(`✅ Successfully added ${answers.commits.length} commits to .git-blame-ignore-revs`));
|
|
57
|
+
console.log(chalk_1.default.blue('💡 Now run `git blame` on affected files to see the improved output!'));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error(chalk_1.default.red('❌ Error during initialization:'), error);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async scan(limit = 20) {
|
|
65
|
+
console.log(chalk_1.default.blue('🔍 git-blame-ignore scan - Finding bulk-change commits'));
|
|
66
|
+
console.log(chalk_1.default.gray(`Analyzing last 100 commits...\n`));
|
|
67
|
+
try {
|
|
68
|
+
const commits = await this.scanner.scan();
|
|
69
|
+
if (commits.length === 0) {
|
|
70
|
+
console.log(chalk_1.default.yellow('🤔 No bulk-change commits found that meet the criteria.'));
|
|
71
|
+
console.log(chalk_1.default.gray('Try running formatting tools like prettier or eslint --fix first.'));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const displayCommits = commits.slice(0, limit);
|
|
75
|
+
console.log(chalk_1.default.green(`📋 Found ${commits.length} bulk-change commits (showing first ${Math.min(limit, commits.length)}):\n`));
|
|
76
|
+
displayCommits.forEach((commit, index) => {
|
|
77
|
+
const scoreColor = commit.bulkScore >= 70 ? chalk_1.default.green : commit.bulkScore >= 50 ? chalk_1.default.yellow : chalk_1.default.red;
|
|
78
|
+
console.log(`${index + 1}. ${commit.sha.substring(0, 7)} ${scoreColor(`[${commit.bulkScore}/100]`)} ${commit.message}`);
|
|
79
|
+
console.log(` 📁 ${commit.filesChanged} files changed, 📝 ${commit.linesChanged} lines changed`);
|
|
80
|
+
console.log(` 📅 ${commit.date} | Whitespace: ${Math.round(commit.whitespaceRatio * 100)}%\n`);
|
|
81
|
+
});
|
|
82
|
+
if (commits.length > limit) {
|
|
83
|
+
console.log(chalk_1.default.gray(`... and ${commits.length - limit} more commits`));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.error(chalk_1.default.red('❌ Error during scan:'), error);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
async add(sha) {
|
|
92
|
+
console.log(chalk_1.default.blue(`📝 git-blame-ignore add ${sha}`));
|
|
93
|
+
try {
|
|
94
|
+
await this.fileManager.add(sha);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error(chalk_1.default.red('❌ Error adding commit:'), error);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async list() {
|
|
102
|
+
console.log(chalk_1.default.blue('📋 git-blame-ignore list - Current .git-blame-ignore-revs entries'));
|
|
103
|
+
try {
|
|
104
|
+
const entries = await this.fileManager.read();
|
|
105
|
+
if (entries.length === 0) {
|
|
106
|
+
console.log(chalk_1.default.yellow('🤔 No entries found in .git-blame-ignore-revs'));
|
|
107
|
+
console.log(chalk_1.default.gray('Run `git-blame-ignore init` to add some commits.'));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
console.log(chalk_1.default.green(`📋 .git-blame-ignore-revs (${entries.length} entries):\n`));
|
|
111
|
+
entries.forEach((entry, index) => {
|
|
112
|
+
console.log(`${index + 1}. ${entry.sha.substring(0, 7)} - ${entry.message}`);
|
|
113
|
+
console.log(` 📅 ${entry.date}`);
|
|
114
|
+
if (entry.comment) {
|
|
115
|
+
console.log(` 💬 ${entry.comment}`);
|
|
116
|
+
}
|
|
117
|
+
console.log('');
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error(chalk_1.default.red('❌ Error listing entries:'), error);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
async remove(sha) {
|
|
126
|
+
console.log(chalk_1.default.blue(`🗑️ git-blame-ignore remove ${sha}`));
|
|
127
|
+
try {
|
|
128
|
+
await this.fileManager.remove(sha);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.error(chalk_1.default.red('❌ Error removing commit:'), error);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async check() {
|
|
136
|
+
console.log(chalk_1.default.blue('✅ git-blame-ignore check - Validating entries'));
|
|
137
|
+
try {
|
|
138
|
+
const entries = await this.fileManager.read();
|
|
139
|
+
if (entries.length === 0) {
|
|
140
|
+
console.log(chalk_1.default.yellow('🤔 No entries to check.'));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const { valid, invalid } = await this.fileManager.validate(entries);
|
|
144
|
+
console.log(chalk_1.default.green(`✅ Valid entries: ${valid.length}`));
|
|
145
|
+
console.log(chalk_1.default.red(`❌ Invalid entries: ${invalid.length}\n`));
|
|
146
|
+
if (invalid.length > 0) {
|
|
147
|
+
console.log(chalk_1.default.red('Invalid entries (SHAs not found in repository):'));
|
|
148
|
+
invalid.forEach(entry => {
|
|
149
|
+
console.log(` - ${entry.sha.substring(0, 7)} - ${entry.message}`);
|
|
150
|
+
});
|
|
151
|
+
console.log('');
|
|
152
|
+
}
|
|
153
|
+
if (valid.length > 0) {
|
|
154
|
+
console.log(chalk_1.default.green('Valid entries:'));
|
|
155
|
+
valid.forEach(entry => {
|
|
156
|
+
console.log(` ✅ ${entry.sha.substring(0, 7)} - ${entry.message}`);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
if (invalid.length > 0) {
|
|
160
|
+
console.log(chalk_1.default.yellow('\n💡 Tip: Remove invalid entries with `git-blame-ignore remove <sha>`'));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
console.error(chalk_1.default.red('❌ Error during validation:'), error);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.GitBlameIgnoreCLI = GitBlameIgnoreCLI;
|
|
170
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { IgnoreEntry } from './types';
|
|
2
|
+
export declare class GitBlameIgnoreFileManager {
|
|
3
|
+
private ignoreFilePath;
|
|
4
|
+
constructor(ignoreFilePath?: string);
|
|
5
|
+
exists(): Promise<boolean>;
|
|
6
|
+
read(): Promise<IgnoreEntry[]>;
|
|
7
|
+
add(sha: string, comment?: string): Promise<void>;
|
|
8
|
+
remove(sha: string): Promise<void>;
|
|
9
|
+
write(entries: IgnoreEntry[]): Promise<void>;
|
|
10
|
+
validate(entries: IgnoreEntry[]): Promise<{
|
|
11
|
+
valid: IgnoreEntry[];
|
|
12
|
+
invalid: IgnoreEntry[];
|
|
13
|
+
}>;
|
|
14
|
+
private createIgnoreEntry;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=file-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-manager.d.ts","sourceRoot":"","sources":["../src/file-manager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAEtC,qBAAa,yBAAyB;IACpC,OAAO,CAAC,cAAc,CAAS;gBAEnB,cAAc,CAAC,EAAE,MAAM;IAI7B,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAS1B,IAAI,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IA2B9B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBjD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAalC,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB5C,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,EAAE,CAAC;QAAC,OAAO,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;YA6BnF,iBAAiB;CAiBhC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.GitBlameIgnoreFileManager = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
class GitBlameIgnoreFileManager {
|
|
10
|
+
constructor(ignoreFilePath) {
|
|
11
|
+
this.ignoreFilePath = ignoreFilePath || '.git-blame-ignore-revs';
|
|
12
|
+
}
|
|
13
|
+
async exists() {
|
|
14
|
+
try {
|
|
15
|
+
await promises_1.default.access(this.ignoreFilePath);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async read() {
|
|
23
|
+
if (!(await this.exists())) {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const content = await promises_1.default.readFile(this.ignoreFilePath, 'utf-8');
|
|
28
|
+
const entries = [];
|
|
29
|
+
const lines = content.split('\n').filter(line => line.trim() && !line.trim().startsWith('#'));
|
|
30
|
+
for (const line of lines) {
|
|
31
|
+
const sha = line.trim();
|
|
32
|
+
if (sha && /^[a-f0-9]{40}$/i.test(sha)) {
|
|
33
|
+
const entry = await this.createIgnoreEntry(sha);
|
|
34
|
+
if (entry) {
|
|
35
|
+
entries.push(entry);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return entries;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new Error(`Failed to read ${this.ignoreFilePath}: ${error}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async add(sha, comment) {
|
|
46
|
+
const entry = await this.createIgnoreEntry(sha);
|
|
47
|
+
if (!entry) {
|
|
48
|
+
throw new Error(`Invalid commit SHA: ${sha}`);
|
|
49
|
+
}
|
|
50
|
+
const entries = await this.read();
|
|
51
|
+
// Check if already exists
|
|
52
|
+
if (entries.some(e => e.sha === sha)) {
|
|
53
|
+
console.log(`Entry ${sha.substring(0, 7)} already exists in ${this.ignoreFilePath}`);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
entries.push({
|
|
57
|
+
...entry,
|
|
58
|
+
comment: comment || `Auto-added by git-blame-ignore`
|
|
59
|
+
});
|
|
60
|
+
await this.write(entries);
|
|
61
|
+
console.log(`Added ${sha.substring(0, 7)} to ${this.ignoreFilePath}`);
|
|
62
|
+
}
|
|
63
|
+
async remove(sha) {
|
|
64
|
+
const entries = await this.read();
|
|
65
|
+
const filtered = entries.filter(e => e.sha !== sha);
|
|
66
|
+
if (filtered.length === entries.length) {
|
|
67
|
+
console.log(`Entry ${sha.substring(0, 7)} not found in ${this.ignoreFilePath}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
await this.write(filtered);
|
|
71
|
+
console.log(`Removed ${sha.substring(0, 7)} from ${this.ignoreFilePath}`);
|
|
72
|
+
}
|
|
73
|
+
async write(entries) {
|
|
74
|
+
try {
|
|
75
|
+
// Create directory if it doesn't exist
|
|
76
|
+
const dir = path_1.default.dirname(this.ignoreFilePath);
|
|
77
|
+
await promises_1.default.mkdir(dir, { recursive: true });
|
|
78
|
+
let content = '# .git-blame-ignore-revs - managed by git-blame-ignore\n';
|
|
79
|
+
content += '# Format: SHA of commits to ignore for git blame\n\n';
|
|
80
|
+
for (const entry of entries) {
|
|
81
|
+
content += `# ${entry.sha.substring(0, 7)} - ${entry.message} (${entry.date})\n`;
|
|
82
|
+
content += `${entry.sha}\n\n`;
|
|
83
|
+
}
|
|
84
|
+
await promises_1.default.writeFile(this.ignoreFilePath, content);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
throw new Error(`Failed to write ${this.ignoreFilePath}: ${error}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async validate(entries) {
|
|
91
|
+
const valid = [];
|
|
92
|
+
const invalid = [];
|
|
93
|
+
for (const entry of entries) {
|
|
94
|
+
try {
|
|
95
|
+
// Check if SHA is a valid 40-character hex string
|
|
96
|
+
if (!/^[a-f0-9]{40}$/i.test(entry.sha)) {
|
|
97
|
+
invalid.push(entry);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
// Try to get commit info to verify it exists
|
|
101
|
+
const git = require('simple-git')();
|
|
102
|
+
const result = await git.show([entry.sha, '--format=%H', '--no-patch']);
|
|
103
|
+
if (result.trim() === entry.sha) {
|
|
104
|
+
valid.push(entry);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
invalid.push(entry);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
invalid.push(entry);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return { valid, invalid };
|
|
115
|
+
}
|
|
116
|
+
async createIgnoreEntry(sha) {
|
|
117
|
+
try {
|
|
118
|
+
const git = require('simple-git')();
|
|
119
|
+
const [message, date] = await Promise.all([
|
|
120
|
+
git.show([sha, '--format=%s', '--no-patch']),
|
|
121
|
+
git.show([sha, '--format=%ai', '--no-patch'])
|
|
122
|
+
]);
|
|
123
|
+
return {
|
|
124
|
+
sha,
|
|
125
|
+
message: message.trim(),
|
|
126
|
+
date: date.trim(),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.GitBlameIgnoreFileManager = GitBlameIgnoreFileManager;
|
|
135
|
+
//# sourceMappingURL=file-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-manager.js","sourceRoot":"","sources":["../src/file-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|