half-orm-dev 0.17.2a3__tar.gz → 0.17.2a4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {half_orm_dev-0.17.2a3/half_orm_dev.egg-info → half_orm_dev-0.17.2a4}/PKG-INFO +1 -1
- half_orm_dev-0.17.2a4/half_orm_dev/decorators.py +133 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/hgit.py +4 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/migration_manager.py +43 -130
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/patch_manager.py +148 -168
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/release_manager.py +55 -583
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/repo.py +272 -6
- half_orm_dev-0.17.2a4/half_orm_dev/version.txt +1 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4/half_orm_dev.egg-info}/PKG-INFO +1 -1
- half_orm_dev-0.17.2a3/half_orm_dev/decorators.py +0 -54
- half_orm_dev-0.17.2a3/half_orm_dev/version.txt +0 -1
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/AUTHORS +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/LICENSE +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/README.md +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/__init__.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/__init__.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/__init__.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/apply.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/check.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/clone.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/init.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/new.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/patch.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/release.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/restore.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/sync.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/todo.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/undo.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/update.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/commands/upgrade.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli/main.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/cli_extension.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/database.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/migrations/0/17/1/00_move_to_hop.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/migrations/0/17/1/01_txt_to_toml.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/modules.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/patch_validator.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/patches/0/1/0/00_half_orm_meta.database.sql +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/patches/0/1/0/01_alter_half_orm_meta.hop_release.sql +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/patches/0/1/0/02_half_orm_meta.view.hop_penultimate_release.sql +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/patches/log +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/patches/sql/half_orm_meta.sql +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/release_file.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/.gitignore +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/MANIFEST.in +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/Pipfile +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/README +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/conftest_template +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/git-hooks/pre-commit +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/git-hooks/prepare-commit-msg +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/init_module_template +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/module_template_1 +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/module_template_2 +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/module_template_3 +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/pyproject.toml +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/relation_test +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/sql_adapter +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/templates/warning +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev/utils.py +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev.egg-info/SOURCES.txt +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev.egg-info/dependency_links.txt +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev.egg-info/requires.txt +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/half_orm_dev.egg-info/top_level.txt +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/pyproject.toml +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/setup.cfg +0 -0
- {half_orm_dev-0.17.2a3 → half_orm_dev-0.17.2a4}/setup.py +0 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Decorators for half-orm-dev.
|
|
3
|
+
|
|
4
|
+
Provides common decorators for ReleaseManager and PatchManager.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import inspect
|
|
9
|
+
from functools import wraps
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def with_dynamic_branch_lock(branch_getter, timeout_minutes: int = 30):
|
|
13
|
+
"""
|
|
14
|
+
Decorator to protect methods with a dynamic branch lock.
|
|
15
|
+
|
|
16
|
+
Unlike with_branch_lock which uses a static branch name, this decorator
|
|
17
|
+
calls a function to determine the branch name at runtime.
|
|
18
|
+
|
|
19
|
+
IMPORTANT: Automatically syncs .hop/ directory to all other active branches
|
|
20
|
+
after the decorated method completes (from locked branch to all others).
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
branch_getter: Callable that takes (self, *args, **kwargs) and returns branch name
|
|
24
|
+
timeout_minutes: Lock timeout in minutes (default: 30)
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
def _get_release_branch(self, patch_id, *args, **kwargs):
|
|
28
|
+
# Logic to determine release branch from patch_id
|
|
29
|
+
return f"ho-release/{version}"
|
|
30
|
+
|
|
31
|
+
@with_dynamic_branch_lock(_get_release_branch)
|
|
32
|
+
def close_patch(self, patch_id):
|
|
33
|
+
# Will lock the release branch determined by _get_release_branch
|
|
34
|
+
...
|
|
35
|
+
|
|
36
|
+
Notes:
|
|
37
|
+
- branch_getter is called with the same arguments as the decorated function
|
|
38
|
+
- The lock is ALWAYS released in the finally block, even on error
|
|
39
|
+
- After success, .hop/ is automatically synced from locked branch to all others
|
|
40
|
+
"""
|
|
41
|
+
def decorator(func):
|
|
42
|
+
@wraps(func)
|
|
43
|
+
def wrapper(self, *args, **kwargs):
|
|
44
|
+
lock_tag = None
|
|
45
|
+
locked_branch = None
|
|
46
|
+
try:
|
|
47
|
+
# Determine branch name dynamically
|
|
48
|
+
locked_branch = branch_getter(self, *args, **kwargs)
|
|
49
|
+
|
|
50
|
+
# Acquire lock
|
|
51
|
+
lock_tag = self._repo.hgit.acquire_branch_lock(locked_branch, timeout_minutes=timeout_minutes)
|
|
52
|
+
|
|
53
|
+
# Execute the method
|
|
54
|
+
result = func(self, *args, **kwargs)
|
|
55
|
+
|
|
56
|
+
# After success, sync .hop/ from current branch to all other active branches
|
|
57
|
+
try:
|
|
58
|
+
sync_result = self._repo.sync_hop_to_active_branches(
|
|
59
|
+
reason=f"{func.__name__}"
|
|
60
|
+
)
|
|
61
|
+
# Log sync errors but don't fail the operation
|
|
62
|
+
if sync_result.get('errors'):
|
|
63
|
+
for error in sync_result['errors']:
|
|
64
|
+
print(f"Warning: .hop/ sync error: {error}", file=sys.stderr)
|
|
65
|
+
except Exception as e:
|
|
66
|
+
# Don't fail the decorated method if sync fails
|
|
67
|
+
print(f"Warning: Failed to sync .hop/ to active branches: {e}", file=sys.stderr)
|
|
68
|
+
|
|
69
|
+
return result
|
|
70
|
+
finally:
|
|
71
|
+
# Always release lock (even on error)
|
|
72
|
+
if lock_tag:
|
|
73
|
+
self._repo.hgit.release_branch_lock(lock_tag)
|
|
74
|
+
|
|
75
|
+
return wrapper
|
|
76
|
+
return decorator
|
|
77
|
+
|
|
78
|
+
class Node:
|
|
79
|
+
def __init__(self, name):
|
|
80
|
+
self.name = name
|
|
81
|
+
self.children = []
|
|
82
|
+
|
|
83
|
+
class Node:
|
|
84
|
+
def __init__(self, name):
|
|
85
|
+
self.name = name
|
|
86
|
+
self.children = []
|
|
87
|
+
|
|
88
|
+
def print_tree(node, depth=0):
|
|
89
|
+
print(" " * depth + node.name)
|
|
90
|
+
for child in node.children:
|
|
91
|
+
print_tree(child, depth + 1)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def trace_package(package_root: str):
|
|
95
|
+
def decorator(func):
|
|
96
|
+
|
|
97
|
+
def wrapper(*args, **kwargs):
|
|
98
|
+
root = Node(func.__qualname__)
|
|
99
|
+
stack = [root]
|
|
100
|
+
|
|
101
|
+
def tracer(frame, event, arg):
|
|
102
|
+
filename = frame.f_code.co_filename
|
|
103
|
+
|
|
104
|
+
# On garde uniquement les appels venant du package
|
|
105
|
+
if package_root not in filename:
|
|
106
|
+
return tracer
|
|
107
|
+
|
|
108
|
+
if event == 'call':
|
|
109
|
+
name = frame.f_code.co_qualname
|
|
110
|
+
node = Node(name)
|
|
111
|
+
stack[-1].children.append(node)
|
|
112
|
+
stack.append(node)
|
|
113
|
+
|
|
114
|
+
elif event == 'return':
|
|
115
|
+
if len(stack) > 1:
|
|
116
|
+
stack.pop()
|
|
117
|
+
|
|
118
|
+
return tracer
|
|
119
|
+
|
|
120
|
+
sys.settrace(tracer)
|
|
121
|
+
try:
|
|
122
|
+
result = func(*args, **kwargs)
|
|
123
|
+
finally:
|
|
124
|
+
sys.settrace(None)
|
|
125
|
+
|
|
126
|
+
print("\n=== Arbre d'exécution ===")
|
|
127
|
+
print_tree(root)
|
|
128
|
+
print("=========================\n")
|
|
129
|
+
|
|
130
|
+
return result # 🔥 retour normal, aucune modification
|
|
131
|
+
|
|
132
|
+
return wrapper
|
|
133
|
+
return decorator
|
|
@@ -247,6 +247,10 @@ class HGit:
|
|
|
247
247
|
"Proxy to git.add method"
|
|
248
248
|
return self.__git_repo.git.add(*args, **kwargs)
|
|
249
249
|
|
|
250
|
+
def rm(self, *args, **kwargs):
|
|
251
|
+
"Proxy to git.rm method"
|
|
252
|
+
return self.__git_repo.git.rm(*args, **kwargs)
|
|
253
|
+
|
|
250
254
|
def commit(self, *args, **kwargs):
|
|
251
255
|
"Proxy to git.commit method"
|
|
252
256
|
return self.__git_repo.git.commit(*args, **kwargs)
|
|
@@ -234,23 +234,24 @@ class MigrationManager:
|
|
|
234
234
|
return result
|
|
235
235
|
|
|
236
236
|
@with_dynamic_branch_lock(lambda self, *args, **kwargs: 'ho-prod')
|
|
237
|
-
def run_migrations(self, target_version: str, create_commit: bool = True
|
|
237
|
+
def run_migrations(self, target_version: str, create_commit: bool = True) -> Dict:
|
|
238
238
|
"""
|
|
239
239
|
Run all pending migrations up to target version.
|
|
240
240
|
|
|
241
241
|
IMPORTANT: This method acquires a lock on ho-prod branch via decorator.
|
|
242
242
|
Should only be called when on ho-prod branch.
|
|
243
243
|
|
|
244
|
+
After successful completion, the decorator automatically syncs .hop/
|
|
245
|
+
directory to all active branches (ho-patch/*, ho-release/*).
|
|
246
|
+
|
|
244
247
|
Args:
|
|
245
248
|
target_version: Target version string (e.g., "0.17.1")
|
|
246
249
|
create_commit: Whether to create Git commit after migration
|
|
247
|
-
notify_branches: Whether to create empty commits on active branches
|
|
248
250
|
|
|
249
251
|
Returns:
|
|
250
252
|
Dict with migration results including:
|
|
251
253
|
- migrations_applied: List of applied migrations
|
|
252
254
|
- commit_created: Whether migration commit was created
|
|
253
|
-
- notified_branches: List of branches that were notified
|
|
254
255
|
"""
|
|
255
256
|
result = {
|
|
256
257
|
'target_version': target_version,
|
|
@@ -296,28 +297,30 @@ class MigrationManager:
|
|
|
296
297
|
self._repo, '_Repo__config'
|
|
297
298
|
) else "0.0.0"
|
|
298
299
|
|
|
300
|
+
# If already at target version, nothing to do
|
|
301
|
+
if current_version == target_version:
|
|
302
|
+
return result
|
|
303
|
+
|
|
299
304
|
# Get pending migrations
|
|
300
305
|
pending = self.get_pending_migrations(current_version, target_version)
|
|
301
306
|
|
|
302
|
-
if
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
try:
|
|
309
|
-
migration_result = self.apply_migration(version_str, migration_dir)
|
|
310
|
-
result['migrations_applied'].append(migration_result)
|
|
307
|
+
# Apply each migration if there are any
|
|
308
|
+
if pending:
|
|
309
|
+
for version_str, migration_dir in pending:
|
|
310
|
+
try:
|
|
311
|
+
migration_result = self.apply_migration(version_str, migration_dir)
|
|
312
|
+
result['migrations_applied'].append(migration_result)
|
|
311
313
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
314
|
+
except MigrationManagerError as e:
|
|
315
|
+
result['errors'].append(str(e))
|
|
316
|
+
raise
|
|
315
317
|
|
|
316
|
-
# Update hop_version in .hop/config
|
|
318
|
+
# Update hop_version in .hop/config (current_version != target_version)
|
|
319
|
+
# This ensures the version is updated even when upgrading between versions
|
|
320
|
+
# that have no migration scripts (e.g., 0.17.1-a2 → 0.17.2-a3)
|
|
317
321
|
if hasattr(self._repo, '_Repo__config'):
|
|
318
322
|
self._repo._Repo__config.hop_version = target_version
|
|
319
323
|
self._repo._Repo__config.write()
|
|
320
|
-
self._repo.hgit.add(str(Path('.hop') / 'config'))
|
|
321
324
|
|
|
322
325
|
# Create Git commit if requested
|
|
323
326
|
if create_commit and self._repo.hgit:
|
|
@@ -328,32 +331,25 @@ class MigrationManager:
|
|
|
328
331
|
result['migrations_applied']
|
|
329
332
|
)
|
|
330
333
|
|
|
331
|
-
# Commit
|
|
332
|
-
self._repo.
|
|
334
|
+
# Commit and sync to active branches
|
|
335
|
+
sync_result = self._repo.commit_and_sync_to_active_branches(
|
|
336
|
+
message=commit_msg,
|
|
337
|
+
reason=f"migration {current_version} → {target_version}"
|
|
338
|
+
)
|
|
333
339
|
|
|
334
340
|
result['commit_created'] = True
|
|
335
341
|
result['commit_message'] = commit_msg
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
try:
|
|
339
|
-
self._repo.hgit.push()
|
|
340
|
-
result['commit_pushed'] = True
|
|
341
|
-
except Exception as e:
|
|
342
|
-
result['errors'].append(f"Failed to push commit: {e}")
|
|
343
|
-
result['commit_pushed'] = False
|
|
342
|
+
result['commit_pushed'] = True
|
|
343
|
+
result['sync_result'] = sync_result
|
|
344
344
|
|
|
345
345
|
except Exception as e:
|
|
346
346
|
# Don't fail migration if commit fails
|
|
347
347
|
result['errors'].append(f"Failed to create commit: {e}")
|
|
348
348
|
|
|
349
|
-
#
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
result['notified_branches'] = notified
|
|
354
|
-
except Exception as e:
|
|
355
|
-
# Don't fail migration if notification fails
|
|
356
|
-
result['errors'].append(f"Failed to notify branches: {e}")
|
|
349
|
+
# Note: Branch synchronization is now handled automatically by the
|
|
350
|
+
# @with_dynamic_branch_lock decorator when the method completes.
|
|
351
|
+
# The decorator calls repo.sync_hop_to_active_branches() for all
|
|
352
|
+
# operations on ho-prod, ensuring .hop/ is always synced.
|
|
357
353
|
|
|
358
354
|
return result
|
|
359
355
|
|
|
@@ -369,111 +365,28 @@ class MigrationManager:
|
|
|
369
365
|
Args:
|
|
370
366
|
from_version: Starting version
|
|
371
367
|
to_version: Target version
|
|
372
|
-
migrations: List of migration result dicts
|
|
368
|
+
migrations: List of migration result dicts (can be empty)
|
|
373
369
|
|
|
374
370
|
Returns:
|
|
375
371
|
Commit message string
|
|
376
372
|
"""
|
|
377
373
|
lines = [
|
|
378
|
-
f"[HOP] Migration from {from_version} to {to_version}"
|
|
379
|
-
"",
|
|
380
|
-
"Applied migrations:"
|
|
374
|
+
f"[HOP] Migration from {from_version} to {to_version}"
|
|
381
375
|
]
|
|
382
376
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
377
|
+
if migrations:
|
|
378
|
+
lines.append("")
|
|
379
|
+
lines.append("Applied migrations:")
|
|
380
|
+
for migration in migrations:
|
|
381
|
+
version = migration['version']
|
|
382
|
+
files = migration['applied_files']
|
|
383
|
+
lines.append(f" - {version}: {', '.join(files)}")
|
|
384
|
+
else:
|
|
385
|
+
lines.append("")
|
|
386
|
+
lines.append("No migration scripts needed (version update only)")
|
|
387
387
|
|
|
388
388
|
return '\n'.join(lines)
|
|
389
389
|
|
|
390
|
-
def _notify_active_branches(self, from_version: str, to_version: str) -> List[str]:
|
|
391
|
-
"""
|
|
392
|
-
Apply migration to active branches (ho-patch/*, ho-release/*).
|
|
393
|
-
|
|
394
|
-
Applies the same migrations on all active branches, creates commits,
|
|
395
|
-
and pushes them to origin. This prevents merge conflicts when branches
|
|
396
|
-
merge ho-prod later.
|
|
397
|
-
|
|
398
|
-
Args:
|
|
399
|
-
from_version: Starting version
|
|
400
|
-
to_version: Target version
|
|
401
|
-
|
|
402
|
-
Returns:
|
|
403
|
-
List of branch names that were migrated
|
|
404
|
-
"""
|
|
405
|
-
migrated_branches = []
|
|
406
|
-
|
|
407
|
-
# Get active branches from origin using hgit method
|
|
408
|
-
branches_status = self._repo.hgit.get_active_branches_status()
|
|
409
|
-
|
|
410
|
-
# Extract branch names from patch_branches and release_branches
|
|
411
|
-
patch_branches = [b['name'] for b in branches_status.get('patch_branches', [])]
|
|
412
|
-
release_branches = [b['name'] for b in branches_status.get('release_branches', [])]
|
|
413
|
-
|
|
414
|
-
# Combine all active branches (excluding ho-prod)
|
|
415
|
-
active_branches = [b for b in patch_branches + release_branches if b != 'ho-prod']
|
|
416
|
-
|
|
417
|
-
# Current branch (should be ho-prod)
|
|
418
|
-
current_branch = self._repo.hgit.branch
|
|
419
|
-
|
|
420
|
-
# Apply migration on each active branch
|
|
421
|
-
for branch in active_branches:
|
|
422
|
-
try:
|
|
423
|
-
# Checkout branch
|
|
424
|
-
self._repo.hgit.checkout(branch)
|
|
425
|
-
|
|
426
|
-
# Reload config for this branch
|
|
427
|
-
from half_orm_dev.repo import Config
|
|
428
|
-
self._repo._Repo__config = Config(self._repo.base_dir)
|
|
429
|
-
|
|
430
|
-
# Get pending migrations for this branch
|
|
431
|
-
branch_version = self._repo._Repo__config.hop_version
|
|
432
|
-
pending = self.get_pending_migrations(branch_version, to_version)
|
|
433
|
-
|
|
434
|
-
if not pending:
|
|
435
|
-
# Already migrated or no migration needed
|
|
436
|
-
continue
|
|
437
|
-
|
|
438
|
-
# Apply each migration
|
|
439
|
-
for version_str, migration_dir in pending:
|
|
440
|
-
self.apply_migration(version_str, migration_dir)
|
|
441
|
-
|
|
442
|
-
# Update hop_version in .hop/config
|
|
443
|
-
self._repo._Repo__config.hop_version = to_version
|
|
444
|
-
self._repo._Repo__config.write()
|
|
445
|
-
self._repo.hgit.add(Path('.hop') / 'config')
|
|
446
|
-
|
|
447
|
-
# Create commit message
|
|
448
|
-
commit_msg = self._create_migration_commit_message(
|
|
449
|
-
branch_version,
|
|
450
|
-
to_version,
|
|
451
|
-
[{'version': v, 'applied_files': []} for v, _ in pending]
|
|
452
|
-
)
|
|
453
|
-
|
|
454
|
-
# commit the changes added by the script
|
|
455
|
-
self._repo.hgit.commit('-m', commit_msg)
|
|
456
|
-
|
|
457
|
-
# Push the commit
|
|
458
|
-
self._repo.hgit.push_branch(branch)
|
|
459
|
-
|
|
460
|
-
migrated_branches.append(branch)
|
|
461
|
-
|
|
462
|
-
except Exception as e:
|
|
463
|
-
print(f"Warning: Failed to migrate branch {branch}: {e}", file=sys.stderr)
|
|
464
|
-
|
|
465
|
-
# Return to original branch (ho-prod)
|
|
466
|
-
if current_branch:
|
|
467
|
-
try:
|
|
468
|
-
self._repo.hgit.checkout(current_branch)
|
|
469
|
-
# Reload config for original branch
|
|
470
|
-
from half_orm_dev.repo import Config
|
|
471
|
-
self._repo._Repo__config = Config(self._repo.base_dir)
|
|
472
|
-
except Exception:
|
|
473
|
-
pass
|
|
474
|
-
|
|
475
|
-
return migrated_branches
|
|
476
|
-
|
|
477
390
|
def check_migration_needed(self, current_tool_version: str) -> bool:
|
|
478
391
|
"""
|
|
479
392
|
Check if migration is needed.
|