git-copilot-commit 0.1.1__tar.gz → 0.1.2__tar.gz
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.
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/PKG-INFO +35 -1
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/README.md +34 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/pyproject.toml +1 -1
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/src/git_copilot_commit/cli.py +44 -9
- git_copilot_commit-0.1.2/src/git_copilot_commit/settings.py +89 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/uv.lock +1 -1
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/.gitignore +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/.python-version +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/LICENSE +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/src/git_copilot_commit/__init__.py +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/src/git_copilot_commit/git.py +0 -0
- {git_copilot_commit-0.1.1 → git_copilot_commit-0.1.2}/src/git_copilot_commit/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: git-copilot-commit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Automatically generate and commit changes using copilot
|
|
5
5
|
Author-email: Dheepak Krishnamurthy <1813121+kdheepak@users.noreply.github.com>
|
|
6
6
|
License-File: LICENSE
|
|
@@ -20,6 +20,8 @@ GitHub Copilot.
|
|
|
20
20
|
|
|
21
21
|
- **AI-Generated Commit Messages**: Uses GitHub Copilot to analyze your staged changes and generate
|
|
22
22
|
conventional commit messages
|
|
23
|
+
- **Multiple AI Models**: Choose from GPT-4, Claude, Gemini, and other available models
|
|
24
|
+
- **Configurable Defaults**: Set a default model to use across all commits
|
|
23
25
|
- **Message Editing**: Edit generated messages using your git-configured editor or commit directly
|
|
24
26
|
- **Conventional Commits**: Follows the [Conventional Commits](https://www.conventionalcommits.org/)
|
|
25
27
|
specification
|
|
@@ -76,6 +78,7 @@ git-copilot-commit commit
|
|
|
76
78
|
|
|
77
79
|
- `--all, -a`: Stage all files before committing
|
|
78
80
|
- `--verbose, -v`: Show verbose output with file details
|
|
81
|
+
- `--model, -m`: Specify which AI model to use for generating the commit message
|
|
79
82
|
|
|
80
83
|
1. The tool analyzes your changes
|
|
81
84
|
2. Prompts you to stage files (if needed)
|
|
@@ -101,6 +104,18 @@ List available AI models:
|
|
|
101
104
|
git-copilot-commit models
|
|
102
105
|
```
|
|
103
106
|
|
|
107
|
+
#### `config`
|
|
108
|
+
|
|
109
|
+
Manage application configuration:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Show current configuration
|
|
113
|
+
git-copilot-commit config --show
|
|
114
|
+
|
|
115
|
+
# Set a default model for all commits
|
|
116
|
+
git-copilot-commit config --set-default-model gpt-4o
|
|
117
|
+
```
|
|
118
|
+
|
|
104
119
|
### Examples
|
|
105
120
|
|
|
106
121
|
**Commit all changes with staging prompts:**
|
|
@@ -115,6 +130,25 @@ git-copilot-commit commit --all
|
|
|
115
130
|
git-copilot-commit commit --verbose
|
|
116
131
|
```
|
|
117
132
|
|
|
133
|
+
**Use a specific AI model:**
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
git-copilot-commit commit --model claude-3.5-sonnet
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Set up a default model and use it:**
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# Set default model once
|
|
143
|
+
git-copilot-commit config --set-default-model gpt-4o
|
|
144
|
+
|
|
145
|
+
# Now all commits will use gpt-4o by default
|
|
146
|
+
git-copilot-commit commit
|
|
147
|
+
|
|
148
|
+
# Override with a different model when needed
|
|
149
|
+
git-copilot-commit commit --model claude-3.5-sonnet
|
|
150
|
+
```
|
|
151
|
+
|
|
118
152
|
## Generated Commit Message Format
|
|
119
153
|
|
|
120
154
|
The tool follows the [Conventional Commits](https://www.conventionalcommits.org/) specification:
|
|
@@ -7,6 +7,8 @@ GitHub Copilot.
|
|
|
7
7
|
|
|
8
8
|
- **AI-Generated Commit Messages**: Uses GitHub Copilot to analyze your staged changes and generate
|
|
9
9
|
conventional commit messages
|
|
10
|
+
- **Multiple AI Models**: Choose from GPT-4, Claude, Gemini, and other available models
|
|
11
|
+
- **Configurable Defaults**: Set a default model to use across all commits
|
|
10
12
|
- **Message Editing**: Edit generated messages using your git-configured editor or commit directly
|
|
11
13
|
- **Conventional Commits**: Follows the [Conventional Commits](https://www.conventionalcommits.org/)
|
|
12
14
|
specification
|
|
@@ -63,6 +65,7 @@ git-copilot-commit commit
|
|
|
63
65
|
|
|
64
66
|
- `--all, -a`: Stage all files before committing
|
|
65
67
|
- `--verbose, -v`: Show verbose output with file details
|
|
68
|
+
- `--model, -m`: Specify which AI model to use for generating the commit message
|
|
66
69
|
|
|
67
70
|
1. The tool analyzes your changes
|
|
68
71
|
2. Prompts you to stage files (if needed)
|
|
@@ -88,6 +91,18 @@ List available AI models:
|
|
|
88
91
|
git-copilot-commit models
|
|
89
92
|
```
|
|
90
93
|
|
|
94
|
+
#### `config`
|
|
95
|
+
|
|
96
|
+
Manage application configuration:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Show current configuration
|
|
100
|
+
git-copilot-commit config --show
|
|
101
|
+
|
|
102
|
+
# Set a default model for all commits
|
|
103
|
+
git-copilot-commit config --set-default-model gpt-4o
|
|
104
|
+
```
|
|
105
|
+
|
|
91
106
|
### Examples
|
|
92
107
|
|
|
93
108
|
**Commit all changes with staging prompts:**
|
|
@@ -102,6 +117,25 @@ git-copilot-commit commit --all
|
|
|
102
117
|
git-copilot-commit commit --verbose
|
|
103
118
|
```
|
|
104
119
|
|
|
120
|
+
**Use a specific AI model:**
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git-copilot-commit commit --model claude-3.5-sonnet
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Set up a default model and use it:**
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# Set default model once
|
|
130
|
+
git-copilot-commit config --set-default-model gpt-4o
|
|
131
|
+
|
|
132
|
+
# Now all commits will use gpt-4o by default
|
|
133
|
+
git-copilot-commit commit
|
|
134
|
+
|
|
135
|
+
# Override with a different model when needed
|
|
136
|
+
git-copilot-commit commit --model claude-3.5-sonnet
|
|
137
|
+
```
|
|
138
|
+
|
|
105
139
|
## Generated Commit Message Format
|
|
106
140
|
|
|
107
141
|
The tool follows the [Conventional Commits](https://www.conventionalcommits.org/) specification:
|
|
@@ -11,6 +11,7 @@ from rich.table import Table
|
|
|
11
11
|
from pycopilot.copilot import Copilot
|
|
12
12
|
from pycopilot.auth import Authentication
|
|
13
13
|
from .git import GitRepository, GitError, NotAGitRepositoryError, GitStatus
|
|
14
|
+
from .settings import Settings
|
|
14
15
|
|
|
15
16
|
console = Console()
|
|
16
17
|
app = typer.Typer(help=__doc__, add_completion=False)
|
|
@@ -59,7 +60,9 @@ def display_file_status(status: GitStatus) -> None:
|
|
|
59
60
|
console.print(table)
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
def generate_commit_message(
|
|
63
|
+
def generate_commit_message(
|
|
64
|
+
repo: GitRepository, status: GitStatus, model: str | None = None
|
|
65
|
+
) -> str:
|
|
63
66
|
"""Generate a conventional commit message using Copilot API."""
|
|
64
67
|
|
|
65
68
|
# Get recent commits for context
|
|
@@ -179,7 +182,9 @@ def commit(
|
|
|
179
182
|
False, "--all", "-a", help="Stage all files before committing"
|
|
180
183
|
),
|
|
181
184
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show verbose output"),
|
|
182
|
-
model: str = typer.Option(
|
|
185
|
+
model: str | None = typer.Option(
|
|
186
|
+
None, "--model", "-m", help="Model to use for generating commit message"
|
|
187
|
+
),
|
|
183
188
|
):
|
|
184
189
|
"""
|
|
185
190
|
Automatically commit changes in the current git repository.
|
|
@@ -190,6 +195,11 @@ def commit(
|
|
|
190
195
|
console.print("[red]Error: Not in a git repository[/red]")
|
|
191
196
|
raise typer.Exit(1)
|
|
192
197
|
|
|
198
|
+
# Load settings and use default model if none provided
|
|
199
|
+
settings = Settings()
|
|
200
|
+
if model is None:
|
|
201
|
+
model = settings.default_model
|
|
202
|
+
|
|
193
203
|
# Get initial status
|
|
194
204
|
status = repo.get_status()
|
|
195
205
|
|
|
@@ -206,19 +216,19 @@ def commit(
|
|
|
206
216
|
repo.stage_files() # Stage all files
|
|
207
217
|
console.print("[green]Staged all files.[/green]")
|
|
208
218
|
else:
|
|
209
|
-
#
|
|
219
|
+
# Show git status once if there are unstaged or untracked files to prompt about
|
|
220
|
+
if status.has_unstaged_changes or status.has_untracked_files:
|
|
221
|
+
git_status_output = repo._run_git_command(["status"])
|
|
222
|
+
console.print(git_status_output.stdout)
|
|
223
|
+
|
|
210
224
|
if status.has_unstaged_changes:
|
|
211
|
-
if Confirm.ask("
|
|
225
|
+
if Confirm.ask("Modified files found. Add all to staging?"):
|
|
212
226
|
repo.stage_modified()
|
|
213
227
|
console.print("[green]Staged modified files.[/green]")
|
|
214
|
-
else:
|
|
215
|
-
raise typer.Exit()
|
|
216
228
|
if status.has_untracked_files:
|
|
217
|
-
if Confirm.ask("
|
|
229
|
+
if Confirm.ask("Untracked files found. Add all to staging?"):
|
|
218
230
|
repo.stage_files()
|
|
219
231
|
console.print("[green]Staged untracked files.[/green]")
|
|
220
|
-
else:
|
|
221
|
-
raise typer.Exit()
|
|
222
232
|
|
|
223
233
|
# Refresh status after staging
|
|
224
234
|
status = repo.get_status()
|
|
@@ -315,5 +325,30 @@ def models():
|
|
|
315
325
|
console.print(table)
|
|
316
326
|
|
|
317
327
|
|
|
328
|
+
@app.command()
|
|
329
|
+
def config(
|
|
330
|
+
set_default_model: str | None = typer.Option(
|
|
331
|
+
None, "--set-default-model", help="Set default model for commit messages"
|
|
332
|
+
),
|
|
333
|
+
show: bool = typer.Option(False, "--show", help="Show current configuration"),
|
|
334
|
+
):
|
|
335
|
+
"""Manage application configuration."""
|
|
336
|
+
settings = Settings()
|
|
337
|
+
|
|
338
|
+
if set_default_model:
|
|
339
|
+
settings.default_model = set_default_model
|
|
340
|
+
console.print(f"[green]✓ Default model set to: {set_default_model}[/green]")
|
|
341
|
+
|
|
342
|
+
if show or (not set_default_model):
|
|
343
|
+
console.print("\n[bold]Current Configuration:[/bold]")
|
|
344
|
+
default_model = settings.default_model
|
|
345
|
+
if default_model:
|
|
346
|
+
console.print(f"Default model: [cyan]{default_model}[/cyan]")
|
|
347
|
+
else:
|
|
348
|
+
console.print("Default model: [dim]not set[/dim]")
|
|
349
|
+
|
|
350
|
+
console.print(f"Config file: [dim]{settings.config_file}[/dim]")
|
|
351
|
+
|
|
352
|
+
|
|
318
353
|
if __name__ == "__main__":
|
|
319
354
|
app()
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Settings management using XDG Base Directory specification.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from xdg_base_dirs import (
|
|
9
|
+
xdg_cache_home,
|
|
10
|
+
xdg_config_home,
|
|
11
|
+
xdg_data_home,
|
|
12
|
+
xdg_state_home,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class Settings:
|
|
17
|
+
"""Manages application settings using XDG Base Directory specification."""
|
|
18
|
+
|
|
19
|
+
APP_NAME = "git-copilot-commit"
|
|
20
|
+
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.config_dir = xdg_config_home() / self.APP_NAME
|
|
23
|
+
self.data_dir = xdg_data_home() / self.APP_NAME
|
|
24
|
+
self.cache_dir = xdg_cache_home() / self.APP_NAME
|
|
25
|
+
self.state_dir = xdg_state_home() / self.APP_NAME
|
|
26
|
+
|
|
27
|
+
self.config_file = self.config_dir / "config.json"
|
|
28
|
+
|
|
29
|
+
# Ensure directories exist
|
|
30
|
+
self.config_dir.mkdir(parents=True, exist_ok=True)
|
|
31
|
+
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
self.cache_dir.mkdir(parents=True, exist_ok=True)
|
|
33
|
+
self.state_dir.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
|
|
35
|
+
self._config: dict[str, Any] = self._load_config()
|
|
36
|
+
|
|
37
|
+
def _load_config(self) -> dict[str, Any]:
|
|
38
|
+
"""Load configuration from file."""
|
|
39
|
+
if not self.config_file.exists():
|
|
40
|
+
return {}
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
with open(self.config_file, "r") as f:
|
|
44
|
+
return json.load(f)
|
|
45
|
+
except (json.JSONDecodeError, IOError):
|
|
46
|
+
return {}
|
|
47
|
+
|
|
48
|
+
def _save_config(self) -> None:
|
|
49
|
+
"""Save configuration to file."""
|
|
50
|
+
try:
|
|
51
|
+
with open(self.config_file, "w") as f:
|
|
52
|
+
json.dump(self._config, f, indent=2)
|
|
53
|
+
except IOError:
|
|
54
|
+
pass # Silently fail if we can't write
|
|
55
|
+
|
|
56
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
57
|
+
"""Get a configuration value."""
|
|
58
|
+
return self._config.get(key, default)
|
|
59
|
+
|
|
60
|
+
def set(self, key: str, value: Any) -> None:
|
|
61
|
+
"""Set a configuration value."""
|
|
62
|
+
self._config[key] = value
|
|
63
|
+
self._save_config()
|
|
64
|
+
|
|
65
|
+
def delete(self, key: str) -> None:
|
|
66
|
+
"""Delete a configuration value."""
|
|
67
|
+
if key in self._config:
|
|
68
|
+
del self._config[key]
|
|
69
|
+
self._save_config()
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def default_model(self) -> str | None:
|
|
73
|
+
"""Get the default model."""
|
|
74
|
+
return self.get("default_model")
|
|
75
|
+
|
|
76
|
+
@default_model.setter
|
|
77
|
+
def default_model(self, model: str) -> None:
|
|
78
|
+
"""Set the default model."""
|
|
79
|
+
self.set("default_model", model)
|
|
80
|
+
|
|
81
|
+
def clear_cache(self) -> None:
|
|
82
|
+
"""Clear the cache directory."""
|
|
83
|
+
for file in self.cache_dir.glob("*"):
|
|
84
|
+
if file.is_file():
|
|
85
|
+
file.unlink()
|
|
86
|
+
elif file.is_dir():
|
|
87
|
+
import shutil
|
|
88
|
+
|
|
89
|
+
shutil.rmtree(file)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|