Skip to content

Commit bd3e574

Browse files
janverbTom Blauwendraat
authored and
Tom Blauwendraat
committed
Support specifying a pin for merges
1 parent 1fa89fe commit bd3e574

File tree

4 files changed

+82
-9
lines changed

4 files changed

+82
-9
lines changed

git_aggregator/config.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,23 @@ def get_repos(config, force=False):
5757
try:
5858
# Assume parts is a str
5959
parts = merge.split(' ')
60-
if len(parts) != 2:
60+
if len(parts) not in {2, 3}:
6161
raise ConfigException(
6262
'%s: Merge must be formatted as '
63-
'"remote_name ref".' % directory)
63+
'"remote_name ref [pin]".' % directory)
6464
merge = {
6565
"remote": parts[0],
6666
"ref": parts[1],
6767
}
68+
if len(parts) == 3:
69+
merge["pin"] = parts[2]
6870
except AttributeError:
6971
# Parts is a dict
7072
try:
7173
merge["remote"] = str(merge["remote"])
7274
merge["ref"] = str(merge["ref"])
75+
if merge.get("pin"):
76+
merge["pin"] = str(merge["pin"])
7377
except KeyError:
7478
raise ConfigException(
7579
'%s: Merge lacks mandatory '

git_aggregator/repo.py

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,26 @@ def fetch(self):
242242
basecmd = ("git", "fetch")
243243
logger.info("Fetching required remotes")
244244
for merge in self.merges:
245+
pin = remote.get("pin")
245246
cmd = basecmd + self._fetch_options(merge) + (merge["remote"],)
246247
if merge["remote"] not in self.fetch_all:
248+
if pin:
249+
# Probably solvable, but a little too tricky for me to
250+
# figure out right now
251+
raise GitAggregatorException(
252+
"Cannot use fetch_all with pin"
253+
)
247254
cmd += (merge["ref"],)
255+
merge["pin"] = pin
248256
self.log_call(cmd, cwd=self.cwd)
249257

258+
def rev_parse(self, ref):
259+
return self.log_call(
260+
["git", "rev-parse", "--verify", ref],
261+
callwith=subprocess.check_output,
262+
cwd=self.cwd,
263+
).strip()
264+
250265
def push(self):
251266
remote = self.target['remote']
252267
branch = self.target['branch']
@@ -295,15 +310,19 @@ def _reset_to(self, remote, ref):
295310
def _switch_to_branch(self, branch_name):
296311
# check if the branch already exists
297312
logger.info("Switch to branch %s", branch_name)
298-
self.log_call(['git', 'checkout', '-B', branch_name], cwd=self.cwd)
313+
cmd = ['git', 'checkout', '-B', branch_name]
314+
if ref is not None:
315+
cmd.append(self.rev_parse(ref))
316+
self.log_call(cmd, cwd=self.cwd)
299317

300318
def _execute_shell_command_after(self):
301319
logger.info('Execute shell after commands')
302320
for cmd in self.shell_command_after:
303321
self.log_call(cmd, shell=True, cwd=self.cwd)
304322

305323
def _merge(self, merge):
306-
logger.info("Pull %s, %s", merge["remote"], merge["ref"])
324+
pin = merge.get("pin")
325+
logger.info("Pull %s, %s, %s", merge["remote"], merge["ref"], pin or "no pin")
307326
cmd = ("git", "pull", "--ff", "--no-rebase")
308327
if self.git_version >= (1, 7, 10):
309328
# --edit and --no-edit appear with Git 1.7.10
@@ -312,7 +331,10 @@ def _merge(self, merge):
312331
cmd += ('--no-edit',)
313332
if logger.getEffectiveLevel() != logging.DEBUG:
314333
cmd += ('--quiet',)
315-
cmd += self._fetch_options(merge) + (merge["remote"], merge["ref"])
334+
if pin:
335+
cmd += self._fetch_options(merge) + (merge["remote"], pin)
336+
else:
337+
cmd += self._fetch_options(merge) + (merge["remote"], merge["ref"])
316338
self.log_call(cmd, cwd=self.cwd)
317339

318340
def _get_remotes(self):

tests/test_config.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_load(self):
2828
merges:
2929
- oca 8.0
3030
- oca refs/pull/105/head
31-
- oca refs/pull/106/head
31+
- oca refs/pull/106/head 1234abcd
3232
target: acsone aggregated_branch_name
3333
"""
3434
repos = config.get_repos(self._parse_config(config_yaml))
@@ -45,7 +45,8 @@ def test_load(self):
4545
'defaults': {},
4646
'merges': [{'ref': '8.0', 'remote': 'oca'},
4747
{'ref': 'refs/pull/105/head', 'remote': 'oca'},
48-
{'ref': 'refs/pull/106/head', 'remote': 'oca'}],
48+
{'ref': 'refs/pull/106/head', 'remote': 'oca',
49+
'pin': '1234abcd'}],
4950
'remotes': [],
5051
'shell_command_after': [],
5152
'target': {'branch': 'aggregated_branch_name',
@@ -76,6 +77,7 @@ def test_load_defaults(self):
7677
-
7778
remote: oca
7879
ref: refs/pull/106/head
80+
pin: 1234abcd
7981
target: acsone aggregated_branch_name
8082
""")
8183
repos = config.get_repos(self._parse_config(config_yaml))
@@ -92,7 +94,8 @@ def test_load_defaults(self):
9294
'defaults': {'depth': 1},
9395
'merges': [{'ref': '8.0', 'remote': 'oca', 'depth': 1000},
9496
{'ref': 'refs/pull/105/head', 'remote': 'oca'},
95-
{'ref': 'refs/pull/106/head', 'remote': 'oca'}],
97+
{'ref': 'refs/pull/106/head', 'remote': 'oca',
98+
'pin': '1234abcd'}],
9699
'remotes': [],
97100
'shell_command_after': [],
98101
'target': {'branch': 'aggregated_branch_name',
@@ -202,7 +205,7 @@ def test_load_merges_exception(self):
202205
self.assertEqual(
203206
ex.exception.args[0],
204207
'/product_attribute: Merge must be formatted as '
205-
'"remote_name ref".')
208+
'"remote_name ref [pin]".')
206209
config_yaml = """
207210
/product_attribute:
208211
remotes:

tests/test_repo.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,47 @@ def test_multithreading(self):
399399

400400
self.assertTrue(os.path.isfile(os.path.join(repo3_dir, 'tracked')))
401401
self.assertTrue(os.path.isfile(os.path.join(repo3_dir, 'tracked2')))
402+
403+
def test_pinned_base(self):
404+
remotes = [{
405+
'name': 'r1',
406+
'url': self.url_remote1
407+
}]
408+
merges = [{
409+
'remote': 'r1',
410+
'ref': 'master',
411+
'pin': self.commit_1_sha[:8]
412+
}]
413+
target = {
414+
'remote': 'r1',
415+
'branch': 'agg1'
416+
}
417+
repo = Repo(self.cwd, remotes, merges, target)
418+
repo.aggregate()
419+
last_rev = git_get_last_rev(self.cwd)
420+
self.assertEqual(last_rev, self.commit_1_sha)
421+
422+
def test_pinned_merge(self):
423+
remotes = [{
424+
'name': 'r1',
425+
'url': self.url_remote1
426+
}, {
427+
'name': 'r2',
428+
'url': self.url_remote2
429+
}]
430+
merges = [{
431+
'remote': 'r1',
432+
'ref': 'tag2'
433+
}, {
434+
'remote': 'r2',
435+
'ref': self.commit_3_sha,
436+
'pin': self.commit_1_sha[:8]
437+
}]
438+
target = {
439+
'remote': 'r1',
440+
'branch': 'agg'
441+
}
442+
repo = Repo(self.cwd, remotes, merges, target)
443+
repo.aggregate()
444+
last_rev = git_get_last_rev(self.cwd)
445+
self.assertEqual(last_rev, self.commit_2_sha)

0 commit comments

Comments
 (0)