half-orm-dev 1.0.0a21__tar.gz → 1.0.0a22__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-1.0.0a21/half_orm_dev.egg-info → half_orm_dev-1.0.0a22}/PKG-INFO +1 -1
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/main.py +35 -3
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/hgit.py +7 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migration_manager.py +67 -47
- half_orm_dev-1.0.0a22/half_orm_dev/migrations/1/0/0/a20/01_update_gitignore.py +36 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/repo.py +7 -13
- half_orm_dev-1.0.0a22/half_orm_dev/version.txt +1 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22/half_orm_dev.egg-info}/PKG-INFO +1 -1
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev.egg-info/SOURCES.txt +1 -0
- half_orm_dev-1.0.0a21/half_orm_dev/version.txt +0 -1
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/AUTHORS +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/LICENSE +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/README.md +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/__init__.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/bootstrap_manager.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/__init__.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/__init__.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/apply.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/bootstrap.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/check.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/clone.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/init.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/migrate.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/patch.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/release.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/restore.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/revert_migration.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/set_git_origin.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/sync.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/todo.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/undo.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/update.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/upgrade.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli_extension.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/database.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/decorators.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/file_executor.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/17/1/00_move_to_hop.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/17/1/01_txt_to_toml.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/17/4/00_toml_dict_format.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/17/4/01_add_bootstrap_table.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/17/4/02_move_patches_to_subdirs.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/17/5/01_update_pyproject_dependency.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/18/0/00_add_async_support.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/18/0/01_update_default_tests.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/hop/BREAKING_CHANGES-1.0.0.md +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/modules.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/patch_manager.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/patch_validator.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/patches/0/1/0/00_half_orm_meta.database.sql +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/patches/0/1/0/01_alter_half_orm_meta.hop_release.sql +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/patches/0/1/0/02_half_orm_meta.view.hop_penultimate_release.sql +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/patches/log +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/patches/sql/half_orm_meta.sql +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/release_file.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/release_manager.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/scripts/repair-metadata.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/.gitignore +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/MANIFEST.in +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/README +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/conftest_template +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/git-hooks/pre-commit +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/git-hooks/pre-push +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/git-hooks/prepare-commit-msg +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/git-hooks/reference-transaction +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/init_module_template +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/module_template_1 +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/module_template_2 +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/module_template_3 +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/pyproject.toml +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/relation_test +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/sql_adapter +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/warning +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/utils.py +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev.egg-info/dependency_links.txt +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev.egg-info/entry_points.txt +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev.egg-info/requires.txt +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev.egg-info/top_level.txt +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/pyproject.toml +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/setup.cfg +0 -0
- {half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/setup.py +0 -0
|
@@ -133,6 +133,38 @@ def create_cli_group():
|
|
|
133
133
|
cmd.callback = check_version_before_invoke(cmd.callback)
|
|
134
134
|
super().add_command(cmd, name)
|
|
135
135
|
|
|
136
|
+
def get_command(self, ctx, cmd_name):
|
|
137
|
+
cmd = super().get_command(ctx, cmd_name)
|
|
138
|
+
if cmd is not None:
|
|
139
|
+
return cmd
|
|
140
|
+
# Unknown command — show a specific message when migration is needed.
|
|
141
|
+
if hop.repo_checked and hop._Hop__repo.needs_migration():
|
|
142
|
+
from half_orm_dev.utils import hop_version
|
|
143
|
+
installed_version = hop_version()
|
|
144
|
+
config_version = hop._Hop__repo._Repo__config.hop_version
|
|
145
|
+
|
|
146
|
+
@click.command(
|
|
147
|
+
cmd_name,
|
|
148
|
+
context_settings={
|
|
149
|
+
'allow_extra_args': True,
|
|
150
|
+
'ignore_unknown_options': True,
|
|
151
|
+
},
|
|
152
|
+
)
|
|
153
|
+
@click.pass_context
|
|
154
|
+
def _migration_required(ctx):
|
|
155
|
+
click.echo(
|
|
156
|
+
f"\n⚠️ Command '{cmd_name}' is not available: migration required.\n\n"
|
|
157
|
+
f" Repository version: {config_version}\n"
|
|
158
|
+
f" Installed version: {installed_version}\n\n"
|
|
159
|
+
f" Apply migration: half_orm dev migrate\n"
|
|
160
|
+
f" Revert version: pip install half-orm-dev=={config_version}\n",
|
|
161
|
+
err=True,
|
|
162
|
+
)
|
|
163
|
+
sys.exit(1)
|
|
164
|
+
|
|
165
|
+
return _migration_required
|
|
166
|
+
return None
|
|
167
|
+
|
|
136
168
|
@click.group(cls=VersionCheckGroup, invoke_without_command=True)
|
|
137
169
|
@click.pass_context
|
|
138
170
|
def dev(ctx):
|
|
@@ -141,8 +173,8 @@ def create_cli_group():
|
|
|
141
173
|
error = hop.hop_upgrade_error
|
|
142
174
|
required = error.required_version
|
|
143
175
|
installed = error.installed_version
|
|
144
|
-
click.echo(f"\n
|
|
145
|
-
f"(installed
|
|
176
|
+
click.echo(f"\n This repository requires half-orm-dev {required} "
|
|
177
|
+
f"(installed: {installed}).")
|
|
146
178
|
click.echo(f" Installing the required version...")
|
|
147
179
|
try:
|
|
148
180
|
subprocess.run(
|
|
@@ -151,7 +183,7 @@ def create_cli_group():
|
|
|
151
183
|
)
|
|
152
184
|
except subprocess.CalledProcessError:
|
|
153
185
|
click.echo(f"\n Installation failed.", err=True)
|
|
154
|
-
click.echo(f" Run manually
|
|
186
|
+
click.echo(f" Run manually: pip install half-orm-dev=={required}", err=True)
|
|
155
187
|
sys.exit(1)
|
|
156
188
|
click.echo(f" ✓ half-orm-dev {required} installed. Restarting...\n")
|
|
157
189
|
os.execv(sys.argv[0], sys.argv)
|
|
@@ -1471,8 +1471,15 @@ class HGit:
|
|
|
1471
1471
|
is_local = branch in local_release_branches
|
|
1472
1472
|
release_branch_infos.append(get_branch_info(branch, check_stage=True, is_local=is_local))
|
|
1473
1473
|
|
|
1474
|
+
# ho-prod is always active — include it without special treatment.
|
|
1475
|
+
prod_branch_info = None
|
|
1476
|
+
local_prod = self.branch_exists('ho-prod')
|
|
1477
|
+
if local_prod or 'ho-prod' in remote_branch_names:
|
|
1478
|
+
prod_branch_info = get_branch_info('ho-prod', is_local=local_prod)
|
|
1479
|
+
|
|
1474
1480
|
return {
|
|
1475
1481
|
'current_branch': current_branch,
|
|
1482
|
+
'prod_branch': prod_branch_info,
|
|
1476
1483
|
'patch_branches': patch_branch_infos,
|
|
1477
1484
|
'staged_branches': staged_branch_infos,
|
|
1478
1485
|
'release_branches': release_branch_infos
|
|
@@ -10,10 +10,11 @@ Directory structure:
|
|
|
10
10
|
├── log # List of applied migrations (version format)
|
|
11
11
|
└── major/ # Major version
|
|
12
12
|
└── minor/ # Minor version
|
|
13
|
-
└── patch/ # Patch version
|
|
13
|
+
└── patch/ # Patch version (stable migrations here)
|
|
14
14
|
├── 00_migration_name.py
|
|
15
15
|
├── 01_another_migration.py
|
|
16
|
-
└──
|
|
16
|
+
└── a20/ # Pre-release migrations (4th level, PEP 440)
|
|
17
|
+
└── 01_migration_name.py
|
|
17
18
|
|
|
18
19
|
Each migration file must define:
|
|
19
20
|
- migrate(repo): Execute the migration
|
|
@@ -66,75 +67,92 @@ class MigrationManager:
|
|
|
66
67
|
# Path to migrations directory (in half_orm_dev package)
|
|
67
68
|
self._migrations_root = Path(__file__).parent / 'migrations'
|
|
68
69
|
|
|
69
|
-
def _version_to_path(self,
|
|
70
|
+
def _version_to_path(self, version_str: str) -> Path:
|
|
70
71
|
"""
|
|
71
|
-
Convert version
|
|
72
|
+
Convert a version string to its migration directory path.
|
|
73
|
+
|
|
74
|
+
For stable versions (e.g., "0.17.5") returns major/minor/patch/.
|
|
75
|
+
For pre-release versions (e.g., "1.0.0a20") returns major/minor/patch/pre/
|
|
76
|
+
where pre is the pre-release segment (e.g., "a20").
|
|
72
77
|
|
|
73
78
|
Args:
|
|
74
|
-
|
|
79
|
+
version_str: PEP 440 version string
|
|
75
80
|
|
|
76
81
|
Returns:
|
|
77
82
|
Path to migration directory
|
|
78
83
|
"""
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
v = version.parse(version_str)
|
|
85
|
+
major, minor, patch = v.release[:3]
|
|
86
|
+
base = self._migrations_root / str(major) / str(minor) / str(patch)
|
|
87
|
+
if v.pre:
|
|
88
|
+
pre_str = ''.join(str(p) for p in v.pre)
|
|
89
|
+
return base / pre_str
|
|
90
|
+
return base
|
|
81
91
|
|
|
82
92
|
def get_pending_migrations(self, current_version: str, target_version: str) -> List[Tuple[str, Path]]:
|
|
83
93
|
"""
|
|
84
94
|
Get list of migrations that need to be applied.
|
|
85
95
|
|
|
86
96
|
Compares current version (from .hop/config) with target version (from hop_version())
|
|
87
|
-
and returns all migrations in between.
|
|
97
|
+
and returns all migrations in between, sorted by PEP 440 version order.
|
|
98
|
+
|
|
99
|
+
Directory structure:
|
|
100
|
+
migrations/major/minor/patch/ ← stable version scripts
|
|
101
|
+
migrations/major/minor/patch/a20/ ← pre-release scripts (4th level)
|
|
88
102
|
|
|
89
103
|
Args:
|
|
90
|
-
current_version: Current version from .hop/config (e.g., "0.17.0")
|
|
91
|
-
target_version: Target version from hop_version() (e.g., "0.17.1")
|
|
104
|
+
current_version: Current version from .hop/config (e.g., "0.17.0" or "1.0.0-a19")
|
|
105
|
+
target_version: Target version from hop_version() (e.g., "0.17.1" or "1.0.0-a20")
|
|
92
106
|
|
|
93
107
|
Returns:
|
|
94
|
-
List of (version_str, migration_dir_path) tuples in order
|
|
108
|
+
List of (version_str, migration_dir_path) tuples in PEP 440 order
|
|
95
109
|
"""
|
|
96
|
-
current = version.parse(current_version)
|
|
97
|
-
target = version.parse(target_version)
|
|
110
|
+
current = version.parse(current_version)
|
|
111
|
+
target = version.parse(target_version)
|
|
98
112
|
|
|
99
|
-
|
|
113
|
+
candidates = []
|
|
100
114
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
for major in range(0, target[0] + 1):
|
|
104
|
-
major_dir = self._migrations_root / str(major)
|
|
105
|
-
if not major_dir.exists():
|
|
115
|
+
for major_dir in sorted(self._migrations_root.iterdir(), key=lambda p: int(p.name) if p.name.isdigit() else -1):
|
|
116
|
+
if not major_dir.is_dir() or not major_dir.name.isdigit():
|
|
106
117
|
continue
|
|
118
|
+
major = int(major_dir.name)
|
|
107
119
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
minor_dir = major_dir / str(minor)
|
|
111
|
-
if not minor_dir.exists():
|
|
120
|
+
for minor_dir in sorted(major_dir.iterdir(), key=lambda p: int(p.name) if p.name.isdigit() else -1):
|
|
121
|
+
if not minor_dir.is_dir() or not minor_dir.name.isdigit():
|
|
112
122
|
continue
|
|
123
|
+
minor = int(minor_dir.name)
|
|
113
124
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
patch_dir = minor_dir / str(patch)
|
|
117
|
-
if not patch_dir.exists():
|
|
118
|
-
continue
|
|
119
|
-
|
|
120
|
-
version_tuple = (major, minor, patch)
|
|
121
|
-
|
|
122
|
-
# Skip if this version is <= current version
|
|
123
|
-
if version_tuple <= current:
|
|
125
|
+
for patch_dir in sorted(minor_dir.iterdir(), key=lambda p: int(p.name) if p.name.isdigit() else -1):
|
|
126
|
+
if not patch_dir.is_dir() or not patch_dir.name.isdigit():
|
|
124
127
|
continue
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
128
|
+
patch = int(patch_dir.name)
|
|
129
|
+
base_version_str = f"{major}.{minor}.{patch}"
|
|
130
|
+
|
|
131
|
+
# 4th level: pre-release subdirectories (e.g., a20/, b1/, rc2/)
|
|
132
|
+
for pre_dir in sorted(patch_dir.iterdir()):
|
|
133
|
+
if not pre_dir.is_dir() or not re.match(r'^[a-z]+\d+$', pre_dir.name):
|
|
134
|
+
continue
|
|
135
|
+
pre_version_str = f"{base_version_str}{pre_dir.name}"
|
|
136
|
+
try:
|
|
137
|
+
v = version.parse(pre_version_str)
|
|
138
|
+
except Exception:
|
|
139
|
+
continue
|
|
140
|
+
if current < v <= target and list(pre_dir.glob('*.py')):
|
|
141
|
+
candidates.append((pre_version_str, pre_dir))
|
|
142
|
+
|
|
143
|
+
# Stable version scripts at patch level
|
|
144
|
+
stable_files = list(patch_dir.glob('*.py'))
|
|
145
|
+
if stable_files:
|
|
146
|
+
try:
|
|
147
|
+
v = version.parse(base_version_str)
|
|
148
|
+
except Exception:
|
|
149
|
+
continue
|
|
150
|
+
if current < v <= target:
|
|
151
|
+
candidates.append((base_version_str, patch_dir))
|
|
152
|
+
|
|
153
|
+
# Sort by PEP 440 version (pre-releases sort before their stable counterpart)
|
|
154
|
+
candidates.sort(key=lambda x: version.parse(x[0]))
|
|
155
|
+
return candidates
|
|
138
156
|
|
|
139
157
|
def _load_migration_module(self, migration_file: Path):
|
|
140
158
|
"""
|
|
@@ -506,10 +524,12 @@ class MigrationManager:
|
|
|
506
524
|
except Exception:
|
|
507
525
|
return # can't determine status, proceed cautiously
|
|
508
526
|
|
|
527
|
+
prod_info = branches_status.get('prod_branch')
|
|
528
|
+
prod_branches = [prod_info['name']] if prod_info else []
|
|
509
529
|
patch_branches = [b['name'] for b in branches_status.get('patch_branches', [])]
|
|
510
530
|
release_branches = [b['name'] for b in branches_status.get('release_branches', [])]
|
|
511
531
|
# ho-staged/* branches are frozen after merge — excluded from sync checks
|
|
512
|
-
active_branches = release_branches + patch_branches
|
|
532
|
+
active_branches = prod_branches + release_branches + patch_branches
|
|
513
533
|
|
|
514
534
|
blocked = []
|
|
515
535
|
for branch in active_branches:
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Migration 1.0.0a20 — Add production-specific entries to .gitignore
|
|
3
|
+
|
|
4
|
+
Adds .hop/production and .hop/.fetching to .gitignore so that production
|
|
5
|
+
server marker files are not tracked by git.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
GITIGNORE_ENTRIES = ['.hop/production', '.hop/.fetching']
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_description():
|
|
12
|
+
return "Add .hop/production and .hop/.fetching to .gitignore"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def migrate(repo):
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
base_dir = repo._Repo__base_dir
|
|
19
|
+
gitignore_path = Path(base_dir) / '.gitignore'
|
|
20
|
+
|
|
21
|
+
if not gitignore_path.exists():
|
|
22
|
+
return {}
|
|
23
|
+
|
|
24
|
+
content = gitignore_path.read_text()
|
|
25
|
+
lines = content.splitlines()
|
|
26
|
+
missing = [e for e in GITIGNORE_ENTRIES if e not in lines]
|
|
27
|
+
|
|
28
|
+
if not missing:
|
|
29
|
+
return {}
|
|
30
|
+
|
|
31
|
+
with gitignore_path.open('a') as f:
|
|
32
|
+
f.write('\n' + '\n'.join(missing) + '\n')
|
|
33
|
+
|
|
34
|
+
repo.stage_maintenance_file('.gitignore')
|
|
35
|
+
|
|
36
|
+
return {'sync_files': ['.gitignore']}
|
|
@@ -526,6 +526,13 @@ class Repo:
|
|
|
526
526
|
f"Dirty files:\n{status}"
|
|
527
527
|
)
|
|
528
528
|
|
|
529
|
+
# Verify all active branches (including ho-prod) are in sync before
|
|
530
|
+
# switching branches or touching anything.
|
|
531
|
+
try:
|
|
532
|
+
migration_mgr._ensure_active_branches_synced()
|
|
533
|
+
except Exception as e:
|
|
534
|
+
raise RepoError(str(e)) from e
|
|
535
|
+
|
|
529
536
|
# From here, all modifications are made by the migration itself.
|
|
530
537
|
self._migration_running = True
|
|
531
538
|
|
|
@@ -1490,18 +1497,6 @@ class Repo:
|
|
|
1490
1497
|
if action == 'installed' or overall_action == 'skipped':
|
|
1491
1498
|
overall_action = action
|
|
1492
1499
|
|
|
1493
|
-
# Ensure production-specific entries are in .gitignore (idempotent).
|
|
1494
|
-
gitignore_path = Path(self.__base_dir) / '.gitignore'
|
|
1495
|
-
if gitignore_path.exists():
|
|
1496
|
-
content = gitignore_path.read_text()
|
|
1497
|
-
lines = content.splitlines()
|
|
1498
|
-
missing = [e for e in ('.hop/production', '.hop/.fetching')
|
|
1499
|
-
if e not in lines]
|
|
1500
|
-
if missing:
|
|
1501
|
-
with gitignore_path.open('a') as f:
|
|
1502
|
-
f.write('\n' + '\n'.join(missing) + '\n')
|
|
1503
|
-
self.stage_maintenance_file('.gitignore')
|
|
1504
|
-
|
|
1505
1500
|
return {
|
|
1506
1501
|
'installed': any_installed,
|
|
1507
1502
|
'action': overall_action
|
|
@@ -1677,7 +1672,6 @@ class Repo:
|
|
|
1677
1672
|
# 1. Check and update Git hooks
|
|
1678
1673
|
if not dry_run:
|
|
1679
1674
|
result['hooks'] = self.install_git_hooks()
|
|
1680
|
-
self.commit_maintenance_files('update git hooks and .gitignore')
|
|
1681
1675
|
else:
|
|
1682
1676
|
# Dry run: just check if update would be needed
|
|
1683
1677
|
hooks_source_dir = os.path.join(TEMPLATE_DIRS, 'git-hooks')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.0-a22
|
|
@@ -52,6 +52,7 @@ half_orm_dev/migrations/0/17/4/02_move_patches_to_subdirs.py
|
|
|
52
52
|
half_orm_dev/migrations/0/17/5/01_update_pyproject_dependency.py
|
|
53
53
|
half_orm_dev/migrations/0/18/0/00_add_async_support.py
|
|
54
54
|
half_orm_dev/migrations/0/18/0/01_update_default_tests.py
|
|
55
|
+
half_orm_dev/migrations/1/0/0/a20/01_update_gitignore.py
|
|
55
56
|
half_orm_dev/migrations/hop/BREAKING_CHANGES-1.0.0.md
|
|
56
57
|
half_orm_dev/patches/log
|
|
57
58
|
half_orm_dev/patches/0/1/0/00_half_orm_meta.database.sql
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.0.0-a21
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/cli/commands/revert_migration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/17/1/00_move_to_hop.py
RENAMED
|
File without changes
|
{half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/migrations/0/17/1/01_txt_to_toml.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{half_orm_dev-1.0.0a21 → half_orm_dev-1.0.0a22}/half_orm_dev/templates/git-hooks/prepare-commit-msg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|