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())