git-filter-repo/t/t9391/splice_repos.py
Elijah Newren 805ce360fa filter-repo: simplify API for parent handling in Commit object
While the underlying fast-export and fast-import streams explicitly
separate 'from' commit (first parent) and 'merge' commits (all other
parents), foisting that separation into the Commit object for
filter-repo forces additional places in the code to deal with that
distinction.  It results in less clear code, and especially does not
make sense to push upon folks who may want to use filter-repo as a
library.

Signed-off-by: Elijah Newren <newren@gmail.com>
2019-04-29 09:56:38 -07:00

85 lines
2.6 KiB
Python
Executable File

#!/usr/bin/env python
"""
Please see the
***** API BACKWARD COMPATIBILITY CAVEAT *****
near the top of git-filter-repo.
Also, note that splicing repos may need some special care as fast-export
only shows the files that changed relative to the first parent, so there
may be gotchas if you are to splice near merge commits; this example does
not try to handle any such special cases.
"""
import re
import sys
import git_filter_repo as fr
class InterleaveRepositories:
def __init__(self, repo1, repo2, output_dir):
self.repo1 = repo1
self.repo2 = repo2
self.output_dir = output_dir
self.commit_map = {}
self.last_commit = None
def skip_reset(self, reset):
reset.skip()
def hold_commit(self, commit):
commit.skip(new_id = commit.id)
letter = re.match('Commit (.)', commit.message).group(1)
self.commit_map[letter] = commit
def weave_commit(self, commit):
letter = re.match('Commit (.)', commit.message).group(1)
prev_letter = chr(ord(letter)-1)
# Splice in any extra commits needed
if prev_letter in self.commit_map:
new_commit = self.commit_map[prev_letter]
new_commit.parents = [self.last_commit] if self.last_commit else []
new_commit.dump(self.out._output)
commit.parents = [new_commit.id]
# Dump our commit now
commit.dump(self.out._output)
# Make sure that commits that depended on new_commit.id will now depend
# on commit.id
if prev_letter in self.commit_map:
self.last_commit = commit.id
fr.record_id_rename(new_commit.id, commit.id)
def run(self):
blob = fr.Blob('public gpg key contents')
tag = fr.Tag('gpg-pubkey', blob.id,
'Ima Tagger', 'ima@tagg.er', '1136199845 +0300',
'Very important explanation and stuff')
args = fr.FilteringOptions.parse_args(['--target', self.output_dir])
out = fr.RepoFilter(args)
out.importer_only()
self.out = out
i1args = fr.FilteringOptions.parse_args(['--source', self.repo1])
i1 = fr.RepoFilter(i1args,
reset_callback = lambda r: self.skip_reset(r),
commit_callback = lambda c: self.hold_commit(c))
i1.set_output(out)
i1.run()
i2args = fr.FilteringOptions.parse_args(['--source', self.repo2])
i2 = fr.RepoFilter(i2args,
commit_callback = lambda c: self.weave_commit(c))
i2.set_output(out)
i2.run()
blob.dump(out._output)
tag.dump(out._output)
out.finish()
splicer = InterleaveRepositories(sys.argv[1], sys.argv[2], sys.argv[3])
splicer.run()