n2b 0.7.1 โ†’ 2.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.
@@ -0,0 +1,397 @@
1
+ #!/bin/bash
2
+
3
+ # Branch Audit Script - Safely analyze all branches for unmerged code
4
+ # Author: Augment Agent
5
+ # Purpose: Find valuable code in branches without touching main
6
+
7
+ set -e # Exit on any error
8
+
9
+ # Colors for output
10
+ RED='\033[0;31m'
11
+ GREEN='\033[0;32m'
12
+ YELLOW='\033[1;33m'
13
+ BLUE='\033[0;34m'
14
+ NC='\033[0m' # No Color
15
+
16
+ # Configuration
17
+ MAIN_BRANCH="main"
18
+ REPORT_FILE="branch_audit_report_$(date +%Y-%m-%d_%H-%M-%S).md"
19
+ TEMP_DIR="temp_branch_audit_$$"
20
+ WORKTREE_DIR="worktree_audit_$$"
21
+
22
+ # Arrays to store results
23
+ declare -a MERGEABLE_BRANCHES=()
24
+ declare -a CONFLICTED_BRANCHES=()
25
+ declare -a EMPTY_BRANCHES=()
26
+ declare -a ERROR_BRANCHES=()
27
+
28
+ # Cleanup function
29
+ cleanup() {
30
+ echo -e "${YELLOW}๐Ÿงน Cleaning up temporary files...${NC}"
31
+ if [ -d "$TEMP_DIR" ]; then
32
+ rm -rf "$TEMP_DIR"
33
+ fi
34
+ if [ -d "$WORKTREE_DIR" ]; then
35
+ git worktree remove "$WORKTREE_DIR" 2>/dev/null || true
36
+ rm -rf "$WORKTREE_DIR" 2>/dev/null || true
37
+ fi
38
+ }
39
+
40
+ # Set up cleanup trap
41
+ trap cleanup EXIT
42
+
43
+ # Function to log with timestamp
44
+ log() {
45
+ echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1"
46
+ }
47
+
48
+ # Function to check if branch exists
49
+ branch_exists() {
50
+ git show-ref --verify --quiet "refs/heads/$1" 2>/dev/null
51
+ }
52
+
53
+ # Function to check if remote branch exists
54
+ remote_branch_exists() {
55
+ git show-ref --verify --quiet "refs/remotes/$1" 2>/dev/null
56
+ }
57
+
58
+ # Function to get unique commits in branch vs main
59
+ get_unique_commits() {
60
+ local branch="$1"
61
+ git log --oneline "${MAIN_BRANCH}..${branch}" 2>/dev/null || echo ""
62
+ }
63
+
64
+ # Function to get file changes summary
65
+ get_file_changes() {
66
+ local branch="$1"
67
+ git diff --name-status "${MAIN_BRANCH}...${branch}" 2>/dev/null || echo ""
68
+ }
69
+
70
+ # Function to check if fast-forward merge is possible
71
+ can_fast_forward() {
72
+ local branch="$1"
73
+ local merge_base=$(git merge-base "$MAIN_BRANCH" "$branch" 2>/dev/null || echo "")
74
+ local main_commit=$(git rev-parse "$MAIN_BRANCH" 2>/dev/null || echo "")
75
+
76
+ if [ -z "$merge_base" ] || [ -z "$main_commit" ]; then
77
+ return 1
78
+ fi
79
+
80
+ # If merge base equals main commit, then it's a fast-forward
81
+ [ "$merge_base" = "$main_commit" ]
82
+ }
83
+
84
+ # Function to analyze a single branch
85
+ analyze_branch() {
86
+ local branch="$1"
87
+ local branch_type="$2" # "local" or "remote"
88
+
89
+ log "Analyzing ${branch_type} branch: $branch"
90
+
91
+ # Skip main branch and its variants
92
+ if [[ "$branch" =~ ^(main|master|origin/main|origin/master)$ ]]; then
93
+ log "Skipping main branch: $branch"
94
+ return
95
+ fi
96
+
97
+ # For remote branches, create local tracking branch if needed
98
+ local local_branch="$branch"
99
+ if [ "$branch_type" = "remote" ]; then
100
+ local_branch="${branch#origin/}"
101
+ if ! branch_exists "$local_branch"; then
102
+ log "Creating local tracking branch for $branch"
103
+ git branch "$local_branch" "$branch" 2>/dev/null || {
104
+ ERROR_BRANCHES+=("$branch (failed to create local branch)")
105
+ return
106
+ }
107
+ fi
108
+ fi
109
+
110
+ # Get unique commits
111
+ local unique_commits=$(get_unique_commits "$local_branch")
112
+ local commit_count=0
113
+ if [ -n "$unique_commits" ] && [ "$unique_commits" != "" ]; then
114
+ commit_count=$(echo "$unique_commits" | wc -l | tr -d ' ')
115
+ fi
116
+
117
+ if [ "$commit_count" -eq 0 ]; then
118
+ log "Branch $branch has no unique commits"
119
+ EMPTY_BRANCHES+=("$branch")
120
+ return
121
+ fi
122
+
123
+ # Check if fast-forward is possible
124
+ if can_fast_forward "$local_branch"; then
125
+ log "โœ… Branch $branch can be fast-forward merged ($commit_count commits)"
126
+ MERGEABLE_BRANCHES+=("$branch|$commit_count|$unique_commits")
127
+ else
128
+ log "โš ๏ธ Branch $branch has conflicts or diverged ($commit_count commits)"
129
+ CONFLICTED_BRANCHES+=("$branch|$commit_count|$unique_commits")
130
+ fi
131
+ }
132
+
133
+ # Main execution starts here
134
+ main() {
135
+ echo -e "${GREEN}๐Ÿ” Starting Branch Audit Analysis${NC}"
136
+ echo -e "${BLUE}Repository: $(pwd)${NC}"
137
+ echo -e "${BLUE}Main branch: $MAIN_BRANCH${NC}"
138
+ echo -e "${BLUE}Report file: $REPORT_FILE${NC}"
139
+ echo ""
140
+
141
+ # Verify we're in a git repository
142
+ if ! git rev-parse --git-dir > /dev/null 2>&1; then
143
+ echo -e "${RED}โŒ Error: Not in a git repository${NC}"
144
+ exit 1
145
+ fi
146
+
147
+ # Verify main branch exists
148
+ if ! git show-ref --verify --quiet "refs/heads/$MAIN_BRANCH"; then
149
+ echo -e "${RED}โŒ Error: Main branch '$MAIN_BRANCH' not found${NC}"
150
+ exit 1
151
+ fi
152
+
153
+ # Fetch latest from remote
154
+ log "Fetching latest changes from remote..."
155
+ git fetch --all --prune
156
+
157
+ # Create temporary directory
158
+ mkdir -p "$TEMP_DIR"
159
+
160
+ # Get current branch to restore later
161
+ CURRENT_BRANCH=$(git branch --show-current)
162
+
163
+ # Ensure we're on main branch for analysis
164
+ log "Switching to main branch for analysis..."
165
+ git checkout "$MAIN_BRANCH" >/dev/null 2>&1
166
+
167
+ # Get all local branches
168
+ log "Analyzing local branches..."
169
+ while IFS= read -r branch; do
170
+ branch=$(echo "$branch" | sed 's/^[* ] //' | xargs)
171
+ analyze_branch "$branch" "local"
172
+ done < <(git branch | grep -v "^\*.*$MAIN_BRANCH$")
173
+
174
+ # Get all remote branches
175
+ log "Analyzing remote branches..."
176
+ while IFS= read -r branch; do
177
+ branch=$(echo "$branch" | sed 's|^ remotes/||' | xargs)
178
+ # Skip if we already have this as a local branch
179
+ local_name="${branch#origin/}"
180
+ if ! branch_exists "$local_name"; then
181
+ analyze_branch "$branch" "remote"
182
+ fi
183
+ done < <(git branch -r | grep -v "HEAD\|$MAIN_BRANCH$")
184
+
185
+ # Restore original branch
186
+ if [ -n "$CURRENT_BRANCH" ] && [ "$CURRENT_BRANCH" != "$MAIN_BRANCH" ]; then
187
+ log "Restoring original branch: $CURRENT_BRANCH"
188
+ git checkout "$CURRENT_BRANCH" >/dev/null 2>&1
189
+ fi
190
+
191
+ # Generate report
192
+ generate_report
193
+
194
+ echo ""
195
+ echo -e "${GREEN}โœ… Branch audit completed!${NC}"
196
+ echo -e "${BLUE}๐Ÿ“„ Report saved to: $REPORT_FILE${NC}"
197
+ }
198
+
199
+ # Function to generate detailed report
200
+ generate_report() {
201
+ log "Generating detailed report..."
202
+
203
+ cat > "$REPORT_FILE" << EOF
204
+ # Branch Audit Report
205
+ **Generated:** $(date)
206
+ **Repository:** $(pwd)
207
+ **Main Branch:** $MAIN_BRANCH
208
+
209
+ ## ๐Ÿ“Š Executive Summary
210
+
211
+ - **Mergeable Branches (Fast-Forward):** ${#MERGEABLE_BRANCHES[@]}
212
+ - **Conflicted Branches (Manual Review):** ${#CONFLICTED_BRANCHES[@]}
213
+ - **Empty Branches (No Changes):** ${#EMPTY_BRANCHES[@]}
214
+ - **Error Branches:** ${#ERROR_BRANCHES[@]}
215
+ - **Total Analyzed:** $((${#MERGEABLE_BRANCHES[@]} + ${#CONFLICTED_BRANCHES[@]} + ${#EMPTY_BRANCHES[@]} + ${#ERROR_BRANCHES[@]}))
216
+
217
+ ---
218
+
219
+ EOF
220
+
221
+ # Mergeable branches section
222
+ if [ ${#MERGEABLE_BRANCHES[@]} -gt 0 ]; then
223
+ cat >> "$REPORT_FILE" << EOF
224
+ ## โœ… Mergeable Branches (Fast-Forward Possible)
225
+
226
+ These branches can be safely merged into main without conflicts:
227
+
228
+ EOF
229
+ for branch_info in "${MERGEABLE_BRANCHES[@]}"; do
230
+ IFS='|' read -r branch commit_count commits <<< "$branch_info"
231
+ cat >> "$REPORT_FILE" << EOF
232
+ ### ๐ŸŒฟ \`$branch\`
233
+ - **Unique Commits:** $commit_count
234
+ - **File Changes:** $(get_file_changes "$branch" | wc -l) files
235
+ - **Recent Commits:**
236
+ \`\`\`
237
+ $commits
238
+ \`\`\`
239
+ - **Files Modified:**
240
+ \`\`\`
241
+ $(get_file_changes "$branch" | head -10)
242
+ $([ $(get_file_changes "$branch" | wc -l) -gt 10 ] && echo "... and $(($(get_file_changes "$branch" | wc -l) - 10)) more files")
243
+ \`\`\`
244
+
245
+ **Recommendation:** โœ… Safe to merge with \`git merge $branch\`
246
+
247
+ ---
248
+
249
+ EOF
250
+ done
251
+ fi
252
+
253
+ # Conflicted branches section
254
+ if [ ${#CONFLICTED_BRANCHES[@]} -gt 0 ]; then
255
+ cat >> "$REPORT_FILE" << EOF
256
+ ## โš ๏ธ Conflicted Branches (Manual Review Required)
257
+
258
+ These branches have diverged from main and may have conflicts:
259
+
260
+ EOF
261
+ for branch_info in "${CONFLICTED_BRANCHES[@]}"; do
262
+ IFS='|' read -r branch commit_count commits <<< "$branch_info"
263
+ cat >> "$REPORT_FILE" << EOF
264
+ ### ๐Ÿ”€ \`$branch\`
265
+ - **Unique Commits:** $commit_count
266
+ - **File Changes:** $(get_file_changes "$branch" | wc -l) files
267
+ - **Recent Commits:**
268
+ \`\`\`
269
+ $commits
270
+ \`\`\`
271
+ - **Files Modified:**
272
+ \`\`\`
273
+ $(get_file_changes "$branch" | head -10)
274
+ $([ $(get_file_changes "$branch" | wc -l) -gt 10 ] && echo "... and $(($(get_file_changes "$branch" | wc -l) - 10)) more files")
275
+ \`\`\`
276
+
277
+ **Recommendation:** โš ๏ธ Manual review required - check for conflicts before merging
278
+
279
+ ---
280
+
281
+ EOF
282
+ done
283
+ fi
284
+
285
+ # Empty branches section
286
+ if [ ${#EMPTY_BRANCHES[@]} -gt 0 ]; then
287
+ cat >> "$REPORT_FILE" << EOF
288
+ ## ๐Ÿ—‘๏ธ Empty Branches (Safe to Delete)
289
+
290
+ These branches have no unique commits compared to main:
291
+
292
+ EOF
293
+ for branch in "${EMPTY_BRANCHES[@]}"; do
294
+ cat >> "$REPORT_FILE" << EOF
295
+ - \`$branch\` - No unique changes
296
+ EOF
297
+ done
298
+ cat >> "$REPORT_FILE" << EOF
299
+
300
+ **Cleanup Commands:**
301
+ \`\`\`bash
302
+ # Delete local empty branches
303
+ EOF
304
+ for branch in "${EMPTY_BRANCHES[@]}"; do
305
+ if [[ ! "$branch" =~ ^origin/ ]]; then
306
+ echo "git branch -d $branch" >> "$REPORT_FILE"
307
+ fi
308
+ done
309
+ cat >> "$REPORT_FILE" << EOF
310
+
311
+ # Delete remote empty branches (be careful!)
312
+ EOF
313
+ for branch in "${EMPTY_BRANCHES[@]}"; do
314
+ if [[ "$branch" =~ ^origin/ ]]; then
315
+ remote_branch="${branch#origin/}"
316
+ echo "git push origin --delete $remote_branch" >> "$REPORT_FILE"
317
+ fi
318
+ done
319
+ cat >> "$REPORT_FILE" << EOF
320
+ \`\`\`
321
+
322
+ ---
323
+
324
+ EOF
325
+ fi
326
+
327
+ # Error branches section
328
+ if [ ${#ERROR_BRANCHES[@]} -gt 0 ]; then
329
+ cat >> "$REPORT_FILE" << EOF
330
+ ## โŒ Error Branches
331
+
332
+ These branches encountered errors during analysis:
333
+
334
+ EOF
335
+ for branch in "${ERROR_BRANCHES[@]}"; do
336
+ cat >> "$REPORT_FILE" << EOF
337
+ - \`$branch\`
338
+ EOF
339
+ done
340
+ cat >> "$REPORT_FILE" << EOF
341
+
342
+ **Recommendation:** Manual investigation required
343
+
344
+ ---
345
+
346
+ EOF
347
+ fi
348
+
349
+ # Summary and recommendations
350
+ cat >> "$REPORT_FILE" << EOF
351
+ ## ๐ŸŽฏ Recommended Actions
352
+
353
+ ### Immediate Actions (Safe)
354
+ 1. **Merge fast-forward branches:** ${#MERGEABLE_BRANCHES[@]} branches ready
355
+ 2. **Delete empty branches:** ${#EMPTY_BRANCHES[@]} branches can be removed
356
+ 3. **Review conflicted branches:** ${#CONFLICTED_BRANCHES[@]} branches need manual review
357
+
358
+ ### Cleanup Script
359
+ \`\`\`bash
360
+ # Run this script to clean up empty branches
361
+ EOF
362
+
363
+ # Generate cleanup commands for empty branches
364
+ for branch in "${EMPTY_BRANCHES[@]}"; do
365
+ if [[ ! "$branch" =~ ^origin/ ]]; then
366
+ echo "git branch -d $branch" >> "$REPORT_FILE"
367
+ fi
368
+ done
369
+
370
+ cat >> "$REPORT_FILE" << EOF
371
+ \`\`\`
372
+
373
+ ### Merge Script for Fast-Forward Branches
374
+ \`\`\`bash
375
+ # Run these commands to merge ready branches
376
+ EOF
377
+
378
+ # Generate merge commands for mergeable branches
379
+ for branch_info in "${MERGEABLE_BRANCHES[@]}"; do
380
+ IFS='|' read -r branch commit_count commits <<< "$branch_info"
381
+ if [[ ! "$branch" =~ ^origin/ ]]; then
382
+ echo "git merge $branch # $commit_count commits" >> "$REPORT_FILE"
383
+ fi
384
+ done
385
+
386
+ cat >> "$REPORT_FILE" << EOF
387
+ \`\`\`
388
+
389
+ ---
390
+ *Report generated by branch-audit.sh on $(date)*
391
+ EOF
392
+
393
+ log "Report generated: $REPORT_FILE"
394
+ }
395
+
396
+ # Run main function
397
+ main "$@"
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+ require_relative '../lib/n2b/github_client'
5
+
6
+ config_file = File.expand_path('~/.n2b/config.yml')
7
+ unless File.exist?(config_file)
8
+ puts "โŒ Config file not found: #{config_file}"
9
+ puts "Please run 'n2b --advanced-config' to set up GitHub integration first."
10
+ exit 1
11
+ end
12
+
13
+ config = YAML.load_file(config_file)
14
+
15
+ begin
16
+ client = N2B::GitHubClient.new(config)
17
+ rescue => e
18
+ puts "โŒ #{e.message}"
19
+ exit 1
20
+ end
21
+
22
+ client.test_connection