@vibe-validate/git 0.9.0 → 0.9.3
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/package.json +1 -1
- package/dist/branch-sync.d.ts +0 -68
- package/dist/branch-sync.d.ts.map +0 -1
- package/dist/branch-sync.js +0 -139
- package/dist/branch-sync.js.map +0 -1
- package/dist/index.d.ts +0 -12
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -15
- package/dist/index.js.map +0 -1
- package/dist/post-merge-cleanup.d.ts +0 -77
- package/dist/post-merge-cleanup.d.ts.map +0 -1
- package/dist/post-merge-cleanup.js +0 -221
- package/dist/post-merge-cleanup.js.map +0 -1
- package/dist/tree-hash.d.ts +0 -44
- package/dist/tree-hash.d.ts.map +0 -1
- package/dist/tree-hash.js +0 -110
- package/dist/tree-hash.js.map +0 -1
package/package.json
CHANGED
package/dist/branch-sync.d.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Smart Branch Sync Checker
|
|
3
|
-
*
|
|
4
|
-
* Safely checks if the current branch is behind a remote branch without auto-merging.
|
|
5
|
-
* Provides clear status reporting and next-step instructions.
|
|
6
|
-
*
|
|
7
|
-
* Key safety features:
|
|
8
|
-
* - Never auto-merges (preserves conflict visibility)
|
|
9
|
-
* - Clear exit codes for CI/agent integration
|
|
10
|
-
* - Explicit instructions when manual intervention needed
|
|
11
|
-
* - Cross-platform compatibility
|
|
12
|
-
*/
|
|
13
|
-
declare const GIT_OPTIONS: {
|
|
14
|
-
timeout: number;
|
|
15
|
-
encoding: "utf8";
|
|
16
|
-
maxBuffer: number;
|
|
17
|
-
};
|
|
18
|
-
export interface SyncCheckResult {
|
|
19
|
-
isUpToDate: boolean;
|
|
20
|
-
behindBy: number;
|
|
21
|
-
currentBranch: string;
|
|
22
|
-
hasRemote: boolean;
|
|
23
|
-
error?: string;
|
|
24
|
-
}
|
|
25
|
-
export type ExecAsyncFunction = (command: string, options: typeof GIT_OPTIONS) => Promise<{
|
|
26
|
-
stdout: string;
|
|
27
|
-
stderr: string;
|
|
28
|
-
}>;
|
|
29
|
-
export interface SyncCheckOptions {
|
|
30
|
-
remoteBranch?: string;
|
|
31
|
-
execAsync?: ExecAsyncFunction;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Branch Sync Checker
|
|
35
|
-
*
|
|
36
|
-
* Checks if current branch is behind a remote branch
|
|
37
|
-
*/
|
|
38
|
-
export declare class BranchSyncChecker {
|
|
39
|
-
private readonly remoteBranch;
|
|
40
|
-
private readonly execAsync;
|
|
41
|
-
constructor(options?: SyncCheckOptions);
|
|
42
|
-
/**
|
|
43
|
-
* Check if the current branch is synchronized with remote branch
|
|
44
|
-
*
|
|
45
|
-
* @returns Promise resolving to sync status information
|
|
46
|
-
*/
|
|
47
|
-
checkSync(): Promise<SyncCheckResult>;
|
|
48
|
-
private getCurrentBranch;
|
|
49
|
-
private hasRemoteBranch;
|
|
50
|
-
private fetchRemote;
|
|
51
|
-
private getCommitsBehind;
|
|
52
|
-
/**
|
|
53
|
-
* Get appropriate exit code based on sync result
|
|
54
|
-
*
|
|
55
|
-
* @param result - The sync check result
|
|
56
|
-
* @returns Exit code (0=success, 1=needs merge, 2=error)
|
|
57
|
-
*/
|
|
58
|
-
getExitCode(result: SyncCheckResult): number;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Convenience function for quick sync checking
|
|
62
|
-
*
|
|
63
|
-
* @param options - Sync check options
|
|
64
|
-
* @returns Sync check result
|
|
65
|
-
*/
|
|
66
|
-
export declare function checkBranchSync(options?: SyncCheckOptions): Promise<SyncCheckResult>;
|
|
67
|
-
export {};
|
|
68
|
-
//# sourceMappingURL=branch-sync.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"branch-sync.d.ts","sourceRoot":"","sources":["../src/branch-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,QAAA,MAAM,WAAW;;;;CAIhB,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,WAAW,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9H,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,iBAAiB,CAAC;CAC/B;AAED;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;gBAElC,OAAO,GAAE,gBAAqB;IAK1C;;;;OAIG;IACG,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC;YA0C7B,gBAAgB;YAUhB,eAAe;YASf,WAAW;YAUX,gBAAgB;IAW9B;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM;CAK7C;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC,CAG9F"}
|
package/dist/branch-sync.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Smart Branch Sync Checker
|
|
3
|
-
*
|
|
4
|
-
* Safely checks if the current branch is behind a remote branch without auto-merging.
|
|
5
|
-
* Provides clear status reporting and next-step instructions.
|
|
6
|
-
*
|
|
7
|
-
* Key safety features:
|
|
8
|
-
* - Never auto-merges (preserves conflict visibility)
|
|
9
|
-
* - Clear exit codes for CI/agent integration
|
|
10
|
-
* - Explicit instructions when manual intervention needed
|
|
11
|
-
* - Cross-platform compatibility
|
|
12
|
-
*/
|
|
13
|
-
import { exec } from 'child_process';
|
|
14
|
-
import { promisify } from 'util';
|
|
15
|
-
const GIT_TIMEOUT = 10000; // 10 seconds timeout for git operations
|
|
16
|
-
const GIT_OPTIONS = {
|
|
17
|
-
timeout: GIT_TIMEOUT,
|
|
18
|
-
encoding: 'utf8',
|
|
19
|
-
maxBuffer: 1024 * 1024 // 1MB buffer
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Branch Sync Checker
|
|
23
|
-
*
|
|
24
|
-
* Checks if current branch is behind a remote branch
|
|
25
|
-
*/
|
|
26
|
-
export class BranchSyncChecker {
|
|
27
|
-
remoteBranch;
|
|
28
|
-
execAsync;
|
|
29
|
-
constructor(options = {}) {
|
|
30
|
-
this.remoteBranch = options.remoteBranch || 'origin/main';
|
|
31
|
-
this.execAsync = options.execAsync || promisify(exec);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Check if the current branch is synchronized with remote branch
|
|
35
|
-
*
|
|
36
|
-
* @returns Promise resolving to sync status information
|
|
37
|
-
*/
|
|
38
|
-
async checkSync() {
|
|
39
|
-
try {
|
|
40
|
-
// Get current branch name
|
|
41
|
-
const currentBranch = await this.getCurrentBranch();
|
|
42
|
-
// Check if remote branch exists
|
|
43
|
-
const hasRemote = await this.hasRemoteBranch();
|
|
44
|
-
if (!hasRemote) {
|
|
45
|
-
return {
|
|
46
|
-
isUpToDate: true,
|
|
47
|
-
behindBy: 0,
|
|
48
|
-
currentBranch,
|
|
49
|
-
hasRemote: false,
|
|
50
|
-
error: `No remote branch ${this.remoteBranch} found`
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
// Fetch latest from remote
|
|
54
|
-
await this.fetchRemote();
|
|
55
|
-
// Check how many commits behind
|
|
56
|
-
const behindBy = await this.getCommitsBehind();
|
|
57
|
-
return {
|
|
58
|
-
isUpToDate: behindBy === 0,
|
|
59
|
-
behindBy,
|
|
60
|
-
currentBranch,
|
|
61
|
-
hasRemote: true
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
66
|
-
return {
|
|
67
|
-
isUpToDate: false,
|
|
68
|
-
behindBy: -1,
|
|
69
|
-
currentBranch: 'unknown',
|
|
70
|
-
hasRemote: false,
|
|
71
|
-
error: errorMessage
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
async getCurrentBranch() {
|
|
76
|
-
try {
|
|
77
|
-
const { stdout } = await this.execAsync('git rev-parse --abbrev-ref HEAD', GIT_OPTIONS);
|
|
78
|
-
return stdout.trim();
|
|
79
|
-
}
|
|
80
|
-
catch (error) {
|
|
81
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
82
|
-
throw new Error(`Not in a git repository or unable to determine current branch: ${errorMessage}`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
async hasRemoteBranch() {
|
|
86
|
-
try {
|
|
87
|
-
await this.execAsync(`git rev-parse --verify ${this.remoteBranch}`, GIT_OPTIONS);
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
async fetchRemote() {
|
|
95
|
-
try {
|
|
96
|
-
const [remote, branch] = this.remoteBranch.split('/');
|
|
97
|
-
await this.execAsync(`git fetch --quiet ${remote} ${branch}`, GIT_OPTIONS);
|
|
98
|
-
}
|
|
99
|
-
catch (error) {
|
|
100
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
101
|
-
throw new Error(`Failed to fetch from ${this.remoteBranch}: ${errorMessage}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
async getCommitsBehind() {
|
|
105
|
-
try {
|
|
106
|
-
const { stdout } = await this.execAsync(`git rev-list --count HEAD..${this.remoteBranch}`, GIT_OPTIONS);
|
|
107
|
-
const count = parseInt(stdout.trim(), 10);
|
|
108
|
-
return isNaN(count) ? 0 : count;
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
112
|
-
throw new Error(`Failed to check commits behind: ${errorMessage}`);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Get appropriate exit code based on sync result
|
|
117
|
-
*
|
|
118
|
-
* @param result - The sync check result
|
|
119
|
-
* @returns Exit code (0=success, 1=needs merge, 2=error)
|
|
120
|
-
*/
|
|
121
|
-
getExitCode(result) {
|
|
122
|
-
if (result.error)
|
|
123
|
-
return 2; // Error condition
|
|
124
|
-
if (!result.hasRemote)
|
|
125
|
-
return 0; // No remote, consider OK
|
|
126
|
-
return result.isUpToDate ? 0 : 1; // 0 = up to date, 1 = needs merge
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Convenience function for quick sync checking
|
|
131
|
-
*
|
|
132
|
-
* @param options - Sync check options
|
|
133
|
-
* @returns Sync check result
|
|
134
|
-
*/
|
|
135
|
-
export async function checkBranchSync(options = {}) {
|
|
136
|
-
const checker = new BranchSyncChecker(options);
|
|
137
|
-
return checker.checkSync();
|
|
138
|
-
}
|
|
139
|
-
//# sourceMappingURL=branch-sync.js.map
|
package/dist/branch-sync.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"branch-sync.js","sourceRoot":"","sources":["../src/branch-sync.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @vibe-validate/git
|
|
3
|
-
*
|
|
4
|
-
* Git utilities for vibe-validate - deterministic tree hash calculation,
|
|
5
|
-
* branch synchronization, and post-merge cleanup.
|
|
6
|
-
*
|
|
7
|
-
* @packageDocumentation
|
|
8
|
-
*/
|
|
9
|
-
export { getGitTreeHash, getHeadTreeHash, hasWorkingTreeChanges } from './tree-hash.js';
|
|
10
|
-
export { BranchSyncChecker, checkBranchSync, type SyncCheckResult, type SyncCheckOptions } from './branch-sync.js';
|
|
11
|
-
export { PostPRMergeCleanup, cleanupMergedBranches, type CleanupResult, type CleanupOptions } from './post-merge-cleanup.js';
|
|
12
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @vibe-validate/git
|
|
3
|
-
*
|
|
4
|
-
* Git utilities for vibe-validate - deterministic tree hash calculation,
|
|
5
|
-
* branch synchronization, and post-merge cleanup.
|
|
6
|
-
*
|
|
7
|
-
* @packageDocumentation
|
|
8
|
-
*/
|
|
9
|
-
// Tree hash calculation (deterministic, content-based)
|
|
10
|
-
export { getGitTreeHash, getHeadTreeHash, hasWorkingTreeChanges } from './tree-hash.js';
|
|
11
|
-
// Branch sync checking (safe, no auto-merge)
|
|
12
|
-
export { BranchSyncChecker, checkBranchSync } from './branch-sync.js';
|
|
13
|
-
// Post-merge cleanup (delete merged branches)
|
|
14
|
-
export { PostPRMergeCleanup, cleanupMergedBranches } from './post-merge-cleanup.js';
|
|
15
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,uDAAuD;AACvD,OAAO,EACL,cAAc,EACd,eAAe,EACf,qBAAqB,EACtB,MAAM,gBAAgB,CAAC;AAExB,6CAA6C;AAC7C,OAAO,EACL,iBAAiB,EACjB,eAAe,EAGhB,MAAM,kBAAkB,CAAC;AAE1B,8CAA8C;AAC9C,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EAGtB,MAAM,yBAAyB,CAAC"}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Post-PR Merge Cleanup Tool
|
|
3
|
-
*
|
|
4
|
-
* Comprehensive post-PR cleanup workflow that:
|
|
5
|
-
* 1. Switches to main branch
|
|
6
|
-
* 2. Syncs main branch with remote origin
|
|
7
|
-
* 3. Deletes local branches that have been merged
|
|
8
|
-
* 4. Provides clean workspace for next PR
|
|
9
|
-
*
|
|
10
|
-
* Safe operations:
|
|
11
|
-
* - Only deletes branches that are confirmed merged
|
|
12
|
-
* - Never deletes the current main branch or unmerged branches
|
|
13
|
-
* - Provides clear feedback on all actions taken
|
|
14
|
-
*/
|
|
15
|
-
export interface CleanupResult {
|
|
16
|
-
success: boolean;
|
|
17
|
-
error?: string;
|
|
18
|
-
branchesDeleted: string[];
|
|
19
|
-
currentBranch: string;
|
|
20
|
-
mainSynced: boolean;
|
|
21
|
-
}
|
|
22
|
-
export interface CleanupOptions {
|
|
23
|
-
mainBranch?: string;
|
|
24
|
-
remoteName?: string;
|
|
25
|
-
dryRun?: boolean;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Post-PR Merge Cleanup
|
|
29
|
-
*
|
|
30
|
-
* Cleans up merged branches and syncs main branch after PR merge
|
|
31
|
-
*/
|
|
32
|
-
export declare class PostPRMergeCleanup {
|
|
33
|
-
private readonly mainBranch;
|
|
34
|
-
private readonly remoteName;
|
|
35
|
-
private readonly dryRun;
|
|
36
|
-
constructor(options?: CleanupOptions);
|
|
37
|
-
/**
|
|
38
|
-
* Run comprehensive post-PR merge cleanup workflow
|
|
39
|
-
*/
|
|
40
|
-
runCleanup(): Promise<CleanupResult>;
|
|
41
|
-
/**
|
|
42
|
-
* Get the current git branch name
|
|
43
|
-
*/
|
|
44
|
-
private getCurrentBranch;
|
|
45
|
-
/**
|
|
46
|
-
* Switch to main branch
|
|
47
|
-
*/
|
|
48
|
-
private switchToMain;
|
|
49
|
-
/**
|
|
50
|
-
* Sync main branch with remote origin
|
|
51
|
-
*/
|
|
52
|
-
private syncMainBranch;
|
|
53
|
-
/**
|
|
54
|
-
* Fetch remote branch information
|
|
55
|
-
*/
|
|
56
|
-
private fetchRemoteInfo;
|
|
57
|
-
/**
|
|
58
|
-
* Find and delete branches that have been merged
|
|
59
|
-
*/
|
|
60
|
-
private deleteMergedBranches;
|
|
61
|
-
/**
|
|
62
|
-
* Check if a branch has been merged into main
|
|
63
|
-
*/
|
|
64
|
-
private isBranchMerged;
|
|
65
|
-
/**
|
|
66
|
-
* Clean up remote tracking references
|
|
67
|
-
*/
|
|
68
|
-
private pruneRemoteReferences;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Convenience function for quick cleanup
|
|
72
|
-
*
|
|
73
|
-
* @param options - Cleanup options
|
|
74
|
-
* @returns Cleanup result
|
|
75
|
-
*/
|
|
76
|
-
export declare function cleanupMergedBranches(options?: CleanupOptions): Promise<CleanupResult>;
|
|
77
|
-
//# sourceMappingURL=post-merge-cleanup.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"post-merge-cleanup.d.ts","sourceRoot":"","sources":["../src/post-merge-cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAU;gBAErB,OAAO,GAAE,cAAmB;IAMxC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC;IAqC1C;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;OAEG;IACH,OAAO,CAAC,YAAY;IAYpB;;OAEG;IACH,OAAO,CAAC,cAAc;IAqBtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAYvB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAkD5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAetB;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAW9B;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAGhG"}
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Post-PR Merge Cleanup Tool
|
|
3
|
-
*
|
|
4
|
-
* Comprehensive post-PR cleanup workflow that:
|
|
5
|
-
* 1. Switches to main branch
|
|
6
|
-
* 2. Syncs main branch with remote origin
|
|
7
|
-
* 3. Deletes local branches that have been merged
|
|
8
|
-
* 4. Provides clean workspace for next PR
|
|
9
|
-
*
|
|
10
|
-
* Safe operations:
|
|
11
|
-
* - Only deletes branches that are confirmed merged
|
|
12
|
-
* - Never deletes the current main branch or unmerged branches
|
|
13
|
-
* - Provides clear feedback on all actions taken
|
|
14
|
-
*/
|
|
15
|
-
import { execSync } from 'child_process';
|
|
16
|
-
const TIMEOUT = 30000; // 30 seconds timeout for git operations
|
|
17
|
-
/**
|
|
18
|
-
* Post-PR Merge Cleanup
|
|
19
|
-
*
|
|
20
|
-
* Cleans up merged branches and syncs main branch after PR merge
|
|
21
|
-
*/
|
|
22
|
-
export class PostPRMergeCleanup {
|
|
23
|
-
mainBranch;
|
|
24
|
-
remoteName;
|
|
25
|
-
dryRun;
|
|
26
|
-
constructor(options = {}) {
|
|
27
|
-
this.mainBranch = options.mainBranch || 'main';
|
|
28
|
-
this.remoteName = options.remoteName || 'origin';
|
|
29
|
-
this.dryRun = options.dryRun || false;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Run comprehensive post-PR merge cleanup workflow
|
|
33
|
-
*/
|
|
34
|
-
async runCleanup() {
|
|
35
|
-
const result = {
|
|
36
|
-
success: false,
|
|
37
|
-
branchesDeleted: [],
|
|
38
|
-
currentBranch: '',
|
|
39
|
-
mainSynced: false
|
|
40
|
-
};
|
|
41
|
-
try {
|
|
42
|
-
// Step 1: Get current branch
|
|
43
|
-
result.currentBranch = this.getCurrentBranch();
|
|
44
|
-
// Step 2: Switch to main branch
|
|
45
|
-
this.switchToMain();
|
|
46
|
-
// Step 3: Sync main branch with remote
|
|
47
|
-
this.syncMainBranch();
|
|
48
|
-
result.mainSynced = true;
|
|
49
|
-
// Step 4: Fetch remote branch information
|
|
50
|
-
this.fetchRemoteInfo();
|
|
51
|
-
// Step 5: Find and delete merged branches
|
|
52
|
-
result.branchesDeleted = this.deleteMergedBranches();
|
|
53
|
-
// Step 6: Clean up remote tracking branches
|
|
54
|
-
this.pruneRemoteReferences();
|
|
55
|
-
result.success = true;
|
|
56
|
-
return result;
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
result.error = error instanceof Error ? error.message : String(error);
|
|
60
|
-
return result;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Get the current git branch name
|
|
65
|
-
*/
|
|
66
|
-
getCurrentBranch() {
|
|
67
|
-
try {
|
|
68
|
-
return execSync('git branch --show-current', {
|
|
69
|
-
encoding: 'utf8',
|
|
70
|
-
timeout: TIMEOUT
|
|
71
|
-
}).trim();
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
throw new Error(`Failed to get current branch: ${error}`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Switch to main branch
|
|
79
|
-
*/
|
|
80
|
-
switchToMain() {
|
|
81
|
-
try {
|
|
82
|
-
execSync(`git checkout ${this.mainBranch}`, {
|
|
83
|
-
encoding: 'utf8',
|
|
84
|
-
timeout: TIMEOUT,
|
|
85
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
throw new Error(`Failed to switch to ${this.mainBranch} branch: ${error}`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Sync main branch with remote origin
|
|
94
|
-
*/
|
|
95
|
-
syncMainBranch() {
|
|
96
|
-
try {
|
|
97
|
-
// Fetch latest changes from remote
|
|
98
|
-
execSync(`git fetch ${this.remoteName} ${this.mainBranch}`, {
|
|
99
|
-
encoding: 'utf8',
|
|
100
|
-
timeout: TIMEOUT,
|
|
101
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
102
|
-
});
|
|
103
|
-
// Fast-forward merge remote/main
|
|
104
|
-
execSync(`git merge ${this.remoteName}/${this.mainBranch} --ff-only`, {
|
|
105
|
-
encoding: 'utf8',
|
|
106
|
-
timeout: TIMEOUT,
|
|
107
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
throw new Error(`Failed to sync ${this.mainBranch} branch: ${error}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Fetch remote branch information
|
|
116
|
-
*/
|
|
117
|
-
fetchRemoteInfo() {
|
|
118
|
-
try {
|
|
119
|
-
execSync(`git fetch ${this.remoteName} --prune`, {
|
|
120
|
-
encoding: 'utf8',
|
|
121
|
-
timeout: TIMEOUT,
|
|
122
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
123
|
-
});
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
throw new Error(`Failed to fetch remote info: ${error}`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Find and delete branches that have been merged
|
|
131
|
-
*/
|
|
132
|
-
deleteMergedBranches() {
|
|
133
|
-
try {
|
|
134
|
-
// Get list of local branches (excluding main)
|
|
135
|
-
const allBranches = execSync('git branch --format="%(refname:short)"', {
|
|
136
|
-
encoding: 'utf8',
|
|
137
|
-
timeout: TIMEOUT
|
|
138
|
-
})
|
|
139
|
-
.trim()
|
|
140
|
-
.split('\n')
|
|
141
|
-
.filter(branch => branch && branch !== this.mainBranch && !branch.startsWith('*'));
|
|
142
|
-
const deletedBranches = [];
|
|
143
|
-
for (const branch of allBranches) {
|
|
144
|
-
if (this.isBranchMerged(branch)) {
|
|
145
|
-
if (this.dryRun) {
|
|
146
|
-
deletedBranches.push(branch);
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
try {
|
|
150
|
-
execSync(`git branch -d "${branch}"`, {
|
|
151
|
-
encoding: 'utf8',
|
|
152
|
-
timeout: TIMEOUT,
|
|
153
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
154
|
-
});
|
|
155
|
-
deletedBranches.push(branch);
|
|
156
|
-
}
|
|
157
|
-
catch (deleteError) {
|
|
158
|
-
// Try force delete if regular delete fails
|
|
159
|
-
try {
|
|
160
|
-
execSync(`git branch -D "${branch}"`, {
|
|
161
|
-
encoding: 'utf8',
|
|
162
|
-
timeout: TIMEOUT,
|
|
163
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
164
|
-
});
|
|
165
|
-
deletedBranches.push(branch);
|
|
166
|
-
}
|
|
167
|
-
catch (forceDeleteError) {
|
|
168
|
-
// Couldn't delete - skip this branch
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
return deletedBranches;
|
|
174
|
-
}
|
|
175
|
-
catch (error) {
|
|
176
|
-
return [];
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
/**
|
|
180
|
-
* Check if a branch has been merged into main
|
|
181
|
-
*/
|
|
182
|
-
isBranchMerged(branch) {
|
|
183
|
-
try {
|
|
184
|
-
const mergedBranches = execSync(`git branch --merged ${this.mainBranch} --format="%(refname:short)"`, {
|
|
185
|
-
encoding: 'utf8',
|
|
186
|
-
timeout: TIMEOUT
|
|
187
|
-
});
|
|
188
|
-
return mergedBranches.includes(branch);
|
|
189
|
-
}
|
|
190
|
-
catch (error) {
|
|
191
|
-
// If we can't determine merge status, don't delete the branch
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Clean up remote tracking references
|
|
197
|
-
*/
|
|
198
|
-
pruneRemoteReferences() {
|
|
199
|
-
try {
|
|
200
|
-
execSync(`git remote prune ${this.remoteName}`, {
|
|
201
|
-
encoding: 'utf8',
|
|
202
|
-
timeout: TIMEOUT,
|
|
203
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
catch (error) {
|
|
207
|
-
// Non-critical operation - don't fail on error
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* Convenience function for quick cleanup
|
|
213
|
-
*
|
|
214
|
-
* @param options - Cleanup options
|
|
215
|
-
* @returns Cleanup result
|
|
216
|
-
*/
|
|
217
|
-
export async function cleanupMergedBranches(options = {}) {
|
|
218
|
-
const cleanup = new PostPRMergeCleanup(options);
|
|
219
|
-
return cleanup.runCleanup();
|
|
220
|
-
}
|
|
221
|
-
//# sourceMappingURL=post-merge-cleanup.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"post-merge-cleanup.js","sourceRoot":"","sources":["../src/post-merge-cleanup.ts"],"names":[],"mappings":"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"}
|
package/dist/tree-hash.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deterministic Git Tree Hash Calculation
|
|
3
|
-
*
|
|
4
|
-
* Provides content-based hashing of working tree state including:
|
|
5
|
-
* - Staged changes (index)
|
|
6
|
-
* - Unstaged changes (working tree modifications)
|
|
7
|
-
* - Untracked files
|
|
8
|
-
*
|
|
9
|
-
* CRITICAL FIX: Uses git write-tree instead of git stash create for determinism.
|
|
10
|
-
* git stash create includes timestamps, making hashes non-deterministic.
|
|
11
|
-
* git write-tree produces content-based hashes only (no timestamps).
|
|
12
|
-
*/
|
|
13
|
-
/**
|
|
14
|
-
* Get deterministic git tree hash representing current working tree state
|
|
15
|
-
*
|
|
16
|
-
* Implementation:
|
|
17
|
-
* 1. Mark untracked files with --intent-to-add (no actual staging)
|
|
18
|
-
* 2. Calculate tree hash with git write-tree (content-based, no timestamps)
|
|
19
|
-
* 3. Reset index to clean state (no side effects)
|
|
20
|
-
*
|
|
21
|
-
* Why this is better than git stash create:
|
|
22
|
-
* - git stash create: includes timestamps in commit → different hash each time
|
|
23
|
-
* - git write-tree: content-based only → same content = same hash (deterministic)
|
|
24
|
-
*
|
|
25
|
-
* @returns Git tree SHA-1 hash (40 hex characters)
|
|
26
|
-
* @throws Error if not in a git repository or git command fails
|
|
27
|
-
*/
|
|
28
|
-
export declare function getGitTreeHash(): Promise<string>;
|
|
29
|
-
/**
|
|
30
|
-
* Get tree hash for HEAD commit (committed state only, no working tree changes)
|
|
31
|
-
*
|
|
32
|
-
* This is useful for comparing committed state vs working tree state.
|
|
33
|
-
*
|
|
34
|
-
* @returns Git tree SHA-1 hash of HEAD commit
|
|
35
|
-
* @throws Error if not in a git repository or HEAD doesn't exist
|
|
36
|
-
*/
|
|
37
|
-
export declare function getHeadTreeHash(): Promise<string>;
|
|
38
|
-
/**
|
|
39
|
-
* Check if working tree has any changes compared to HEAD
|
|
40
|
-
*
|
|
41
|
-
* @returns true if working tree differs from HEAD, false if clean
|
|
42
|
-
*/
|
|
43
|
-
export declare function hasWorkingTreeChanges(): Promise<boolean>;
|
|
44
|
-
//# sourceMappingURL=tree-hash.d.ts.map
|
package/dist/tree-hash.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tree-hash.d.ts","sourceRoot":"","sources":["../src/tree-hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CA6CtD;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC,CAQvD;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC,CAS9D"}
|
package/dist/tree-hash.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deterministic Git Tree Hash Calculation
|
|
3
|
-
*
|
|
4
|
-
* Provides content-based hashing of working tree state including:
|
|
5
|
-
* - Staged changes (index)
|
|
6
|
-
* - Unstaged changes (working tree modifications)
|
|
7
|
-
* - Untracked files
|
|
8
|
-
*
|
|
9
|
-
* CRITICAL FIX: Uses git write-tree instead of git stash create for determinism.
|
|
10
|
-
* git stash create includes timestamps, making hashes non-deterministic.
|
|
11
|
-
* git write-tree produces content-based hashes only (no timestamps).
|
|
12
|
-
*/
|
|
13
|
-
import { execSync } from 'child_process';
|
|
14
|
-
const GIT_TIMEOUT = 10000; // 10 seconds
|
|
15
|
-
const GIT_OPTIONS = {
|
|
16
|
-
encoding: 'utf8',
|
|
17
|
-
timeout: GIT_TIMEOUT,
|
|
18
|
-
stdio: ['pipe', 'pipe', 'ignore'],
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Get deterministic git tree hash representing current working tree state
|
|
22
|
-
*
|
|
23
|
-
* Implementation:
|
|
24
|
-
* 1. Mark untracked files with --intent-to-add (no actual staging)
|
|
25
|
-
* 2. Calculate tree hash with git write-tree (content-based, no timestamps)
|
|
26
|
-
* 3. Reset index to clean state (no side effects)
|
|
27
|
-
*
|
|
28
|
-
* Why this is better than git stash create:
|
|
29
|
-
* - git stash create: includes timestamps in commit → different hash each time
|
|
30
|
-
* - git write-tree: content-based only → same content = same hash (deterministic)
|
|
31
|
-
*
|
|
32
|
-
* @returns Git tree SHA-1 hash (40 hex characters)
|
|
33
|
-
* @throws Error if not in a git repository or git command fails
|
|
34
|
-
*/
|
|
35
|
-
export async function getGitTreeHash() {
|
|
36
|
-
try {
|
|
37
|
-
// Check if we're in a git repository
|
|
38
|
-
execSync('git rev-parse --is-inside-work-tree', GIT_OPTIONS);
|
|
39
|
-
// Step 1: Mark all untracked files with --intent-to-add
|
|
40
|
-
// This adds them to the index WITHOUT staging their content
|
|
41
|
-
// --force: include ignored files for complete state tracking
|
|
42
|
-
try {
|
|
43
|
-
execSync('git add --intent-to-add --all --force', {
|
|
44
|
-
...GIT_OPTIONS,
|
|
45
|
-
stdio: ['pipe', 'pipe', 'pipe'] // Capture stderr for error handling
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
catch (addError) {
|
|
49
|
-
// If no untracked files, git add fails with "nothing to add"
|
|
50
|
-
// This is fine - just means we only have tracked files
|
|
51
|
-
const errorMessage = addError instanceof Error ? addError.message : String(addError);
|
|
52
|
-
if (!errorMessage.includes('nothing')) {
|
|
53
|
-
// Real error - re-throw
|
|
54
|
-
throw addError;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
// Step 2: Get tree hash (content-based, no timestamps)
|
|
58
|
-
const treeHash = execSync('git write-tree', GIT_OPTIONS).trim();
|
|
59
|
-
// Step 3: Reset index to clean state (remove intent-to-add marks)
|
|
60
|
-
// This ensures no side effects from our hash calculation
|
|
61
|
-
execSync('git reset', GIT_OPTIONS);
|
|
62
|
-
return treeHash;
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
// Handle not-in-git-repo case
|
|
66
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
67
|
-
if (errorMessage.includes('not a git repository')) {
|
|
68
|
-
// Not in git repo - fall back to timestamp-based hash
|
|
69
|
-
console.warn('⚠️ Not in git repository, using timestamp-based hash');
|
|
70
|
-
return `nogit-${Date.now()}`;
|
|
71
|
-
}
|
|
72
|
-
// Other git errors
|
|
73
|
-
throw new Error(`Failed to calculate git tree hash: ${errorMessage}`);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Get tree hash for HEAD commit (committed state only, no working tree changes)
|
|
78
|
-
*
|
|
79
|
-
* This is useful for comparing committed state vs working tree state.
|
|
80
|
-
*
|
|
81
|
-
* @returns Git tree SHA-1 hash of HEAD commit
|
|
82
|
-
* @throws Error if not in a git repository or HEAD doesn't exist
|
|
83
|
-
*/
|
|
84
|
-
export async function getHeadTreeHash() {
|
|
85
|
-
try {
|
|
86
|
-
const treeHash = execSync('git rev-parse HEAD^{tree}', GIT_OPTIONS).trim();
|
|
87
|
-
return treeHash;
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
91
|
-
throw new Error(`Failed to get HEAD tree hash: ${errorMessage}`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Check if working tree has any changes compared to HEAD
|
|
96
|
-
*
|
|
97
|
-
* @returns true if working tree differs from HEAD, false if clean
|
|
98
|
-
*/
|
|
99
|
-
export async function hasWorkingTreeChanges() {
|
|
100
|
-
try {
|
|
101
|
-
const workingTreeHash = await getGitTreeHash();
|
|
102
|
-
const headTreeHash = await getHeadTreeHash();
|
|
103
|
-
return workingTreeHash !== headTreeHash;
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
// If we can't determine, assume there are changes (safe default)
|
|
107
|
-
return true;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=tree-hash.js.map
|
package/dist/tree-hash.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tree-hash.js","sourceRoot":"","sources":["../src/tree-hash.ts"],"names":[],"mappings":"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"}
|