Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ai_commit_msg/cli/conventional_commit_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,4 @@ def conventional_commit_handler(args):

execute_cli_command(["git", "commit", "-m", f'"{formatted_commit}"'], output=True)

handle_git_push()
handle_git_push()
30 changes: 30 additions & 0 deletions ai_commit_msg/cli/doctor_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import os
from rich.console import Console
from rich.panel import Panel
from rich.text import Text
from rich import box

from ai_commit_msg.services.git_service import GitService
from ai_commit_msg.utils.logger import Logger
from ai_commit_msg.utils.utils import execute_cli_command

console = Console()


def check_git_hooks_directory():
"""Check if we can determine the correct git hooks directory"""
try:
# Get the hooks directory using git's built-in command
hooks_dir = execute_cli_command(
["git", "rev-parse", "--git-path", "hooks"]
).stdout.strip()
git_dir = execute_cli_command(["git", "rev-parse", "--git-dir"]).stdout.strip()

return {
"status": "ok",
"hooks_dir": hooks_dir,
"git_dir": git_dir,
"is_worktree": "worktrees" in git_dir,
}
except Exception as e:
return {"status": "error", "error": str(e)}
5 changes: 5 additions & 0 deletions ai_commit_msg/cli/hook_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ def get_bash_script():


def handle_setup_hook(hook_directory_path: str):
# Ensure the hooks directory exists
hooks_dir = os.path.dirname(hook_directory_path)
if not os.path.exists(hooks_dir):
os.makedirs(hooks_dir, exist_ok=True)

existing_hook_content = ""
if os.path.exists(hook_directory_path):
with open(hook_directory_path, "r") as file:
Expand Down
8 changes: 6 additions & 2 deletions ai_commit_msg/services/git_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,12 @@ def get_git_config_value(key: GitConfigKeysEnum):

@staticmethod
def get_git_prepare_commit_msg_hook_path():
git_repo_path = GitService.get_git_directory()
return git_repo_path + "/hooks/prepare-commit-msg"
# Use git's built-in command to get the correct hooks directory
# This properly handles worktrees and other git configurations
hooks_dir = execute_cli_command(
["git", "rev-parse", "--git-path", "hooks"]
).stdout.strip()
return hooks_dir + "/prepare-commit-msg"
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using os.path.join(hooks_dir, 'prepare-commit-msg') to build the path, which improves cross-platform compatibility.

Copilot uses AI. Check for mistakes.

@staticmethod
def get_last_n_commit_msg(n):
Expand Down
3 changes: 2 additions & 1 deletion ai_commit_msg/services/llm_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from abc import ABC, abstractmethod


class LLMService(ABC):
@abstractmethod
def chat_completion(self, messages):
pass
pass
93 changes: 93 additions & 0 deletions test_hook_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#!/usr/bin/env python3

import os
import tempfile
import shutil
from ai_commit_msg.cli.hook_handler import handle_setup_hook


def test_hook_setup_with_missing_directory():
"""Test that handle_setup_hook creates the hooks directory if it doesn't exist"""

# Create a temporary directory for testing
with tempfile.TemporaryDirectory() as temp_dir:
# Create a fake hooks path that doesn't exist
hooks_dir = os.path.join(temp_dir, "hooks")
hook_file_path = os.path.join(hooks_dir, "prepare-commit-msg")

print(f"Testing hook setup with path: {hook_file_path}")
print(f"Hooks directory exists before: {os.path.exists(hooks_dir)}")

# This should create the directory and the hook file
handle_setup_hook(hook_file_path)

print(f"Hooks directory exists after: {os.path.exists(hooks_dir)}")
print(f"Hook file exists: {os.path.exists(hook_file_path)}")
print(f"Hook file is executable: {os.access(hook_file_path, os.X_OK)}")

# Verify the content
if os.path.exists(hook_file_path):
with open(hook_file_path, "r") as f:
content = f.read()
print(f"Hook file contains git-ai-commit: {'git-ai-commit' in content}")

print("✅ Test completed successfully!")


def test_local_git_hooks():
"""Test the actual local .git/hooks directory"""

# Check if we're in a git repository
git_dir = ".git"
if not os.path.exists(git_dir):
print("❌ Not in a git repository - .git directory not found")
return

hooks_dir = os.path.join(git_dir, "hooks")
hook_file_path = os.path.join(hooks_dir, "prepare-commit-msg")

print(f"🔍 Checking local git hooks in: {os.path.abspath(hooks_dir)}")
print(f"Hooks directory exists: {os.path.exists(hooks_dir)}")

if os.path.exists(hooks_dir):
print(f"Files in hooks directory:")
for file in os.listdir(hooks_dir):
file_path = os.path.join(hooks_dir, file)
is_executable = os.access(file_path, os.X_OK)
print(
f" - {file} {'(executable)' if is_executable else '(not executable)'}"
)

print(f"\n📋 prepare-commit-msg hook status:")
print(f"Hook file exists: {os.path.exists(hook_file_path)}")

if os.path.exists(hook_file_path):
print(f"Hook file is executable: {os.access(hook_file_path, os.X_OK)}")

# Check content
with open(hook_file_path, "r") as f:
content = f.read()
has_git_ai_commit = "git-ai-commit" in content
print(f"Hook file contains 'git-ai-commit': {has_git_ai_commit}")

if has_git_ai_commit:
print("✅ git-ai-commit hook is installed!")
else:
print("❌ git-ai-commit not found in hook file")
print("Hook content preview:")
print("-" * 40)
print(content[:200] + "..." if len(content) > 200 else content)
print("-" * 40)
else:
print("❌ prepare-commit-msg hook not found")
print("\n🔧 To install the hook, you can run:")
print(f"handle_setup_hook('{hook_file_path}')")


if __name__ == "__main__":
print("=== Testing Local Git Hooks ===")
test_local_git_hooks()

print("\n" + "=" * 50)
print("=== Testing with Temporary Directory ===")
test_hook_setup_with_missing_directory()