CodeCommunity commited on
Commit
7ac49fd
·
verified ·
1 Parent(s): 3b8737a

Create danger_zone_service.py

Browse files
Files changed (1) hide show
  1. app/services/danger_zone_service.py +86 -0
app/services/danger_zone_service.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+ import shutil
3
+ import logging
4
+ from typing import List, Dict, Any
5
+ from git import Repo
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ class DangerZoneService:
10
+ @staticmethod
11
+ def simulate_destructive_action(
12
+ owner: str,
13
+ repo_name: str,
14
+ action: str,
15
+ target_ref: str,
16
+ current_local_shas: List[str] = None,
17
+ ) -> Dict[str, Any]:
18
+ """
19
+ Clones the repo into an ephemeral temp directory, performs the action,
20
+ and returns what would be lost. The temp dir is always cleaned up.
21
+ """
22
+ temp_dir = tempfile.mkdtemp(prefix="gitgud_danger_")
23
+ repo_url = f"https://github.com/{owner}/{repo_name}.git"
24
+
25
+ try:
26
+ logger.info(f"Cloning {repo_url} into isolation dir for simulation...")
27
+ repo = Repo.clone_from(repo_url, temp_dir, depth=100) # shallow is enough
28
+
29
+ # Record reachable commits before the action
30
+ before_shas = {c.hexsha for c in repo.iter_commits()}
31
+
32
+ # Apply the simulated operation
33
+ if action in ("hard_reset", "force_push"):
34
+ repo.git.reset("--hard", target_ref)
35
+ else:
36
+ # Future-proof: you can add rebase/squash later
37
+ repo.git.reset("--hard", target_ref)
38
+
39
+ after_shas = {c.hexsha for c in repo.iter_commits()}
40
+ lost_shas = before_shas - after_shas
41
+
42
+ would_lose = []
43
+ for sha in lost_shas:
44
+ try:
45
+ commit = repo.commit(sha)
46
+ would_lose.append({
47
+ "id": sha[:7],
48
+ "author": commit.author.name if commit.author else "unknown",
49
+ "message": commit.summary,
50
+ "timestamp": commit.authored_date,
51
+ })
52
+ except Exception:
53
+ continue
54
+
55
+ # Optional: filter only commits that the client currently has locally
56
+ if current_local_shas:
57
+ local_set = set(current_local_shas)
58
+ would_lose = [c for c in would_lose if any(c["id"] in s or s.startswith(c["id"]) for s in local_set)]
59
+
60
+ summary = (
61
+ f"This {action.replace('_', ' ')} will eliminate "
62
+ f"{len(would_lose)} commits from the remote history."
63
+ )
64
+
65
+ return {
66
+ "wouldLose": would_lose,
67
+ "wouldRewrite": [], # extend later for rebase/squash
68
+ "conflicts": [],
69
+ "summary": summary,
70
+ }
71
+
72
+ except Exception as e:
73
+ logger.error(f"Danger zone simulation failed: {e}", exc_info=True)
74
+ return {
75
+ "wouldLose": [],
76
+ "wouldRewrite": [],
77
+ "conflicts": [],
78
+ "summary": f"Simulation failed: {str(e)}",
79
+ "error": str(e),
80
+ }
81
+ finally:
82
+ # Always clean the isolation directory
83
+ try:
84
+ shutil.rmtree(temp_dir, ignore_errors=True)
85
+ except Exception:
86
+ pass