mirror of
https://github.com/newren/git-filter-repo.git
synced 2024-07-04 01:15:41 +02:00
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>
This commit is contained in:
parent
bec6bd8d3c
commit
805ce360fa
|
@ -569,8 +569,7 @@ class Commit(_GitElementWithId):
|
|||
committer_name, committer_email, committer_date,
|
||||
message,
|
||||
file_changes,
|
||||
from_commit = None,
|
||||
merge_commits = [],
|
||||
parents,
|
||||
original_id = None,
|
||||
**kwargs):
|
||||
_GitElementWithId.__init__(self)
|
||||
|
@ -609,12 +608,7 @@ class Commit(_GitElementWithId):
|
|||
# are also represented as git elements
|
||||
self.file_changes = file_changes
|
||||
|
||||
# Record the commit to initialize this branch from. This revision will be
|
||||
# the first parent of the new commit
|
||||
self.from_commit = from_commit
|
||||
|
||||
# Record additional parent commits
|
||||
self.merge_commits = merge_commits
|
||||
self.parents = parents
|
||||
|
||||
def dump(self, file_):
|
||||
"""
|
||||
|
@ -625,7 +619,7 @@ class Commit(_GitElementWithId):
|
|||
# Make output to fast-import slightly easier for humans to read if the
|
||||
# message has no trailing newline of its own; cosmetic, but a nice touch...
|
||||
extra_newline = '\n'
|
||||
if self.message.endswith('\n') or not (self.from_commit or self.file_changes):
|
||||
if self.message.endswith('\n') or not (self.parents or self.file_changes):
|
||||
extra_newline = ''
|
||||
|
||||
file_.write(('commit {}\n'
|
||||
|
@ -640,37 +634,24 @@ class Commit(_GitElementWithId):
|
|||
len(self.message), self.message,
|
||||
extra_newline)
|
||||
)
|
||||
if self.from_commit:
|
||||
mark = ':' if isinstance(self.from_commit, int) else ''
|
||||
file_.write('from {}{}\n'.format(mark, self.from_commit))
|
||||
for ref in self.merge_commits:
|
||||
mark = ':' if isinstance(ref, int) else ''
|
||||
file_.write('merge {}{}\n'.format(mark, ref))
|
||||
for i, parent in enumerate(self.parents):
|
||||
mark = ':' if isinstance(parent, int) else ''
|
||||
file_.write('from ' if i==0 else 'merge ')
|
||||
file_.write('{}{}\n'.format(mark, parent))
|
||||
for change in self.file_changes:
|
||||
change.dump(file_)
|
||||
if not self.from_commit and not self.file_changes:
|
||||
if not self.parents and not self.file_changes:
|
||||
# Workaround a bug in pre-git-2.22 versions of fast-import with
|
||||
# the get-mark directive.
|
||||
file_.write('\n')
|
||||
file_.write('\n')
|
||||
|
||||
def get_parents(self):
|
||||
"""
|
||||
Return all parent commits
|
||||
"""
|
||||
my_parents = []
|
||||
if self.from_commit:
|
||||
my_parents.append(self.from_commit)
|
||||
my_parents += self.merge_commits
|
||||
return my_parents
|
||||
|
||||
def first_parent(self):
|
||||
"""
|
||||
Return first parent commit
|
||||
"""
|
||||
my_parents = self.get_parents()
|
||||
if my_parents:
|
||||
return my_parents[0]
|
||||
if self.parents:
|
||||
return self.parents[0]
|
||||
return None
|
||||
|
||||
def skip(self, new_id=None):
|
||||
|
@ -1209,11 +1190,8 @@ class FastExportFilter(object):
|
|||
[x in _SKIPPED_COMMITS for x in orig_parents])
|
||||
tmp2 = [x for x in tmp if x[0] is not None]
|
||||
if not tmp2:
|
||||
# All ancestors have been pruned; we have no parents. Note that the
|
||||
# way fast-export/fast-import split parents into from_commit and
|
||||
# merge_commits means we'd rather a parentless commit be represented
|
||||
# as a list containing a single None entry.
|
||||
return [None], None
|
||||
# All ancestors have been pruned; we have no parents.
|
||||
return [], None
|
||||
parents, orig_parents, is_rewritten = [list(x) for x in zip(*tmp2)]
|
||||
|
||||
# We can't have redundant parents if we don't have at least 2 parents
|
||||
|
@ -1268,9 +1246,7 @@ class FastExportFilter(object):
|
|||
return parents, None
|
||||
|
||||
def prunable(self, commit, new_1st_parent, had_file_changes, orig_parents):
|
||||
parents = [commit.from_commit] + commit.merge_commits
|
||||
if not commit.from_commit:
|
||||
parents = []
|
||||
parents = commit.parents
|
||||
|
||||
# For merge commits, unless there are prunable (redundant) parents, we
|
||||
# do not want to prune
|
||||
|
@ -1334,8 +1310,7 @@ class FastExportFilter(object):
|
|||
# the rest. But I'm worried about fast-import blocking on fi_output
|
||||
# buffers filling up so I instead read from it as I go.
|
||||
for change in commit.file_changes:
|
||||
parent = new_1st_parent or commit.from_commit
|
||||
assert parent # Should be good based on the checks above
|
||||
parent = new_1st_parent or commit.parents[0] # exists due to above checks
|
||||
self._output.write("ls :{} {}\n".format(parent, change.filename))
|
||||
self._output.flush()
|
||||
parent_version = fi_output.readline().split()
|
||||
|
@ -1368,7 +1343,7 @@ class FastExportFilter(object):
|
|||
self._flush_renames(None, limit=40)
|
||||
# Also, record if this was a merge commit that turned into a non-merge
|
||||
# commit.
|
||||
if len(orig_parents) >= 2 and not commit.merge_commits:
|
||||
if len(orig_parents) >= 2 and len(commit.parents) < 2:
|
||||
self._commits_no_longer_merges.append((commit.original_id, new_id))
|
||||
|
||||
def num_commits_parsed(self):
|
||||
|
@ -1413,13 +1388,16 @@ class FastExportFilter(object):
|
|||
pinfo.append(self._parse_optional_parent_ref('merge'))
|
||||
orig_parents, parents = [list(tmp) for tmp in zip(*pinfo)]
|
||||
|
||||
# Prune parents (due to pruning of empty commits) if relevant
|
||||
parents, new_1st_parent = self.trim_extra_parents(orig_parents, parents)
|
||||
from_commit = parents[0]
|
||||
merge_commits = parents[1:]
|
||||
# No parents is oddly represented as [None] instead of [], due to the
|
||||
# special 'from' handling. Convert it here to a more canonical form.
|
||||
if parents == [None]:
|
||||
parents = []
|
||||
if orig_parents == [None]:
|
||||
orig_parents = []
|
||||
|
||||
# Prune parents (due to pruning of empty commits) if relevant
|
||||
parents, new_1st_parent = self.trim_extra_parents(orig_parents, parents)
|
||||
|
||||
# Get the list of file changes
|
||||
file_changes = []
|
||||
file_change = self._parse_optional_filechange()
|
||||
|
@ -1437,8 +1415,7 @@ class FastExportFilter(object):
|
|||
committer_name, committer_email, committer_date,
|
||||
commit_msg,
|
||||
file_changes,
|
||||
from_commit,
|
||||
merge_commits,
|
||||
parents,
|
||||
original_id)
|
||||
|
||||
# If fast-export text had a mark for this commit, need to make sure this
|
||||
|
@ -1448,11 +1425,11 @@ class FastExportFilter(object):
|
|||
_IDS.record_rename(id_, commit.id)
|
||||
|
||||
# Record ancestry graph
|
||||
external_parents = [p for p in commit.get_parents()
|
||||
external_parents = [p for p in commit.parents
|
||||
if not isinstance(p, int)]
|
||||
self._graph.record_external_commits(external_parents)
|
||||
self._orig_graph.record_external_commits(external_parents)
|
||||
self._graph.add_commit_and_parents(commit.id, commit.get_parents())
|
||||
self._graph.add_commit_and_parents(commit.id, commit.parents)
|
||||
self._orig_graph.add_commit_and_parents(id_, orig_parents)
|
||||
|
||||
# Record the original list of file changes relative to first parent
|
||||
|
@ -1464,10 +1441,6 @@ class FastExportFilter(object):
|
|||
if self._everything_callback:
|
||||
self._everything_callback(commit)
|
||||
|
||||
# Sanity check that user callbacks didn't violate assumption on parents
|
||||
if commit.merge_commits:
|
||||
assert commit.from_commit is not None
|
||||
|
||||
# Find out which files were modified by the callbacks. Such paths could
|
||||
# lead to sebsequent commits being empty (e.g. if removed a line containing
|
||||
# a password from every version of a file that had the password, and some
|
||||
|
|
|
@ -43,8 +43,7 @@ commit1 = Commit("refs/heads/master",
|
|||
"Com M. Iter", "comm@iter.email", when_string,
|
||||
"My first commit! Wooot!\n\nLonger description",
|
||||
changes,
|
||||
from_commit = None,
|
||||
merge_commits = [])
|
||||
parents = [])
|
||||
commit1.dump(output)
|
||||
|
||||
world = Blob("Hello\nHi")
|
||||
|
@ -61,8 +60,7 @@ commit2 = Commit("refs/heads/master",
|
|||
"Com M. Iter", "comm@iter.email", when_string,
|
||||
"Make a symlink to world called planet, modify world",
|
||||
changes,
|
||||
from_commit = commit1.id,
|
||||
merge_commits = [])
|
||||
parents = [commit1.id])
|
||||
commit2.dump(output)
|
||||
|
||||
script = Blob("#!/bin/sh\n\necho Hello")
|
||||
|
@ -75,8 +73,7 @@ commit3 = Commit("refs/heads/master",
|
|||
"Com M. Iter", "comm@iter.email", when_string,
|
||||
"Add runme script, remove bar",
|
||||
changes,
|
||||
from_commit = commit2.id,
|
||||
merge_commits = [])
|
||||
parents = [commit2.id])
|
||||
commit3.dump(output)
|
||||
|
||||
progress = Progress("Done with the master branch now...")
|
||||
|
@ -98,8 +95,7 @@ commit4 = Commit("refs/heads/devel",
|
|||
"Com M. Iter", "comm@iter.email", when_string,
|
||||
"Modify world",
|
||||
changes,
|
||||
from_commit = commit1.id,
|
||||
merge_commits = [])
|
||||
parents = [commit1.id])
|
||||
commit4.dump(output)
|
||||
|
||||
world = Blob("Hello\nHi\nGoodbye")
|
||||
|
@ -120,8 +116,7 @@ commit5 = Commit("refs/heads/devel",
|
|||
"Com M. Iter", "comm@iter.email", when_string,
|
||||
"Merge branch 'master'\n",
|
||||
changes,
|
||||
from_commit = commit4.id,
|
||||
merge_commits = [commit3.id])
|
||||
parents = [commit4.id, commit3.id])
|
||||
commit5.dump(output)
|
||||
|
||||
|
||||
|
|
|
@ -39,9 +39,9 @@ class InterleaveRepositories:
|
|||
# Splice in any extra commits needed
|
||||
if prev_letter in self.commit_map:
|
||||
new_commit = self.commit_map[prev_letter]
|
||||
new_commit.from_commit = self.last_commit
|
||||
new_commit.parents = [self.last_commit] if self.last_commit else []
|
||||
new_commit.dump(self.out._output)
|
||||
commit.from_commit = new_commit.id
|
||||
commit.parents = [new_commit.id]
|
||||
|
||||
# Dump our commit now
|
||||
commit.dump(self.out._output)
|
||||
|
|
Loading…
Reference in New Issue
Block a user