Loosen criteria for deleting initial branch commits.
[cvs2svn.git] / cvs2svn_lib / git_revision_recorder.py
blob604f8ac8282c0d92709c20708936beaefb3add75
1 # (Be in -*- python -*- mode.)
3 # ====================================================================
4 # Copyright (c) 2007-2009 CollabNet. All rights reserved.
6 # This software is licensed as described in the file COPYING, which
7 # you should have received as part of this distribution. The terms
8 # are also available at http://subversion.tigris.org/license-1.html.
9 # If newer versions of this license are posted there, you may use a
10 # newer version instead, at your option.
12 # This software consists of voluntary contributions made by many
13 # individuals. For exact contribution history, see the revision
14 # history and logs, available at http://cvs2svn.tigris.org/.
15 # ====================================================================
17 """Write file contents to a stream of git-fast-import blobs."""
19 import itertools
21 from cvs2svn_lib.symbol import Trunk
22 from cvs2svn_lib.cvs_item import CVSRevisionDelete
23 from cvs2svn_lib.cvs_item import CVSSymbol
24 from cvs2svn_lib.fulltext_revision_recorder import FulltextRevisionRecorder
25 from cvs2svn_lib.key_generator import KeyGenerator
28 class GitRevisionRecorder(FulltextRevisionRecorder):
29 """Output file revisions to git-fast-import."""
31 def __init__(self, blob_filename):
32 self.blob_filename = blob_filename
34 def start(self):
35 self.dump_file = open(self.blob_filename, 'wb')
36 self._mark_generator = KeyGenerator()
38 def start_file(self, cvs_file_items):
39 self._cvs_file_items = cvs_file_items
41 def _get_original_source(self, cvs_rev):
42 """Return the original source of the contents of CVS_REV.
44 Return the first non-delete CVSRevision with the same contents as
45 CVS_REV. 'First' here refers to deltatext order; i.e., the very
46 first revision is HEAD on trunk, then backwards to the root of a
47 branch, then out to the tip of a branch.
49 The candidates are all revisions along the CVS delta-dependency
50 chain until the next one that has a deltatext (inclusive). Of the
51 candidates, CVSRevisionDeletes are disqualified because, even
52 though CVS records their contents, it is impossible to extract
53 their fulltext using commands like 'cvs checkout -p'.
55 If there is no other CVSRevision that has the same content, return
56 CVS_REV itself."""
58 # Keep track of the "best" source CVSRevision found so far:
59 best_source_rev = None
61 for cvs_rev in itertools.chain(
62 [cvs_rev], self._cvs_file_items.iter_deltatext_ancestors(cvs_rev)
64 if not isinstance(cvs_rev, CVSRevisionDelete):
65 best_source_rev = cvs_rev
67 if cvs_rev.deltatext_exists:
68 break
70 return best_source_rev
72 def record_fulltext(self, cvs_rev, log, fulltext):
73 """Write the fulltext to a blob if it is original and not a delete.
75 The reason we go to this trouble is to avoid writing the same file
76 contents multiple times for a string of revisions that don't have
77 deltatexts (as, for example, happens with dead revisions and
78 imported revisions)."""
80 if isinstance(cvs_rev, CVSRevisionDelete):
81 # There is no need to record a delete revision, and its token
82 # will never be needed:
83 return None
85 source = self._get_original_source(cvs_rev)
87 if source.id == cvs_rev.id:
88 # Revision is its own source; write it out:
89 mark = self._mark_generator.gen_id()
90 self.dump_file.write('blob\n')
91 self.dump_file.write('mark :%d\n' % (mark,))
92 self.dump_file.write('data %d\n' % (len(fulltext),))
93 self.dump_file.write(fulltext)
94 self.dump_file.write('\n')
95 return mark
96 else:
97 # Return as revision_recorder_token the CVSRevision.id of the
98 # original source revision:
99 return source.revision_recorder_token
101 def finish_file(self, cvs_file_items):
102 # Determine the original source of each CVSSymbol, and store it as
103 # the symbol's revision_recorder_token.
104 for cvs_item in cvs_file_items.values():
105 if isinstance(cvs_item, CVSSymbol):
106 cvs_source = cvs_item.get_cvs_revision_source(cvs_file_items)
107 cvs_item.revision_recorder_token = cvs_source.revision_recorder_token
109 del self._cvs_file_items
111 def finish(self):
112 self.dump_file.close()