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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ codewiki generate --create-branch --github-pages --verbose

# Incremental update (only regenerate changed modules since last run)
codewiki generate --update

# Incremental update using a specific commit hash to compare against (useful in CI/CD or squashed PRs)
# This overrides the stored commit hash in metadata.json and implicitly enables --update
codewiki generate --compare-to <commit-hash>
```

### Customization Options
Expand Down
48 changes: 32 additions & 16 deletions codewiki/cli/commands/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def _detect_changed_files(
repo_path: Path,
output_dir: Path,
logger,
verbose: bool
verbose: bool,
compare_to: Optional[str] = None
) -> Optional[List[str]]:
"""
Detect files changed since the last documentation generation.
Expand All @@ -57,21 +58,25 @@ def _detect_changed_files(
"""
import json

metadata_path = output_dir / "metadata.json"
if not metadata_path.exists():
if verbose:
logger.debug("No metadata.json found — cannot detect changes, running full generation.")
return None

try:
metadata = json.loads(metadata_path.read_text())
prev_commit = metadata.get("generation_info", {}).get("commit_id")
if not prev_commit:
prev_commit = None
if compare_to:
prev_commit = compare_to
else:
metadata_path = output_dir / "metadata.json"
if not metadata_path.exists():
if verbose:
logger.debug("No commit_id in metadata — running full generation.")
logger.debug("No metadata.json found — cannot detect changes, running full generation.")
return None

try:
metadata = json.loads(metadata_path.read_text())
prev_commit = metadata.get("generation_info", {}).get("commit_id")
if not prev_commit:
if verbose:
logger.debug("No commit_id in metadata — running full generation.")
return None
except (json.JSONDecodeError, OSError):
return None
except (json.JSONDecodeError, OSError):
return None

# Get current HEAD commit
try:
Expand Down Expand Up @@ -295,6 +300,12 @@ def _find_affected(tree, parent_names=None):
is_flag=True,
help="Incremental update: only regenerate modules affected by changes since last generation",
)
@click.option(
"--compare-to",
type=str,
default=None,
help="Commit hash to compare against for incremental updates (overrides stored commit in metadata.json)",
)
@click.pass_context
def generate_command(
ctx,
Expand All @@ -312,7 +323,8 @@ def generate_command(
max_token_per_module: Optional[int],
max_token_per_leaf_module: Optional[int],
max_depth: Optional[int],
update: bool = False
update: bool = False,
compare_to: Optional[str] = None
):
"""
Generate comprehensive documentation for a code repository.
Expand Down Expand Up @@ -416,10 +428,14 @@ def generate_command(

logger.success(f"Output directory: {output_dir}")

# If a base commit is specified to compare against, implicitly enable update
if compare_to:
update = True

# Incremental update: detect changed files and selectively regenerate
changed_files = None
if update and output_dir.exists():
changed_files = _detect_changed_files(repo_path, output_dir, logger, verbose)
changed_files = _detect_changed_files(repo_path, output_dir, logger, verbose, compare_to=compare_to)
if changed_files is not None and len(changed_files) == 0:
logger.success("No changes detected since last generation. Documentation is up to date.")
sys.exit(EXIT_SUCCESS)
Expand Down