Skip to content

Commit 24393b6

Browse files
committed
feat: add 'git info' command to display repository details
- Implement 'git info' command in gcop/__main__.py - Update docs/guide/commands.md with new command details - Update docs/guide/quick-start.md with usage examples - Add docs/images/git-info.png for visual reference - Update pyproject.toml to reflect version bump The 'git info' command provides a comprehensive overview of the current git repository, including project name, branch, latest commit, contributor statistics, file changes, and more. This feature enhances project management and code review processes by offering detailed insights into the repository's structure and history.
1 parent 1b93b94 commit 24393b6

File tree

5 files changed

+302
-3
lines changed

5 files changed

+302
-3
lines changed

docs/guide/commands.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ Show the help message with a list of available GCOP commands.
3232

3333
Open the GCOP configuration file in the default editor.
3434

35+
### `git info`
36+
37+
Display basic information about the current git repository.
38+
3539
## Usage Examples
3640

3741
1. Generate and apply an AI commit message:
@@ -54,4 +58,30 @@ Open the GCOP configuration file in the default editor.
5458
git p
5559
```
5660

57-
For more detailed information on each command, refer to the [Quick Start](/guide/quick-start.md) section in the guide.
61+
5. View repository information:
62+
```
63+
git info
64+
```
65+
This command provides a summary of your repository, including:
66+
67+
- Project name
68+
- Current branch
69+
- Latest commit
70+
- Number of uncommitted changes
71+
- Remote URL
72+
- Total number of commits
73+
- Number of contributors
74+
- Repository creation time
75+
- Last modified time
76+
- Repository size
77+
- Most active contributor
78+
- Most changed file
79+
- Line count by language (if cloc is installed)
80+
- Latest tag
81+
- Branch count
82+
- Untracked files count
83+
- Submodule information
84+
- Latest merge commit
85+
- File type statistics
86+
87+
For more detailed information on each command, refer to the [Quick Start](/guide/quick-start.md) section in the guide.

docs/guide/quick-start.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,44 @@ These changes improve the clarity and accuracy of the documentation, ensuring th
100100
3 files changed, 5 insertions(+), 2 deletions(-)
101101
```
102102

103+
### Viewing Repository Information
104+
105+
To get a detailed overview of your repository, use:
106+
107+
```
108+
git info
109+
```
110+
111+
This command now displays comprehensive information about your repository, including:
112+
113+
- Project name
114+
- Current branch
115+
- Latest commit
116+
- Number of uncommitted changes
117+
- Remote URL
118+
- Total number of commits
119+
- Number of contributors
120+
- Repository creation time
121+
- Last modified time
122+
- Repository size
123+
- Most active contributor
124+
- Most changed file
125+
- Line count by language (if cloc is installed)
126+
- Latest tag
127+
- Branch count
128+
- Untracked files count
129+
- Submodule information
130+
- Latest merge commit
131+
- File type statistics
132+
133+
This detailed information provides a thorough understanding of your project's state, history, and composition. It's particularly useful for quickly assessing the repository's overall structure and recent activities.
134+
135+
For example:
136+
137+
![repository information](../images/git-info.png)
138+
139+
> Note: Some features like line count by language require additional tools (e.g., cloc) to be installed.
140+
103141
### Other Useful Commands
104142

105143
- `git ac`: Add all changes and commit with an AI-generated message

docs/images/git-info.png

100 KB
Loading

gcop/__main__.py

Lines changed: 232 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ def init_command():
210210
check=True,
211211
encoding="utf-8", # noqa
212212
)
213+
subprocess.run(
214+
["git", "config", "--global", "alias.info", "!gcop info"],
215+
check=True,
216+
encoding="utf-8", # noqa
217+
)
213218
subprocess.run(
214219
["git", "config", "--global", "alias.gconfig", "!gcop config"],
215220
check=True,
@@ -228,6 +233,231 @@ def init_command():
228233
print(f"Error adding git aliases: {error}")
229234

230235

236+
@app.command(name="info")
237+
def info_command():
238+
"""Display detailed information about the current git repository."""
239+
try:
240+
# Get project name (usually the directory name)
241+
project_name = os.path.basename(os.getcwd())
242+
243+
# Get current branch
244+
current_branch = subprocess.check_output(
245+
["git", "rev-parse", "--abbrev-ref", "HEAD"], text=True
246+
).strip()
247+
248+
# Get latest commit info
249+
latest_commit = subprocess.check_output(
250+
["git", "log", "-1", "--oneline"], text=True
251+
).strip()
252+
253+
# Get number of uncommitted changes
254+
uncommitted_changes = len(
255+
subprocess.check_output(
256+
["git", "status", "--porcelain"], text=True
257+
).splitlines()
258+
)
259+
260+
# Get remote URL
261+
remote_url = subprocess.check_output(
262+
["git", "config", "--get", "remote.origin.url"], text=True
263+
).strip()
264+
265+
# Get total number of commits
266+
total_commits = subprocess.check_output(
267+
["git", "rev-list", "--count", "HEAD"], text=True
268+
).strip()
269+
270+
# Get number of contributors
271+
contributors = len(
272+
set(
273+
subprocess.check_output(
274+
["git", "log", "--format='%ae'"], text=True
275+
).splitlines()
276+
)
277+
)
278+
279+
# Get repository creation time
280+
creation_time = subprocess.check_output(
281+
[
282+
"git",
283+
"log",
284+
"--reverse",
285+
"--date=iso",
286+
"--format=%ad",
287+
"|",
288+
"head",
289+
"-1",
290+
],
291+
text=True,
292+
shell=True,
293+
).strip()
294+
295+
# Get last modified time
296+
last_modified = subprocess.check_output(
297+
["git", "log", "-1", "--date=iso", "--format=%ad"], text=True
298+
).strip()
299+
300+
# Get repository size
301+
repo_size = (
302+
subprocess.check_output(["git", "count-objects", "-vH"], text=True)
303+
.split("\n")[2]
304+
.split(":")[1]
305+
.strip()
306+
)
307+
308+
# Get most active contributor
309+
most_active = (
310+
subprocess.check_output(
311+
["git", "shortlog", "-sn", "--no-merges", "|", "head", "-n", "1"],
312+
text=True,
313+
shell=True,
314+
)
315+
.strip()
316+
.split("\t")[1]
317+
)
318+
319+
# Get most changed file
320+
most_changed = (
321+
subprocess.check_output(
322+
[
323+
"git",
324+
"log",
325+
"--pretty=format:",
326+
"--name-only",
327+
"|",
328+
"sort",
329+
"|",
330+
"uniq",
331+
"-c",
332+
"|",
333+
"sort",
334+
"-rg",
335+
"|",
336+
"head",
337+
"-n",
338+
"1",
339+
],
340+
text=True,
341+
shell=True,
342+
)
343+
.strip()
344+
.split()[-1]
345+
)
346+
347+
# Get line count by language (requires cloc to be installed)
348+
try:
349+
line_count = subprocess.check_output(
350+
["cloc", ".", "--quiet", "--json"], text=True
351+
)
352+
# Parse JSON output and format it
353+
import json
354+
355+
line_count_data = json.loads(line_count)
356+
formatted_line_count = "\n".join(
357+
[
358+
f"{lang}: {data['code']} lines"
359+
for lang, data in line_count_data.items()
360+
if lang != "header" and lang != "SUM"
361+
]
362+
)
363+
line_count = formatted_line_count
364+
except FileNotFoundError:
365+
line_count = (
366+
"cloc not found. Please ensure it's installed and in your system PATH."
367+
)
368+
except json.JSONDecodeError:
369+
line_count = (
370+
"Error parsing cloc output. Please check if cloc is working correctly."
371+
)
372+
except subprocess.CalledProcessError:
373+
line_count = "Error running cloc. Please check if it's installed correctly."
374+
375+
# Get latest tag
376+
try:
377+
latest_tag = subprocess.check_output(
378+
["git", "describe", "--tags", "--abbrev=0"], text=True
379+
).strip()
380+
except subprocess.CalledProcessError:
381+
latest_tag = "No tags found"
382+
383+
# Get branch count
384+
branch_count = len(
385+
subprocess.check_output(["git", "branch", "-a"], text=True).splitlines()
386+
)
387+
388+
# Get untracked files count
389+
untracked_count = len(
390+
subprocess.check_output(
391+
["git", "ls-files", "--others", "--exclude-standard"], text=True
392+
).splitlines()
393+
)
394+
395+
# Get submodule info
396+
try:
397+
submodules = subprocess.check_output(
398+
["git", "submodule", "status"], text=True
399+
).strip()
400+
if not submodules:
401+
submodules = "No submodules"
402+
except subprocess.CalledProcessError:
403+
submodules = "No submodules"
404+
405+
# Get latest merge commit
406+
try:
407+
latest_merge = subprocess.check_output(
408+
["git", "log", "--merges", "-n", "1", "--pretty=format:%h - %s"],
409+
text=True,
410+
).strip()
411+
if not latest_merge:
412+
latest_merge = "No merge commits found"
413+
except subprocess.CalledProcessError:
414+
latest_merge = "No merge commits found"
415+
416+
# Get file type statistics
417+
file_types = subprocess.check_output(
418+
[
419+
"git",
420+
"ls-files",
421+
"|",
422+
"sed",
423+
"s/.*\\.//",
424+
"|",
425+
"sort",
426+
"|",
427+
"uniq",
428+
"-c",
429+
"|",
430+
"sort",
431+
"-rn",
432+
],
433+
text=True,
434+
shell=True,
435+
).strip()
436+
437+
console.print(f"[bold]Project Name:[/] {project_name}")
438+
console.print(f"[bold]Current Branch:[/] {current_branch}")
439+
console.print(f"[bold]Latest Commit:[/] {latest_commit}")
440+
console.print(f"[bold]Uncommitted Changes:[/] {uncommitted_changes}")
441+
console.print(f"[bold]Remote URL:[/] {remote_url}")
442+
console.print(f"[bold]Total Commits:[/] {total_commits}")
443+
console.print(f"[bold]Contributors:[/] {contributors}")
444+
console.print(f"[bold]Repository Created:[/] {creation_time}")
445+
console.print(f"[bold]Last Modified:[/] {last_modified}")
446+
console.print(f"[bold]Repository Size:[/] {repo_size}")
447+
console.print(f"[bold]Most Active Contributor:[/] {most_active}")
448+
console.print(f"[bold]Most Changed File:[/] {most_changed}")
449+
console.print(f"[bold]Line Count by Language:[/]\n{line_count}")
450+
console.print(f"[bold]Latest Tag:[/] {latest_tag}")
451+
console.print(f"[bold]Branch Count:[/] {branch_count}")
452+
console.print(f"[bold]Untracked Files:[/] {untracked_count}")
453+
console.print(f"[bold]Submodules:[/]{submodules}")
454+
console.print(f"[bold]Latest Merge Commit:[/] {latest_merge}")
455+
console.print(f"[bold]File Type Statistics:[/]\n{file_types}")
456+
457+
except subprocess.CalledProcessError as e:
458+
console.print(f"[red]Error getting repository information: {e}[/]")
459+
460+
231461
@app.command(name="commit")
232462
def commit_command(feedback: Optional[str] = None):
233463
"""Generate a git commit message based on the staged changes and commit the
@@ -296,8 +526,9 @@ def help_command():
296526
git ghelp Add command into git config
297527
git gconfig Open the config file in the default editor
298528
git gcommit Generate a git commit message based on the staged changes and commit the changes
299-
git ac The same as `git add . && git gcommit` command
300529
git c The same as `git gcommit` command
530+
git ac The same as `git add . && git gcommit` command
531+
git info Display basic information about the current git repository
301532
""" # noqa
302533

303534
console.print(help_message)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ requires = ["poetry-core"]
55

66
[tool.poetry]
77
name = "gcop"
8-
version = "1.3.2"
8+
version = "1.4.0"
99
description = "gcop is your git AI copilot."
1010
readme = "README.md"
1111
authors = ["gcop <zeeland4work@gmail.com>"]

0 commit comments

Comments
 (0)