Skip to content

Commit 906b09c

Browse files
authored
Merge pull request #6 from gagip/feature/cli-generate
feat: add generate subcommand to CLI
2 parents e1f3d8e + 85f4b30 commit 906b09c

7 files changed

Lines changed: 253 additions & 63 deletions

File tree

README.md

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ git-log-analysis/
2323
│ │ ├── file_processor.py # File processing
2424
│ │ └── encoding_handler.py # Encoding handling
2525
│ ├── cli/ # CLI subcommands
26+
│ │ ├── generate_command.py # generate subcommand
2627
│ │ ├── parse_command.py # parse subcommand
2728
│ │ ├── search_command.py # search subcommand
2829
│ │ └── projects_command.py # projects subcommand
@@ -33,25 +34,16 @@ git-log-analysis/
3334
└── data/ # Data to analyze
3435
```
3536

36-
## Installation & Requirements
37-
38-
### Requirements
37+
## Requirements
3938

4039
- Python 3.12+
40+
- [uv](https://docs.astral.sh/uv/)
4141
- Git must be installed on the system
4242

43-
### Package Installation
44-
45-
**Using UV (recommended)**:
43+
## Installation
4644

4745
```bash
48-
uv pip install mcp pytest
49-
```
50-
51-
**Using pip**:
52-
53-
```bash
54-
pip install mcp pytest
46+
uv sync
5547
```
5648

5749
## Usage
@@ -61,37 +53,41 @@ pip install mcp pytest
6153
Extracts logs from a Git repository on a monthly basis:
6254

6355
```bash
64-
python git_log_analysis/git_monthly_log_generator.py <repo_path> <start_year> <start_month>
56+
uv run cli.py generate -r <repo_path> -y <start_year> [-m <start_month>]
6557
```
6658

6759
**Example:**
6860

6961
```bash
70-
python git_log_analysis/git_monthly_log_generator.py <repository absolute directory path> 2021 8
62+
# Generate from January 2021 (default month)
63+
uv run cli.py generate -r /path/to/repo -y 2021
64+
65+
# Generate from August 2021
66+
uv run cli.py generate -r /path/to/repo -y 2021 -m 8
7167
```
7268

73-
This command generates monthly Git logs from August 2021 to the present in the `<repository absolute directory path>/git_logs_by_month/` directory.
69+
This command generates monthly Git logs from the specified month (default: January) to the present in the `<repo_path>/git_logs_by_month/` directory.
7470

7571
### 2. Analyze Git Logs (CLI)
7672

7773
Parse generated Git log files and save results as JSON:
7874

7975
```bash
80-
python cli.py parse -l <log_directory> -o <output_directory>
76+
uv run cli.py parse -l <log_directory> -o <output_directory>
8177
```
8278

8379
**Example:**
8480

8581
```bash
86-
python cli.py parse -l data/project_git_logs_by_month -o results/project
82+
uv run cli.py parse -l data/project_git_logs_by_month -o results/project
8783
```
8884

8985
### 3. Search Commits (CLI)
9086

9187
Search parsed commits:
9288

9389
```bash
94-
python cli.py search -r <results_directory> -k <keyword>
90+
uv run cli.py search -r <results_directory> -k <keyword>
9591
```
9692

9793
**Options:**
@@ -111,7 +107,7 @@ python cli.py search -r <results_directory> -k <keyword>
111107
View available projects and commit counts:
112108

113109
```bash
114-
python cli.py projects -r <results_directory>
110+
uv run cli.py projects -r <results_directory>
115111
```
116112

117113
### 5. Integrate with Claude Desktop via MCP Server
@@ -160,8 +156,5 @@ Configure the Claude Desktop config file for your OS:
160156
## Tests
161157

162158
```bash
163-
# Run tests
164159
uv run pytest
165-
# or
166-
python -m pytest
167160
```

cli.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import sys
88
import io
99
from git_log_analysis.cli import (
10+
setup_generate_parser,
1011
setup_parse_parser,
1112
setup_search_parser,
1213
setup_projects_parser,
@@ -24,14 +25,16 @@ def main():
2425
formatter_class=argparse.RawDescriptionHelpFormatter,
2526
epilog="""
2627
Subcommands:
28+
generate Extract monthly Git logs from a repository
2729
parse Convert Git log files to JSON
2830
search Search commits from parsed JSON
2931
projects View project list and statistics
3032
3133
For detailed usage of each subcommand:
32-
python cli.py parse --help
33-
python cli.py search --help
34-
python cli.py projects --help
34+
uv run cli.py generate --help
35+
uv run cli.py parse --help
36+
uv run cli.py search --help
37+
uv run cli.py projects --help
3538
""",
3639
)
3740

@@ -44,6 +47,7 @@ def main():
4447
)
4548

4649
# Setup each subcommand
50+
setup_generate_parser(subparsers)
4751
setup_parse_parser(subparsers)
4852
setup_search_parser(subparsers)
4953
setup_projects_parser(subparsers)

docs/architecture.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,17 @@ List Projects: View all managed projects along with their total commit counts.
3434

3535
Get Commit Changes: Retrieve detailed diffs and modification statistics for a specific commit hash.
3636

37-
## 5. Core Module Architecture
37+
## 5. MCP Server Constraints
38+
39+
The MCP server runs in **stdio mode** — stdout is reserved exclusively for MCP protocol communication. Violating this causes the server to hang silently with no response to the client.
40+
41+
**Rules for any code called from MCP tool handlers:**
42+
43+
- Never use `print()` — use `logging` instead (logs go to a file, not stdout)
44+
- Never write to `sys.stdout` directly
45+
- Subprocess calls must not inherit stdout (use `subprocess.PIPE` or redirect to a file)
46+
47+
## 6. Core Module Architecture
3848

3949
Parser: Interprets Git log formats and transforms them into data objects.
4050

docs/usage.md

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,20 @@
33
## Setup
44

55
```bash
6-
# Install dependencies using uv (recommended)
7-
uv sync --dev
8-
9-
# Or using pip
10-
pip install mcp pytest ruff
6+
uv sync
117
```
128

139
## Testing
1410

1511
```bash
16-
# Configure tests first
17-
cp tests/config.py.example tests/config.py
18-
# Edit tests/config.py to set RESULTS_DIR
19-
2012
# Run all tests
2113
uv run pytest
2214

2315
# Run specific test file
24-
pytest tests/test_query_engine.py
16+
uv run pytest tests/test_query_engine.py
2517

2618
# Run with verbose output
27-
pytest -v
19+
uv run pytest -v
2820
```
2921

3022
## Linting
@@ -39,55 +31,61 @@ uv run ruff check --fix .
3931

4032
## CLI Usage
4133

42-
The CLI supports three subcommands: `parse`, `search`, and `projects`.
34+
The CLI supports four subcommands: `generate`, `parse`, `search`, and `projects`.
4335

4436
**1. Generate monthly Git logs:**
4537

4638
```bash
47-
python git_log_analysis/git_monthly_log_generator.py <repo_path> <start_year> <start_month>
39+
uv run cli.py generate -r <repo_path> -y <start_year> [-m <start_month>]
40+
41+
# Generate from January 2024 (default month)
42+
uv run cli.py generate -r /path/to/repo -y 2024
43+
44+
# Generate from June 2024
45+
uv run cli.py generate -r /path/to/repo -y 2024 -m 6
4846
```
4947

5048
**2. Parse logs to JSON:**
5149

5250
```bash
53-
python cli.py parse -l <log_dir> -o <output_dir>
51+
uv run cli.py parse -l <log_dir> -o <output_dir>
5452

5553
# Example
56-
python cli.py parse -l data/project1_logs -o results/project1
54+
uv run cli.py parse -l data/project1_logs -o results/project1
5755
```
5856

5957
**3. Search commits:**
6058

6159
```bash
6260
# Basic keyword search
63-
python cli.py search -r results -k "fix bug"
61+
uv run cli.py search -r results -k "fix bug"
6462

6563
# Date range search
66-
python cli.py search -r results -s 2024-01-01 -e 2024-12-31
64+
uv run cli.py search -r results -s 2024-01-01 -e 2024-12-31
6765

6866
# Filter by author
69-
python cli.py search -r results -a "홍길동"
67+
uv run cli.py search -r results -a "홍길동"
7068

7169
# Filter by project
72-
python cli.py search -r results -p project1 -k "feature"
70+
uv run cli.py search -r results -p project1 -k "feature"
7371

7472
# Export to JSON
75-
python cli.py search -r results -k "update" --format json -o results.json
73+
uv run cli.py search -r results -k "update" --format json -o results.json
7674

7775
# Export to CSV
78-
python cli.py search -r results -a "김철수" --format csv -o report.csv
76+
uv run cli.py search -r results -a "김철수" --format csv -o report.csv
7977

8078
# Limit results
81-
python cli.py search -r results -k "refactor" --limit 10
79+
uv run cli.py search -r results -k "refactor" --limit 10
8280

8381
# Combined filters
84-
python cli.py search -r results -k "authentication" -a "developer" -s 2024-01-01 --format json
82+
uv run cli.py search -r results -k "authentication" -a "developer" -s 2024-01-01 --format json
8583
```
8684

8785
**4. List projects:**
8886

8987
```bash
90-
python cli.py projects -r results
88+
uv run cli.py projects -r results
9189

9290
# Example output:
9391
# Available projects in results:

git_log_analysis/cli/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
"""CLI commands module"""
22

3+
from .generate_command import setup_generate_parser
34
from .parse_command import setup_parse_parser
4-
from .search_command import setup_search_parser
55
from .projects_command import setup_projects_parser
6+
from .search_command import setup_search_parser
67

7-
__all__ = ["setup_parse_parser", "setup_search_parser", "setup_projects_parser"]
8+
__all__ = [
9+
"setup_generate_parser",
10+
"setup_parse_parser",
11+
"setup_search_parser",
12+
"setup_projects_parser",
13+
]
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Generate command: Extract monthly git logs from a repository"""
2+
3+
import argparse
4+
from pathlib import Path
5+
6+
from git_log_analysis.git_monthly_log_generator import generate_git_logs
7+
8+
from .types import SubParser
9+
10+
11+
def setup_generate_parser(subparsers: SubParser):
12+
"""Setup argument parser for generate subcommand
13+
14+
Args:
15+
subparsers: argparse subparsers object
16+
"""
17+
parser = subparsers.add_parser(
18+
"generate",
19+
help="Extract monthly Git logs from a repository",
20+
description="Runs 'git log' on a local repository and saves the output as monthly .txt files.",
21+
formatter_class=argparse.RawDescriptionHelpFormatter,
22+
epilog="""
23+
Examples:
24+
uv run cli.py generate -r /path/to/repo -y 2024 -m 1
25+
uv run cli.py generate -r /path/to/repo -y 2023 -m 6
26+
""",
27+
)
28+
29+
parser.add_argument(
30+
"-r",
31+
"--repo-path",
32+
required=True,
33+
help="Path to the local Git repository",
34+
)
35+
parser.add_argument(
36+
"-y",
37+
"--year",
38+
required=True,
39+
type=int,
40+
help="Start year (YYYY)",
41+
)
42+
parser.add_argument(
43+
"-m",
44+
"--month",
45+
type=int,
46+
choices=range(1, 13),
47+
default=1,
48+
help="Start month (1-12, default: 1)",
49+
)
50+
51+
parser.set_defaults(func=_generate_command)
52+
53+
54+
def _generate_command(args):
55+
"""Execute generate command
56+
57+
Args:
58+
args: Parsed command line arguments
59+
"""
60+
repo_path = Path(args.repo_path).resolve()
61+
print(f"Generating Git logs from: {repo_path}")
62+
print(f" Start: {args.year}-{args.month:02d}\n")
63+
64+
try:
65+
generate_git_logs(repo_path, args.year, args.month)
66+
except (FileNotFoundError, ValueError) as e:
67+
print(f"❌ Error: {e}")
68+
return 1
69+
except Exception as e:
70+
print(f"❌ Unexpected error: {e}")
71+
return 1
72+
73+
return 0

0 commit comments

Comments
 (0)