git-copilot-commit 0.1.0__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.
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.4
2
+ Name: git-copilot-commit
3
+ Version: 0.1.2
4
+ Summary: Automatically generate and commit changes using copilot
5
+ Author-email: Dheepak Krishnamurthy <1813121+kdheepak@users.noreply.github.com>
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.12
8
+ Requires-Dist: pycopilot>=0.1.1
9
+ Requires-Dist: rich>=14.0.0
10
+ Requires-Dist: typer>=0.16.0
11
+ Requires-Dist: xdg-base-dirs>=6.0.2
12
+ Description-Content-Type: text/markdown
13
+
14
+ # git-copilot-commit
15
+
16
+ 🤖 AI-powered Git commit assistant that automatically generates conventional commit messages using
17
+ GitHub Copilot.
18
+
19
+ ## Features
20
+
21
+ - **AI-Generated Commit Messages**: Uses GitHub Copilot to analyze your staged changes and generate
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
25
+ - **Message Editing**: Edit generated messages using your git-configured editor or commit directly
26
+ - **Conventional Commits**: Follows the [Conventional Commits](https://www.conventionalcommits.org/)
27
+ specification
28
+ - **Rich Output**: Beautiful terminal output with syntax highlighting and tables
29
+
30
+ ## Installation
31
+
32
+ Install using uv (recommended):
33
+
34
+ ```bash
35
+ uv tool install git-copilot-commit
36
+ # or
37
+ uvx git-copilot-commit
38
+ ```
39
+
40
+ Or with pip:
41
+
42
+ ```bash
43
+ pipx install git-copilot-commit
44
+ ```
45
+
46
+ ## Prerequisites
47
+
48
+ 1. **GitHub Copilot Access**: You need an active GitHub Copilot subscription
49
+ 2. **Authentication**: Authenticate with GitHub Copilot before first use
50
+
51
+ ## Quick Start
52
+
53
+ 1. **Authenticate with GitHub Copilot**:
54
+
55
+ ```bash
56
+ git-copilot-commit authenticate
57
+ ```
58
+
59
+ 2. **Make some changes** in your git repository
60
+
61
+ 3. **Generate and commit**:
62
+
63
+ ```bash
64
+ git-copilot-commit commit
65
+ ```
66
+
67
+ ## Usage
68
+
69
+ #### `commit`
70
+
71
+ Automatically commit changes in the current git repository:
72
+
73
+ ```bash
74
+ git-copilot-commit commit
75
+ ```
76
+
77
+ **Options:**
78
+
79
+ - `--all, -a`: Stage all files before committing
80
+ - `--verbose, -v`: Show verbose output with file details
81
+ - `--model, -m`: Specify which AI model to use for generating the commit message
82
+
83
+ 1. The tool analyzes your changes
84
+ 2. Prompts you to stage files (if needed)
85
+ 3. Generates an AI-powered commit message
86
+ 4. Offers three choices:
87
+ - `(c)ommit`: Commit with the generated message
88
+ - `(e)dit`: Edit the message in your git-configured editor
89
+ - `(q)uit`: Cancel the commit
90
+
91
+ #### `authenticate`
92
+
93
+ Set up authentication with GitHub Copilot:
94
+
95
+ ```bash
96
+ git-copilot-commit authenticate
97
+ ```
98
+
99
+ #### `models`
100
+
101
+ List available AI models:
102
+
103
+ ```bash
104
+ git-copilot-commit models
105
+ ```
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
+
119
+ ### Examples
120
+
121
+ **Commit all changes with staging prompts:**
122
+
123
+ ```bash
124
+ git-copilot-commit commit --all
125
+ ```
126
+
127
+ **Commit with verbose output:**
128
+
129
+ ```bash
130
+ git-copilot-commit commit --verbose
131
+ ```
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
+
152
+ ## Generated Commit Message Format
153
+
154
+ The tool follows the [Conventional Commits](https://www.conventionalcommits.org/) specification:
155
+
156
+ ```
157
+ <type>[optional scope]: <description>
158
+ ```
159
+
160
+ **Supported Types:**
161
+
162
+ - `feat`: A new feature
163
+ - `fix`: A bug fix
164
+ - `docs`: Documentation changes
165
+ - `style`: Code formatting (no logic changes)
166
+ - `refactor`: Code restructuring (no behavior changes)
167
+ - `perf`: Performance improvements
168
+ - `test`: Adding or updating tests
169
+ - `chore`: Maintenance tasks (tooling, dependencies, etc.)
170
+ - `revert`: Reverting previous changes
171
+
172
+ **Example Messages:**
173
+
174
+ - `feat(auth): add user authentication with JWT`
175
+ - `fix(database): handle connection retries properly`
176
+ - `docs(readme): update installation instructions`
177
+ - `refactor(utils): simplify date parsing logic`
@@ -0,0 +1,164 @@
1
+ # git-copilot-commit
2
+
3
+ 🤖 AI-powered Git commit assistant that automatically generates conventional commit messages using
4
+ GitHub Copilot.
5
+
6
+ ## Features
7
+
8
+ - **AI-Generated Commit Messages**: Uses GitHub Copilot to analyze your staged changes and generate
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
12
+ - **Message Editing**: Edit generated messages using your git-configured editor or commit directly
13
+ - **Conventional Commits**: Follows the [Conventional Commits](https://www.conventionalcommits.org/)
14
+ specification
15
+ - **Rich Output**: Beautiful terminal output with syntax highlighting and tables
16
+
17
+ ## Installation
18
+
19
+ Install using uv (recommended):
20
+
21
+ ```bash
22
+ uv tool install git-copilot-commit
23
+ # or
24
+ uvx git-copilot-commit
25
+ ```
26
+
27
+ Or with pip:
28
+
29
+ ```bash
30
+ pipx install git-copilot-commit
31
+ ```
32
+
33
+ ## Prerequisites
34
+
35
+ 1. **GitHub Copilot Access**: You need an active GitHub Copilot subscription
36
+ 2. **Authentication**: Authenticate with GitHub Copilot before first use
37
+
38
+ ## Quick Start
39
+
40
+ 1. **Authenticate with GitHub Copilot**:
41
+
42
+ ```bash
43
+ git-copilot-commit authenticate
44
+ ```
45
+
46
+ 2. **Make some changes** in your git repository
47
+
48
+ 3. **Generate and commit**:
49
+
50
+ ```bash
51
+ git-copilot-commit commit
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ #### `commit`
57
+
58
+ Automatically commit changes in the current git repository:
59
+
60
+ ```bash
61
+ git-copilot-commit commit
62
+ ```
63
+
64
+ **Options:**
65
+
66
+ - `--all, -a`: Stage all files before committing
67
+ - `--verbose, -v`: Show verbose output with file details
68
+ - `--model, -m`: Specify which AI model to use for generating the commit message
69
+
70
+ 1. The tool analyzes your changes
71
+ 2. Prompts you to stage files (if needed)
72
+ 3. Generates an AI-powered commit message
73
+ 4. Offers three choices:
74
+ - `(c)ommit`: Commit with the generated message
75
+ - `(e)dit`: Edit the message in your git-configured editor
76
+ - `(q)uit`: Cancel the commit
77
+
78
+ #### `authenticate`
79
+
80
+ Set up authentication with GitHub Copilot:
81
+
82
+ ```bash
83
+ git-copilot-commit authenticate
84
+ ```
85
+
86
+ #### `models`
87
+
88
+ List available AI models:
89
+
90
+ ```bash
91
+ git-copilot-commit models
92
+ ```
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
+
106
+ ### Examples
107
+
108
+ **Commit all changes with staging prompts:**
109
+
110
+ ```bash
111
+ git-copilot-commit commit --all
112
+ ```
113
+
114
+ **Commit with verbose output:**
115
+
116
+ ```bash
117
+ git-copilot-commit commit --verbose
118
+ ```
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
+
139
+ ## Generated Commit Message Format
140
+
141
+ The tool follows the [Conventional Commits](https://www.conventionalcommits.org/) specification:
142
+
143
+ ```
144
+ <type>[optional scope]: <description>
145
+ ```
146
+
147
+ **Supported Types:**
148
+
149
+ - `feat`: A new feature
150
+ - `fix`: A bug fix
151
+ - `docs`: Documentation changes
152
+ - `style`: Code formatting (no logic changes)
153
+ - `refactor`: Code restructuring (no behavior changes)
154
+ - `perf`: Performance improvements
155
+ - `test`: Adding or updating tests
156
+ - `chore`: Maintenance tasks (tooling, dependencies, etc.)
157
+ - `revert`: Reverting previous changes
158
+
159
+ **Example Messages:**
160
+
161
+ - `feat(auth): add user authentication with JWT`
162
+ - `fix(database): handle connection retries properly`
163
+ - `docs(readme): update installation instructions`
164
+ - `refactor(utils): simplify date parsing logic`
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "git-copilot-commit"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "Automatically generate and commit changes using copilot"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -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(repo: GitRepository, status: GitStatus) -> str:
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
@@ -169,7 +172,7 @@ Avoid wrapping the whole response in triple backticks.
169
172
 
170
173
  Generate a conventional commit message:"""
171
174
 
172
- response = client.ask(prompt)
175
+ response = client.ask(prompt, model=model) if model else client.ask(prompt)
173
176
  return response.content
174
177
 
175
178
 
@@ -179,6 +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"),
185
+ model: str | None = typer.Option(
186
+ None, "--model", "-m", help="Model to use for generating commit message"
187
+ ),
182
188
  ):
183
189
  """
184
190
  Automatically commit changes in the current git repository.
@@ -189,6 +195,11 @@ def commit(
189
195
  console.print("[red]Error: Not in a git repository[/red]")
190
196
  raise typer.Exit(1)
191
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
+
192
203
  # Get initial status
193
204
  status = repo.get_status()
194
205
 
@@ -205,19 +216,19 @@ def commit(
205
216
  repo.stage_files() # Stage all files
206
217
  console.print("[green]Staged all files.[/green]")
207
218
  else:
208
- # Check if we need to stage files
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
+
209
224
  if status.has_unstaged_changes:
210
- if Confirm.ask("Stage modified files?"):
225
+ if Confirm.ask("Modified files found. Add all to staging?"):
211
226
  repo.stage_modified()
212
227
  console.print("[green]Staged modified files.[/green]")
213
- else:
214
- raise typer.Exit()
215
228
  if status.has_untracked_files:
216
- if Confirm.ask("Stage untracked files?"):
229
+ if Confirm.ask("Untracked files found. Add all to staging?"):
217
230
  repo.stage_files()
218
231
  console.print("[green]Staged untracked files.[/green]")
219
- else:
220
- raise typer.Exit()
221
232
 
222
233
  # Refresh status after staging
223
234
  status = repo.get_status()
@@ -229,7 +240,7 @@ def commit(
229
240
  # Generate or use provided commit message
230
241
  console.print("[cyan]Generating commit message...[/cyan]")
231
242
  with console.status("[cyan]Generating commit message using Copilot API...[/cyan]"):
232
- commit_message = generate_commit_message(repo, status)
243
+ commit_message = generate_commit_message(repo, status, model)
233
244
 
234
245
  # Display commit message
235
246
  console.print(Panel(commit_message, title="Commit Message", border_style="green"))
@@ -273,57 +284,6 @@ def commit(
273
284
  console.print(f"[green]✓ Successfully committed: {commit_sha[:8]}[/green]")
274
285
 
275
286
 
276
- def handle_interactive_staging(repo: GitRepository, status: GitStatus) -> None:
277
- """Handle interactive file staging."""
278
- # Combine all files that can be staged
279
- stageable_files = [f for f in status.files if not f.is_staged]
280
-
281
- if not stageable_files:
282
- console.print("[yellow]No files to stage.[/yellow]")
283
- return
284
-
285
- table = Table(title="Select files to stage")
286
- table.add_column("Index", style="cyan", width=6)
287
- table.add_column("Status", style="yellow", width=8)
288
- table.add_column("File", style="white")
289
-
290
- for i, file in enumerate(stageable_files, 1):
291
- status_char = file.status if not file.is_untracked else "?"
292
- table.add_row(str(i), status_char, file.path)
293
-
294
- console.print(table)
295
-
296
- selection = (
297
- console.input(
298
- "\nEnter file numbers to stage (comma-separated), 'all', or 'quit': "
299
- )
300
- .strip()
301
- .lower()
302
- )
303
-
304
- if selection == "quit":
305
- return
306
- elif selection == "all":
307
- repo.stage_files([f.path for f in stageable_files])
308
- console.print(f"[green]Staged {len(stageable_files)} files.[/green]")
309
- else:
310
- try:
311
- indices = [int(x.strip()) - 1 for x in selection.split(",")]
312
- files_to_stage = [
313
- stageable_files[i].path
314
- for i in indices
315
- if 0 <= i < len(stageable_files)
316
- ]
317
-
318
- if files_to_stage:
319
- repo.stage_files(files_to_stage)
320
- console.print(f"[green]Staged {len(files_to_stage)} files.[/green]")
321
- else:
322
- console.print("[yellow]No valid files selected.[/yellow]")
323
- except (ValueError, IndexError):
324
- console.print("[red]Invalid selection.[/red]")
325
-
326
-
327
287
  @app.command()
328
288
  def authenticate():
329
289
  """Autheticate with GitHub Copilot."""
@@ -365,5 +325,30 @@ def models():
365
325
  console.print(table)
366
326
 
367
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
+
368
353
  if __name__ == "__main__":
369
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)
@@ -78,7 +78,7 @@ wheels = [
78
78
 
79
79
  [[package]]
80
80
  name = "git-copilot-commit"
81
- version = "0.1.0"
81
+ version = "0.1.2"
82
82
  source = { editable = "." }
83
83
  dependencies = [
84
84
  { name = "pycopilot" },
@@ -1,11 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: git-copilot-commit
3
- Version: 0.1.0
4
- Summary: Automatically generate and commit changes using copilot
5
- Author-email: Dheepak Krishnamurthy <1813121+kdheepak@users.noreply.github.com>
6
- License-File: LICENSE
7
- Requires-Python: >=3.12
8
- Requires-Dist: pycopilot>=0.1.1
9
- Requires-Dist: rich>=14.0.0
10
- Requires-Dist: typer>=0.16.0
11
- Requires-Dist: xdg-base-dirs>=6.0.2
File without changes