10 class HgExportGenerator(object):
11 def __init__(self, repo):
12 self.git_hg = repo.git_hg
14 self.prefix = repo.prefix
15 self.nullref = "0" * 40
24 def tohex(self, binhex):
25 return binascii.hexlify(binhex)
39 def parents(self, parents):
40 parents = [self.tohex(i.node()) for i in parents]
41 parents = [i for i in parents if i != self.nullref]
42 assert all(i in self.mapping for i in parents)
43 parents = [':%d' % self.mapping[i] for i in parents]
48 return self.prefix + ctx.branch()
50 def write(self, *args):
51 msg = ''.join([str(i) for i in args])
56 self.write('#', SP, msg, LF)
58 def feature(self, feature, value=None):
60 self.write('feature', SP, feature, '=', value, LF)
62 self.write('feature', SP, feature, LF)
64 def option(self, option, value=None):
66 self.write('option', SP, option, '=', value, LF)
68 self.write('option', SP, option, LF)
70 def option_quiet(self):
73 def feature_relative_marks(self):
74 self.feature('relative-marks')
76 def feature_export_marks(self, marks):
77 self.feature('export-marks', marks)
79 def feature_import_marks(self, marks):
80 self.feature('import-marks', marks)
82 def feature_force(self):
85 def progress(self, message):
86 self.write('progress', SP, message, LF)
88 def write_data(self, data):
90 self.write('data', SP, count, LF)
93 def write_mark(self, idnum):
94 self.write('mark', SP, ':', idnum, LF)
96 def write_blob(self, data, idnum):
97 self.write('blob', LF)
98 self.write_mark(idnum)
101 def write_file(self, ctx, file, idnum):
102 fctx = ctx.filectx(file)
105 self.write_blob(data, idnum)
107 def write_commit(self, ref):
108 self.write('commit', SP, ref, LF)
110 def write_author(self, author):
111 self.write('author', SP, author, LF)
113 def write_committer(self, committer):
114 self.write('committer', SP, committer, LF)
116 def write_from(self, parent):
117 self.write('from', SP, parent, LF)
119 def write_merge(self, parent):
120 self.write('merge', SP, parent, LF)
122 def write_reset(self, ref, idnum):
123 self.write('reset', SP, ref, LF)
124 self.write('from', SP, ':', idnum, LF)
126 def write_parents(self, parents):
127 parents = self.parents(parents)
135 self.write_from(parent)
137 for parent in parents[1:]:
138 self.write_merge(parent)
140 def write_filedeleteall(self):
141 self.write('deleteall', LF)
143 def write_filedelete(self, ctx, name):
144 self.write('D', SP, name, LF)
146 def write_filemodify_mark(self, mode, name, mark):
147 self.write('M', SP, mode, SP, ':', mark, SP, name, LF)
149 def write_filemodify_inline(self, mode, name, data):
150 self.write('M', SP, mode, SP, 'inline', SP, name, LF)
151 self.write_data(data)
153 def write_filemodify(self, ctx, name):
154 fctx = ctx.filectx(name)
157 hash = self.tohex(nodesha)
158 mode = self.mode(fctx)
160 if hash in self.mapping:
161 mark = self.mapping[hash]
162 self.write_filemodify_mark(mode, name, mark)
165 self.write_filemodify_inline(mode, name, data)
167 def write_files(self, ctx):
170 if len(ctx.parents()) == 2:
171 self.write_filedeleteall()
173 self.write_filemodify(ctx, name)
175 for name in ctx.files():
178 self.write_filedelete(ctx, name)
180 self.write_filemodify(ctx, name)
182 def export_files(self, ctx):
185 for name in [i for i in ctx.files() if i in man]:
186 idnum = self.nextid()
188 hash = self.tohex(nodesha)
190 self.write_file(ctx, name, idnum)
191 self.mapping[hash] = idnum
193 def export_commit(self, ctx, ref, idnum, msg, parents):
194 author = self.git_hg.get_author(ctx)
195 committer = self.git_hg.get_committer(ctx)
196 committer = committer if committer else author
198 self.debug('exporting commit')
199 self.write_commit(ref)
200 self.write_mark(idnum)
201 self.write_author(author)
202 self.write_committer(committer)
204 self.write_parents(parents)
205 self.write_files(ctx)
206 self.debug('commit exported')
208 def export_revision(self, ctx):
210 hash = self.tohex(nodesha)
212 if hash in self.mapping:
215 self.export_files(ctx)
217 idnum = self.nextid()
220 msg = self.git_hg.get_message(ctx)
221 parents = self.git_hg.get_parents(ctx)
223 self.export_commit(ctx, ref, idnum, msg, parents)
224 self.mapping[hash] = idnum
228 def export_branch(self, name, rev):
229 ctx = self.repo.changectx(rev)
231 hash = self.tohex(nodesha)
232 idnum = self.mapping[hash]
234 ref = self.prefix + name
236 self.write_reset(ref, idnum)
238 def export_repo(self, refs):
242 exported = printed = False
244 for rev in self.repo.changelog:
245 ctx = self.repo.changectx(rev)
246 exported = self.export_revision(ctx) or exported
248 if (exported and not printed) or (exported and rev%1000 == 0):
249 self.progress("Exported revision %d.\n" % rev)
252 def write_marks(self, base):
253 dirname = self.repo.get_base_path(base)
254 path = os.path.join(dirname, 'hg.marks')
255 if not os.path.exists(dirname):
257 f = open(path, 'w') #self.repo.opener(self.marksfile, 'w', atomictemp=True)
259 second = lambda (a, b): b
261 for hash, mark in sorted(self.mapping.iteritems(), key=second):
262 f.write(':%d %s\n' % (mark, hash))
264 f.close() #f.rename()
266 def read_marks(self, base):
267 dirname = self.repo.get_base_path(base)
268 path = os.path.join(dirname, 'hg.marks')
270 if not os.path.exists(path):
271 sys.stderr.write("warning: cannot find " + path)
274 f = open(path) #self.repo.opener(self.marksfile)
276 marks = [i.strip().split(' ') for i in f.readlines()]
278 self.mapping = dict((i[1], int(i[0][1:])) for i in marks)
279 self.next_id = max(self.mapping.values())