fastexport.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. # __init__.py -- Fast export/import functionality
  2. # Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
  3. #
  4. # This program is free software; you can redistribute it and/or
  5. # modify it under the terms of the GNU General Public License
  6. # as published by the Free Software Foundation; version 2
  7. # of the License or (at your option) any later version of
  8. # the License.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  18. # MA 02110-1301, USA.
  19. """Fast export/import functionality."""
  20. from dulwich.objects import (
  21. format_timezone,
  22. )
  23. import stat
  24. class FastExporter(object):
  25. """Generate a fast-export output stream for Git objects."""
  26. def __init__(self, outf, store):
  27. self.outf = outf
  28. self.store = store
  29. self.markers = {}
  30. self._marker_idx = 0
  31. def _allocate_marker(self):
  32. self._marker_idx+=1
  33. return self._marker_idx
  34. def _dump_blob(self, blob, marker):
  35. self.outf.write("blob\nmark :%s\n" % marker)
  36. self.outf.write("data %s\n" % blob.raw_length())
  37. for chunk in blob.as_raw_chunks():
  38. self.outf.write(chunk)
  39. self.outf.write("\n")
  40. def export_blob(self, blob):
  41. i = self._allocate_marker()
  42. self.markers[i] = blob.id
  43. self._dump_blob(blob, i)
  44. return i
  45. def _dump_commit(self, commit, marker, ref, file_changes):
  46. self.outf.write("commit %s\n" % ref)
  47. self.outf.write("mark :%s\n" % marker)
  48. self.outf.write("author %s %s %s\n" % (commit.author,
  49. commit.author_time, format_timezone(commit.author_timezone)))
  50. self.outf.write("committer %s %s %s\n" % (commit.committer,
  51. commit.commit_time, format_timezone(commit.commit_timezone)))
  52. self.outf.write("data %s\n" % len(commit.message))
  53. self.outf.write(commit.message)
  54. self.outf.write("\n")
  55. self.outf.write('\n'.join(file_changes))
  56. self.outf.write("\n\n")
  57. def export_commit(self, commit, ref, base_tree=None):
  58. file_changes = []
  59. for (old_path, new_path), (old_mode, new_mode), (old_hexsha, new_hexsha) in \
  60. self.store.tree_changes(base_tree, commit.tree):
  61. if new_path is None:
  62. file_changes.append("D %s" % old_path)
  63. continue
  64. if not stat.S_ISDIR(new_mode):
  65. marker = self.export_blob(self.store[new_hexsha])
  66. file_changes.append("M %o :%s %s" % (new_mode, marker, new_path))
  67. i = self._allocate_marker()
  68. self._dump_commit(commit, i, ref, file_changes)
  69. return i