Skip to content

Commit fac9ebd

Browse files
[IMP] Add patches directly in repos.yaml
Appling it without extra command in shell_command_after
1 parent b662f47 commit fac9ebd

File tree

4 files changed

+86
-1
lines changed

4 files changed

+86
-1
lines changed

git_aggregator/config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# © 2015 ACSONE SA/NV
2+
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
23
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)
34

45
import logging
@@ -9,10 +10,21 @@
910

1011
from ._compat import string_types
1112
from .exception import ConfigException
13+
from .patch import Patches
1214

1315
log = logging.getLogger(__name__)
1416

1517

18+
def update_patches(repo_dict, repo_data):
19+
"""Check and update repo_dict with patch files"""
20+
patches_data = repo_data.get("patches")
21+
patches = repo_dict.setdefault("patches", Patches())
22+
if not patches_data:
23+
return
24+
for patch in patches_data:
25+
patches += Patches.prepare_patches(patch, repo_dict.get("cwd"))
26+
27+
1628
def get_repos(config, force=False):
1729
"""Return a :py:obj:`list` list of repos from config file.
1830
:param config: the repos config in :py:class:`dict` format.
@@ -126,6 +138,7 @@ def get_repos(config, force=False):
126138
cmds = [cmds]
127139
commands = cmds
128140
repo_dict['shell_command_after'] = commands
141+
update_patches(repo_dict, repo_data)
129142
repo_list.append(repo_dict)
130143
return repo_list
131144

git_aggregator/patch.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
2+
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)
3+
import logging
4+
import subprocess
5+
from pathlib import Path
6+
7+
from .command import CommandExecutor
8+
9+
logger = logging.getLogger(__name__)
10+
11+
12+
class Patch(CommandExecutor):
13+
is_local = False
14+
15+
def __init__(self, path, cwd):
16+
super().__init__(cwd)
17+
self.path = path
18+
path = Path(path)
19+
if path.exists():
20+
self.is_local = True
21+
22+
def retrive_data(self):
23+
path = self.path
24+
if self.is_local:
25+
patch_path = Path(path).absolute()
26+
path = f"FILE:{str(patch_path)}"
27+
cmd = [
28+
"curl",
29+
path,
30+
]
31+
if logger.getEffectiveLevel() != logging.DEBUG:
32+
cmd.append('-s')
33+
return self.log_call(
34+
cmd,
35+
callwith=subprocess.Popen,
36+
stdout=subprocess.PIPE
37+
)
38+
39+
def apply(self):
40+
res = self.retrive_data()
41+
cmd = [
42+
"git",
43+
"am",
44+
]
45+
if logger.getEffectiveLevel() != logging.DEBUG:
46+
cmd.append('--quiet')
47+
self.log_call(cmd, cwd=self.cwd, stdin=res.stdout)
48+
49+
50+
class Patches(list):
51+
"""List of patches"""
52+
@staticmethod
53+
def prepare_patches(path, cwd):
54+
_path = Path(path)
55+
patches = Patches()
56+
if not _path.exists() or _path.is_file():
57+
patches.append(Patch(path, cwd))
58+
elif _path.is_dir():
59+
for fpath in _path.iterdir():
60+
if fpath.is_file():
61+
patches.append(Patch(str(fpath), cwd))
62+
return patches
63+
64+
def apply(self):
65+
for patch in self:
66+
patch.apply()

git_aggregator/repo.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# © 2015 ACSONE SA/NV
2+
# Copyright 2023 Michael Tietz (MT Software) <mtietz@mt-software.de>
23
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)
34
# Parts of the code comes from ANYBOX
45
# https://github.com/anybox/anybox.recipe.odoo
@@ -37,7 +38,7 @@ class Repo(CommandExecutor):
3738

3839
def __init__(self, cwd, remotes, merges, target,
3940
shell_command_after=None, fetch_all=False, defaults=None,
40-
force=False):
41+
force=False, patches=None):
4142
"""Initialize a git repository aggregator
4243
4344
:param cwd: path to the directory where to initialize the repository
@@ -68,6 +69,7 @@ def __init__(self, cwd, remotes, merges, target,
6869
self.shell_command_after = shell_command_after or []
6970
self.defaults = defaults or dict()
7071
self.force = force
72+
self.patches = patches
7173

7274
@property
7375
def git_version(self):
@@ -173,6 +175,7 @@ def aggregate(self):
173175
self._reset_to(origin["remote"], origin["ref"])
174176
for merge in merges:
175177
self._merge(merge)
178+
self.patches.apply()
176179
self._execute_shell_command_after()
177180
logger.info('End aggregation of %s', self.cwd)
178181

tests/test_config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# © 2015 ACSONE SA/NV
2+
# Copyright 2025 Michael Tietz (MT Software) <mtietz@mt-software.de>
23
# License AGPLv3 (http://www.gnu.org/licenses/agpl-3.0-standalone.html)
34
import os
45
import tempfile
@@ -44,6 +45,7 @@ def test_load(self):
4445
'merges': [{'ref': '8.0', 'remote': 'oca'},
4546
{'ref': 'refs/pull/105/head', 'remote': 'oca'},
4647
{'ref': 'refs/pull/106/head', 'remote': 'oca'}],
48+
'patches': [],
4749
'remotes': [],
4850
'shell_command_after': [],
4951
'target': {'branch': 'aggregated_branch_name',
@@ -91,6 +93,7 @@ def test_load_defaults(self):
9193
'merges': [{'ref': '8.0', 'remote': 'oca', 'depth': 1000},
9294
{'ref': 'refs/pull/105/head', 'remote': 'oca'},
9395
{'ref': 'refs/pull/106/head', 'remote': 'oca'}],
96+
'patches': [],
9497
'remotes': [],
9598
'shell_command_after': [],
9699
'target': {'branch': 'aggregated_branch_name',

0 commit comments

Comments
 (0)