-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathgcommit.py
More file actions
147 lines (122 loc) · 5 KB
/
gcommit.py
File metadata and controls
147 lines (122 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import git
import os
import sys
import google.generativeai as genai
import time
import threading
from datetime import datetime
model_name = "gemini-1.5-flash-002"
class LoadingSpinner:
def __init__(self, message="Loading"):
self.spinner_chars = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
self.message = message
self.spinning = False
self.thread = None
def spin(self):
while self.spinning:
for char in self.spinner_chars:
if not self.spinning:
break
print(f"\r{char} {self.message}...", end="", flush=True)
time.sleep(0.1)
def start(self):
self.spinning = True
self.thread = threading.Thread(target=self.spin)
self.thread.start()
def stop(self):
self.spinning = False
if self.thread:
self.thread.join()
print("\r" + " " * (len(self.message) + 10), end="\r")
def generate_commit_message(push=False, remote_name=None, branch_name=None):
print("\n┌─────────────────────────────────────────┐")
print("│ 🤖 GCOMMIT - AI Git Commit Generator │")
print("└─────────────────────────────────────────┘\n")
# API Key validation
api_key = os.getenv("GOOGLE_API_KEY")
if not api_key:
print(" ❌ Error: GOOGLE_API_KEY not set")
sys.exit(1)
genai.configure(api_key=api_key)
model = genai.GenerativeModel(model_name=model_name)
try:
repo = git.Repo('.')
if not repo.git.rev_parse('--is-inside-work-tree'):
print(" ❌ Error: Not a valid git repository")
sys.exit(1)
except git.InvalidGitRepositoryError:
print(" ❌ Error: Not a valid git repository")
sys.exit(1)
except Exception as e:
print(f" ❌ Error: {e}")
sys.exit(1)
# Get changes
changes = repo.git.diff('HEAD', cached=True, name_only=True).splitlines()
if not changes:
print(" ⚠️ No staged changes found")
print(" 💡 Use 'git add' to stage changes first")
sys.exit(0)
print(f" 📁 Files to commit: {len(changes)}")
for file in changes[:3]:
print(f" • {file}")
if len(changes) > 3:
print(f" • ...and {len(changes) - 3} more files")
# Generate commit message
spinner = LoadingSpinner("Generating commit message")
spinner.start()
diff_details = repo.git.diff('HEAD', cached=True)
prompt_text = f"""Create a concise commit message for these changes:
Files changed: {changes}
Diff: {diff_details[:1500]}
Use Conventional Commits format (e.g., feat:, fix:, docs:)
Keep it under 60 characters
Example: feat: add user authentication system
Return only the commit message:"""
try:
response = model.generate_content(prompt_text)
spinner.stop()
commit_message = response.text.strip()
print("\n┌─ Suggested Commit Message ─────────────┐")
print(f"│ {commit_message:<35} │")
print("└───────────────────────────────────────┘\n")
confirm = input("Use this message? [Y/n]: ").strip().lower()
if confirm in ['', 'y', 'yes']:
# Perform commit
spinner = LoadingSpinner("Committing changes")
spinner.start()
repo.index.commit(commit_message)
spinner.stop()
print(" ✅ Commit successful!")
# Handle push if requested
if push:
if not remote_name or not branch_name:
print(" ❌ Error: Remote and branch required for push")
sys.exit(1)
spinner = LoadingSpinner(f"Pushing to {remote_name}/{branch_name}")
spinner.start()
repo.git.push(remote_name, branch_name)
spinner.stop()
print(f" ✅ Pushed to {remote_name}/{branch_name}")
else:
print(" ⚠️ Commit cancelled")
print(f" 💡 Manual commit: git commit -m \"{commit_message}\"")
except Exception as e:
spinner.stop()
print(f" ❌ Error: {str(e)[:100]}")
sys.exit(1)
finally:
git.Repo.close(repo)
if __name__ == "__main__":
push_flag = '--push' in sys.argv
remote_name = None
branch_name = None
if push_flag:
try:
remote_name = sys.argv[sys.argv.index('--push') + 1]
branch_name = sys.argv[sys.argv.index('--push') + 2]
except IndexError:
print(" ❌ Error: Missing remote/branch after --push")
print(" 💡 Usage: gcommit --push <remote> <branch>")
sys.exit(1)
# Ini adalah command
generate_commit_message(push=push_flag, remote_name=remote_name, branch_name=branch_name)