Skip to content

Commit 8cc518f

Browse files
committed
Finalisation du todo: branche Git dans le locking, version Python précise, i18n stats et amélioration ergonomie UI
1 parent 56b7e4e commit 8cc518f

16 files changed

Lines changed: 253 additions & 51 deletions

File tree

Core/Compiler/utils.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,20 @@ def get_interpreter_version(python_path: Optional[str] = None) -> Tuple[int, int
443443
return sys.version_info.major, sys.version_info.minor, sys.version_info.micro
444444

445445

446+
def get_interpreter_version_str(python_path: Optional[str] = None) -> str:
447+
"""
448+
Return Python interpreter version as a string.
449+
450+
Args:
451+
python_path: Path de l'interpréteur (défaut: sys.executable)
452+
453+
Returns:
454+
Version string (ex: "3.10.12")
455+
"""
456+
v = get_interpreter_version(python_path)
457+
return f"{v[0]}.{v[1]}.{v[2]}"
458+
459+
446460
def check_module_available(module_name: str, python_path: Optional[str] = None) -> bool:
447461
"""
448462
Check whether a Python module is available.

Core/Locking/__init__.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,23 @@ def get_git_commit_hash(workspace: Path) -> str | None:
133133
return None
134134

135135

136+
def get_git_branch(workspace: Path) -> str | None:
137+
"""Return the current Git branch of the workspace if available."""
138+
try:
139+
import subprocess
140+
result = subprocess.run(
141+
["git", "rev-parse", "--abbrev-ref", "HEAD"],
142+
cwd=str(workspace),
143+
capture_output=True,
144+
text=True,
145+
timeout=5,
146+
check=True
147+
)
148+
return result.stdout.strip()
149+
except Exception:
150+
return None
151+
152+
136153
def next_build_id(lock_dir: Path) -> str:
137154
from datetime import UTC
138155
today = datetime.now(UTC).strftime("%Y_%m_%d")
@@ -153,6 +170,7 @@ def build_lock_payload(
153170
engine_id: str,
154171
engine_version: str = "unknown",
155172
dependencies: dict[str, str] | None = None,
173+
python_version: str | None = None,
156174
) -> dict[str, Any]:
157175
config = normalize_ark_config(config)
158176
build = config.get("build") or {}
@@ -162,6 +180,7 @@ def build_lock_payload(
162180
lock_dir = workspace / ".ark" / "lock"
163181
build_id = next_build_id(lock_dir)
164182
git_commit = get_git_commit_hash(workspace)
183+
git_branch = get_git_branch(workspace)
165184

166185
return {
167186
"build_id": build_id,
@@ -170,6 +189,7 @@ def build_lock_payload(
170189
"version": project.get("version"),
171190
"entry": project.get("entry"),
172191
"git_commit": git_commit,
192+
"git_branch": git_branch,
173193
},
174194
"workspace": {"exclude_patterns": exclude_patterns},
175195
"build": {
@@ -186,7 +206,7 @@ def build_lock_payload(
186206
"platform": {
187207
"os": sys.platform,
188208
"arch": platform.machine(),
189-
"python_version": platform.python_version(),
209+
"python_version": python_version or platform.python_version(),
190210
},
191211
"dependencies": dependencies or installed_distributions_snapshot(),
192212
"workspace_hash": compute_workspace_hash(workspace, exclude_patterns),
@@ -275,6 +295,8 @@ def build_context_from_lock(lock_payload: dict[str, Any]) -> BuildContext:
275295
"default_lock_path",
276296
"engine_config_path",
277297
"ensure_workspace_layout",
298+
"get_git_branch",
299+
"get_git_commit_hash",
278300
"included_workspace_files",
279301
"installed_distributions_snapshot",
280302
"load_yaml_file",

Ui/Cli/app.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,26 @@ def _build_impl(
9090
if not as_json and verbose:
9191
info(f"Workspace: {workspace}")
9292

93+
# Shared Python version resolution for locking/comparison
94+
python_version = None
95+
try:
96+
from Core.Compiler.utils import get_interpreter_version_str
97+
from Core.Venv_Manager.Manager import VenvManager
98+
# We create a dummy bridge for VenvManager
99+
class DummyBridge:
100+
def __init__(self, ws):
101+
self.workspace_dir = ws
102+
self.use_system_python = False
103+
vm = VenvManager(DummyBridge(str(workspace)))
104+
vpython = vm.resolve_existing_venv()
105+
if vpython:
106+
vpath = vm.python_path(vpython)
107+
python_version = get_interpreter_version_str(vpath)
108+
else:
109+
python_version = get_interpreter_version_str()
110+
except Exception:
111+
pass
112+
93113
if lock_file is None:
94114
if not as_json and verbose:
95115
info("Loading ark.yml...")
@@ -102,9 +122,13 @@ def _build_impl(
102122

103123
if not as_json and verbose:
104124
info(f"Generating lock payload for engine '{engine_id}'...")
125+
105126
# Point 3 alignment: build_lock_payload now correctly loads engine config via fixed path
106127
lock_payload = build_lock_payload(
107-
workspace, validated.config, engine_id=engine_id
128+
workspace,
129+
validated.config,
130+
engine_id=engine_id,
131+
python_version=python_version,
108132
)
109133
if not as_json and verbose:
110134
info("Writing lock files...")
@@ -204,6 +228,7 @@ def _build_impl(
204228
workspace,
205229
validated.config,
206230
engine_id=str(validated.config["build"]["engine"]),
231+
python_version=python_version,
207232
)
208233
rebuild_cache = cache_rebuild_lock(workspace, regenerated)
209234
comparison = compare_lock_payloads(lock_payload, regenerated)

Ui/Cli/helpers.py

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -354,12 +354,14 @@ def build_lock_payload(
354354
config: dict[str, Any],
355355
*,
356356
engine_id: str,
357+
python_version: str | None = None,
357358
) -> dict[str, Any]:
358359
return _build_lock_payload(
359360
workspace,
360361
config,
361362
engine_id=engine_id,
362363
engine_version=engine_version(engine_id),
364+
python_version=python_version,
363365
)
364366

365367

@@ -407,15 +409,22 @@ def engine_config_from_lock(lock_payload: dict[str, Any]) -> dict[str, Any]:
407409

408410

409411
def ensure_correct_git_commit(workspace: Path, lock_payload: dict[str, Any]) -> bool:
410-
"""Vérifie si le commit Git actuel correspond à celui du verrou."""
411-
locked_commit = ((lock_payload.get("project") or {}).get("git_commit"))
412-
if not locked_commit:
412+
"""Vérifie si le commit et la branche Git actuels correspondent à ceux du verrou."""
413+
project = lock_payload.get("project") or {}
414+
locked_commit = project.get("git_commit")
415+
locked_branch = project.get("git_branch")
416+
417+
if not locked_commit and not locked_branch:
413418
return True
414419

415-
from Core.Locking import get_git_commit_hash
420+
from Core.Locking import get_git_commit_hash, get_git_branch
416421
current_commit = get_git_commit_hash(workspace)
422+
current_branch = get_git_branch(workspace)
423+
424+
commit_match = (not locked_commit) or (current_commit == locked_commit)
425+
branch_match = (not locked_branch) or (current_branch == locked_branch)
417426

418-
if not current_commit or current_commit == locked_commit:
427+
if commit_match and branch_match:
419428
return True
420429

421430
from .output import warn, info, error, success
@@ -425,26 +434,46 @@ def ensure_correct_git_commit(workspace: Path, lock_payload: dict[str, Any]) ->
425434
is_linux = platform.system().lower() == "linux"
426435

427436
warn(f"Mismatch Git détecté.")
428-
info(f" - Verrou : {locked_commit[:8]}")
429-
info(f" - Actuel : {current_commit[:8]}")
437+
if not branch_match:
438+
info(f" - Branche Verrou : {locked_branch}")
439+
info(f" - Branche Actuelle : {current_branch}")
440+
if not commit_match:
441+
info(f" - Commit Verrou : {locked_commit[:8] if locked_commit else 'N/A'}")
442+
info(f" - Commit Actuel : {current_commit[:8] if current_commit else 'N/A'}")
430443

431444
if is_linux:
432445
try:
433446
import click
434-
if click.confirm(f"Effectuer un 'git checkout {locked_commit[:8]}' automatique ?", default=True):
435-
info(f"Alignement Git en cours...")
436-
subprocess.run(["git", "checkout", locked_commit], cwd=str(workspace), check=True)
447+
if not branch_match and locked_branch:
448+
if click.confirm(f"Effectuer un 'git checkout {locked_branch}' automatique ?", default=True):
449+
info(f"Changement de branche en cours...")
450+
subprocess.run(["git", "checkout", locked_branch], cwd=str(workspace), check=True)
451+
# Re-verify commit after branch change
452+
current_commit = get_git_commit_hash(workspace)
453+
commit_match = (not locked_commit) or (current_commit == locked_commit)
454+
455+
if not commit_match and locked_commit:
456+
if click.confirm(f"Effectuer un 'git checkout {locked_commit[:8]}' automatique ?", default=True):
457+
info(f"Alignement du commit en cours...")
458+
subprocess.run(["git", "checkout", locked_commit], cwd=str(workspace), check=True)
459+
success("Workspace aligné.")
460+
return True
461+
462+
if commit_match and branch_match:
437463
success("Workspace aligné.")
438464
return True
439465
else:
440466
warn("Build avec mismatch (non recommandé).")
441467
return True
442468
except Exception as e:
443-
error(f"Échec checkout : {e}")
469+
error(f"Échec alignement Git : {e}")
444470
return False
445471
else:
446-
warn("Checkout automatique non supporté sur cette plateforme.")
447-
info(f"Action manuelle requise : git checkout {locked_commit}")
472+
warn("Alignement automatique non supporté sur cette plateforme.")
473+
if not branch_match and locked_branch:
474+
info(f"Action manuelle requise : git checkout {locked_branch}")
475+
if not commit_match and locked_commit:
476+
info(f"Action manuelle requise : git checkout {locked_commit}")
448477
try:
449478
import click
450479
return click.confirm("Continuer quand même ?", default=False)

Ui/Gui/Dialogs/CompilerDialog.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,27 @@ def _t(fr: str, en: str) -> str:
235235
"🔒 Génération du verrou de compilation (lock file)...",
236236
"🔒 Generating build lock file...",
237237
)
238+
239+
# Resolve Python version for locking
240+
python_version = None
241+
try:
242+
from Core.Compiler.utils import get_interpreter_version_str
243+
from Core.Venv_Manager.Manager import VenvManager
244+
vm = VenvManager(self)
245+
vpython = vm.resolve_project_venv()
246+
if vpython:
247+
vpath = vm.python_path(vpython)
248+
python_version = get_interpreter_version_str(vpath)
249+
else:
250+
python_version = get_interpreter_version_str()
251+
except Exception:
252+
pass
253+
238254
lock_payload = build_lock_payload(
239-
Path(self.workspace_dir), validated.config, engine_id=engine_id
255+
Path(self.workspace_dir),
256+
validated.config,
257+
engine_id=engine_id,
258+
python_version=python_version,
240259
)
241260
write_lock_files(Path(self.workspace_dir), lock_payload)
242261

Ui/Gui/Dialogs/LockDialog.py

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -164,46 +164,75 @@ def _do_rebuild(self):
164164
QMessageBox.critical(self, "Error", "rebuild_from_lock method not implemented in GUI")
165165

166166
def _ensure_git_alignment(self, lock_payload: dict) -> bool:
167-
locked_commit = (lock_payload.get("project") or {}).get("git_commit")
168-
if not locked_commit:
167+
project = lock_payload.get("project") or {}
168+
locked_commit = project.get("git_commit")
169+
locked_branch = project.get("git_branch")
170+
171+
if not locked_commit and not locked_branch:
169172
return True
170173

171-
from Core.Locking import get_git_commit_hash
174+
from Core.Locking import get_git_commit_hash, get_git_branch
172175
ws = getattr(self.gui, "workspace_dir", None)
173176
if not ws:
174177
return True
175178

176179
current_commit = get_git_commit_hash(Path(ws))
177-
if not current_commit or current_commit == locked_commit:
180+
current_branch = get_git_branch(Path(ws))
181+
182+
commit_match = (not locked_commit) or (current_commit == locked_commit)
183+
branch_match = (not locked_branch) or (current_branch == locked_branch)
184+
185+
if commit_match and branch_match:
178186
return True
179187

180188
import platform
181189
import subprocess
182190
is_linux = platform.system().lower() == "linux"
183191

192+
lines = []
193+
if not branch_match:
194+
lines.append(self.gui.tr(
195+
f"Branche : actuelle={current_branch}, verrou={locked_branch}",
196+
f"Branch: current={current_branch}, lock={locked_branch}"
197+
))
198+
if not commit_match:
199+
lines.append(self.gui.tr(
200+
f"Commit : actuel={current_commit[:8] if current_commit else 'N/A'}, verrou={locked_commit[:8] if locked_commit else 'N/A'}",
201+
f"Commit: current={current_commit[:8] if current_commit else 'N/A'}, lock={locked_commit[:8] if locked_commit else 'N/A'}"
202+
))
203+
184204
msg = self.gui.tr(
185-
f"Le commit Git actuel ({current_commit[:8]}) ne correspond pas à celui du verrou ({locked_commit[:8]}).\n\n",
186-
f"Current Git commit ({current_commit[:8]}) does not match lock file ({locked_commit[:8]}).\n\n"
187-
)
205+
"Désalignement Git détecté :\n",
206+
"Git mismatch detected:\n"
207+
) + "\n".join(lines) + "\n\n"
188208

189209
if is_linux:
190210
msg += self.gui.tr(
191-
"Voulez-vous que ARK effectue un 'git checkout' automatique pour aligner le code ?",
192-
"Do you want ARK to perform an automatic 'git checkout' to align the code?"
211+
"Voulez-vous que ARK tente d'aligner automatiquement le code (git checkout) ?",
212+
"Do you want ARK to attempt automatic code alignment (git checkout)?"
193213
)
194214
ans = QMessageBox.question(self, "Git Mismatch", msg, QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel)
195215
if ans == QMessageBox.Yes:
196216
try:
197-
subprocess.run(["git", "checkout", locked_commit], cwd=ws, check=True)
217+
if not branch_match and locked_branch:
218+
subprocess.run(["git", "checkout", locked_branch], cwd=ws, check=True)
219+
if not commit_match and locked_commit:
220+
subprocess.run(["git", "checkout", locked_commit], cwd=ws, check=True)
198221
return True
199222
except Exception as e:
200-
QMessageBox.critical(self, "Error", f"Échec du checkout : {e}")
223+
QMessageBox.critical(self, "Error", f"Échec de l'alignement : {e}")
201224
return False
202225
return ans == QMessageBox.No # True si l'user ignore, False si Cancel
203226
else:
227+
cmd_hint = ""
228+
if not branch_match and locked_branch:
229+
cmd_hint += f"git checkout {locked_branch}\n"
230+
if not commit_match and locked_commit:
231+
cmd_hint += f"git checkout {locked_commit[:8]}\n"
232+
204233
msg += self.gui.tr(
205-
f"Action recommandée : exécutez 'git checkout {locked_commit}' manuellement avant de continuer.\n\nContinuer le build quand même ?",
206-
f"Recommended action: run 'git checkout {locked_commit}' manually before continuing.\n\nContinue build anyway?"
234+
f"Action manuelle recommandée :\n{cmd_hint}\nContinuer le build quand même ?",
235+
f"Recommended manual action:\n{cmd_hint}\nContinue build anyway?"
207236
)
208237
ans = QMessageBox.warning(self, "Git Mismatch", msg, QMessageBox.Yes | QMessageBox.No)
209238
return ans == QMessageBox.Yes

0 commit comments

Comments
 (0)