diff --git a/codewiki/src/be/dependency_analyzer/analysis/cloning.py b/codewiki/src/be/dependency_analyzer/analysis/cloning.py index df36942f..1c2994e9 100644 --- a/codewiki/src/be/dependency_analyzer/analysis/cloning.py +++ b/codewiki/src/be/dependency_analyzer/analysis/cloning.py @@ -106,8 +106,8 @@ def clone_repository(github_url: str) -> str: capture_output=True, text=True, ) - except: - pass + except Exception as e: + logger.debug(f"Non-fatal git config step failed: {e}") subprocess.run( [ @@ -158,8 +158,8 @@ def clone_repository(github_url: str) -> str: capture_output=True, text=True, ) - except: - pass + except Exception as e: + logger.debug(f"Non-fatal sparse-checkout setup failed: {e}") return temp_dir except subprocess.TimeoutExpired: if os.path.exists(temp_dir): @@ -178,6 +178,10 @@ def clone_repository(github_url: str) -> str: f"Git executable not found at '{GIT_EXECUTABLE_PATH}'. " "Please ensure Git is installed and the path is correct." ) + except Exception: + if os.path.exists(temp_dir): + cleanup_repository_safe(temp_dir) + raise def cleanup_repository_safe(repo_dir: str) -> bool: diff --git a/codewiki/src/fe/routes.py b/codewiki/src/fe/routes.py index 4750c21c..a431fd57 100644 --- a/codewiki/src/fe/routes.py +++ b/codewiki/src/fe/routes.py @@ -3,6 +3,7 @@ FastAPI route handlers for the CodeWiki web application. """ +import logging import re from datetime import datetime, timedelta from pathlib import Path @@ -22,6 +23,8 @@ from .config import WebAppConfig from codewiki.src.utils import file_manager +logger = logging.getLogger(__name__) + class WebRoutes: """Handles all web routes for the application.""" @@ -132,6 +135,7 @@ async def index_post(self, request: Request, repo_url: str = Form(...), commit_i repo_url = "" # Clear form except Exception as e: + logger.exception("Failed to add repository %s to queue", normalized_repo_url) message = f"Failed to add repository to queue: {str(e)}\n{format_exc()}" message_type = "error" @@ -182,6 +186,9 @@ async def serve_generated_docs(self, job_id: str, filename: str = "overview.md") if not re.match(r'^[A-Za-z0-9_.-]+$', job_id): raise HTTPException(status_code=400, detail="Invalid job ID") + if '..' in filename: + raise HTTPException(status_code=400, detail="Invalid file path") + job = self.background_worker.get_job_status(job_id) docs_path = None repo_url = None @@ -230,7 +237,7 @@ async def serve_generated_docs(self, job_id: str, filename: str = "overview.md") try: module_tree = file_manager.load_json(module_tree_file) except Exception: - pass + logger.exception("Failed to load module tree from %s", module_tree_file) # Load metadata metadata = None @@ -239,12 +246,12 @@ async def serve_generated_docs(self, job_id: str, filename: str = "overview.md") try: metadata = file_manager.load_json(metadata_file) except Exception: - pass + logger.exception("Failed to load metadata from %s", metadata_file) # Serve the requested file docs_path_resolved = docs_path.resolve() file_path = (docs_path / filename).resolve() - if docs_path_resolved != file_path and docs_path_resolved not in file_path.parents: + if not file_path.is_relative_to(docs_path_resolved): raise HTTPException(status_code=400, detail="Invalid file path") if not file_path.exists(): raise HTTPException(status_code=404, detail=f"File {filename} not found") @@ -272,6 +279,7 @@ async def serve_generated_docs(self, job_id: str, filename: str = "overview.md") return HTMLResponse(content=render_template(DOCS_VIEW_TEMPLATE, context)) except Exception as e: + logger.exception("Error reading %s", filename) raise HTTPException(status_code=500, detail=f"Error reading {filename}: {e}\n{format_exc()}") def _normalize_github_url(self, url: str) -> str: @@ -281,6 +289,7 @@ def _normalize_github_url(self, url: str) -> str: repo_info = GitHubRepoProcessor.get_repo_info(url) return f"https://github.com/{repo_info['full_name']}" except Exception: + logger.exception("Failed to normalize GitHub URL %s, falling back to basic normalization", url) # Fallback to basic normalization return url.rstrip('/').lower() @@ -304,3 +313,4 @@ def cleanup_old_jobs(self): for job_id in expired_jobs: if job_id in self.background_worker.job_status: del self.background_worker.job_status[job_id] + diff --git a/codewiki/src/fe/web_app.py b/codewiki/src/fe/web_app.py index 6f5d846b..220fec44 100644 --- a/codewiki/src/fe/web_app.py +++ b/codewiki/src/fe/web_app.py @@ -11,6 +11,7 @@ """ import argparse +import logging from fastapi import FastAPI, Request, Form from fastapi.responses import HTMLResponse @@ -20,6 +21,8 @@ from .config import WebAppConfig +logger = logging.getLogger(__name__) + # Initialize FastAPI app app = FastAPI( title="CodeWiki", @@ -110,11 +113,11 @@ def main(): # Start background worker background_worker.start() - print(f"šŸš€ CodeWiki Web Application starting...") - print(f"🌐 Server running at: http://{args.host}:{args.port}") - print(f"šŸ“ Cache directory: {WebAppConfig.get_absolute_path(WebAppConfig.CACHE_DIR)}") - print(f"šŸ—‚ļø Temp directory: {WebAppConfig.get_absolute_path(WebAppConfig.TEMP_DIR)}") - print("\nPress Ctrl+C to stop the server") + logger.info("šŸš€ CodeWiki Web Application starting...") + logger.info(f"🌐 Server running at: http://{args.host}:{args.port}") + logger.info(f"šŸ“ Cache directory: {WebAppConfig.get_absolute_path(WebAppConfig.CACHE_DIR)}") + logger.info(f"šŸ—‚ļø Temp directory: {WebAppConfig.get_absolute_path(WebAppConfig.TEMP_DIR)}") + logger.info("Press Ctrl+C to stop the server") try: uvicorn.run( @@ -125,9 +128,9 @@ def main(): log_level="debug" if args.debug else "info" ) except KeyboardInterrupt: - print("\nšŸ‘‹ Server stopped") + logger.info("šŸ‘‹ Server stopped") background_worker.stop() if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/test_clustering_forced.py b/test_clustering_forced.py index 6070bffa..9602eede 100644 --- a/test_clustering_forced.py +++ b/test_clustering_forced.py @@ -5,10 +5,13 @@ import os, sys, logging -# Setup logging -logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(message)s', force=True) sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from codewiki.src.be.dependency_analyzer.utils.logging_config import setup_logging + +# Setup logging +setup_logging(level=logging.INFO, format='[%(levelname)s] %(message)s', force=True) + from dotenv import load_dotenv load_dotenv('.env.local')