From e9678a367f19a293877744bc57aa171a4fd01a93 Mon Sep 17 00:00:00 2001 From: Elijah Newren Date: Sat, 22 Jun 2019 08:04:52 -0600 Subject: [PATCH] filter-repo: support deleteall directive Signed-off-by: Elijah Newren --- git-filter-repo | 29 ++++++++++++++++++---------- t/t9391/create_fast_export_output.py | 4 +++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/git-filter-repo b/git-filter-repo index b11fbef..0dbc60d 100755 --- a/git-filter-repo +++ b/git-filter-repo @@ -548,7 +548,7 @@ class FileChange(_GitElement): elements are components within a Commit element. """ - def __init__(self, type_, filename, id_ = None, mode = None): + def __init__(self, type_, filename = None, id_ = None, mode = None): _GitElement.__init__(self) # Denote the type of file-change (b'M' for modify, b'D' for delete, etc) @@ -562,23 +562,27 @@ class FileChange(_GitElement): # Record the mode (mode describes type of file entry (non-executable, # executable, or symlink)). - self.mode = None + self.mode = mode # blob_id is the id (mark) of the affected blob - self.blob_id = None + self.blob_id = id_ + + if type_ == b'DELETEALL': + assert filename is None and id_ is None and mode is None + self.filename = b'' # Just so PathQuoting.enquote doesn't die + else: + assert filename is not None - # For b'M' file changes (modify), expect to have id and mode if type_ == b'M': - if mode is None: - raise SystemExit(_("file mode and idnum needed for %s") % filename) # pragma: no cover - self.mode = mode - self.blob_id = id_ - - # For b'R' file changes (rename), expect to have newname as third arg + assert id_ is not None and mode is not None + elif type_ == b'D': + assert id_ is None and mode is None elif type_ == b'R': # pragma: no cover (now avoid fast-export renames) + assert mode is None if id_ is None: raise SystemExit(_("new name needed for rename of %s") % filename) self.filename = (self.filename, id_) + self.blob_id = None def dump(self, file_): """ @@ -595,6 +599,8 @@ class FileChange(_GitElement): file_.write(b'M %s %s %s\n' % (self.mode, self.blob_id, quoted_filename)) elif self.type == b'D': file_.write(b'D %s\n' % quoted_filename) + elif self.type == b'DELETEALL': + file_.write(b'deleteall\n') else: raise SystemExit(_("Unhandled filechange type: %s") % self.type) # pragma: no cover @@ -3028,6 +3034,9 @@ class RepoFilter(object): # issues a deleteall directive which has no filename, and thus this # block would normally strip it. Of course, FileChange() and # _parse_optional_filechange() would need updates too. + if change.type == b'DELETEALL': + new_file_changes[b''] = change + continue if change.filename in self._newnames: change.filename = self._newnames[change.filename] else: diff --git a/t/t9391/create_fast_export_output.py b/t/t9391/create_fast_export_output.py index ea68716..dff19ba 100755 --- a/t/t9391/create_fast_export_output.py +++ b/t/t9391/create_fast_export_output.py @@ -80,7 +80,9 @@ out.insert(devel) world = Blob(b"Hello\nGoodbye") out.insert(world) -changes = [FileChange(b'M', b'world', world.id, mode=b"100644")] +changes = [FileChange(b'DELETEALL'), + FileChange(b'M', b'world', world.id, mode=b"100644"), + FileChange(b'M', b'bar', bar.id, mode=b"100644")] when = datetime(2006, 8, 17, tzinfo=FixedTimeZone(b"+0200")) when_string = fr.date_to_string(when) commit4 = Commit(b"refs/heads/devel",