Mercurial > hg > soundsoftware-site
comparison extra/fast-export/hg-fast-export.py @ 1567:3ad53f43483d live
Update hg-fast-export to current version (with fix-broken-bare upstream branch) for compatibility with current git
author | Chris Cannam |
---|---|
date | Mon, 10 Oct 2016 12:56:28 +0100 |
parents | e9e55585ebf2 |
children |
comparison
equal
deleted
inserted
replaced
1566:ac2e4a54a6a6 | 1567:3ad53f43483d |
---|---|
143 if count%cfg_export_boundary==0: | 143 if count%cfg_export_boundary==0: |
144 sys.stderr.write('Exported %d/%d files\n' % (count,max)) | 144 sys.stderr.write('Exported %d/%d files\n' % (count,max)) |
145 if max>cfg_export_boundary: | 145 if max>cfg_export_boundary: |
146 sys.stderr.write('Exported %d/%d files\n' % (count,max)) | 146 sys.stderr.write('Exported %d/%d files\n' % (count,max)) |
147 | 147 |
148 def sanitize_name(name,what="branch"): | 148 def sanitize_name(name,what="branch", mapping={}): |
149 """Sanitize input roughly according to git-check-ref-format(1)""" | 149 """Sanitize input roughly according to git-check-ref-format(1)""" |
150 | |
151 # NOTE: Do not update this transform to work around | |
152 # incompatibilities on your platform. If you change it and it starts | |
153 # modifying names which previously were not touched it will break | |
154 # preexisting setups which are doing incremental imports. | |
155 # | |
156 # Use the -B and -T options to mangle branch and tag names | |
157 # instead. If you have a source repository where this is too much | |
158 # work to do manually, write a tool that does it for you. | |
150 | 159 |
151 def dot(name): | 160 def dot(name): |
152 if name[0] == '.': return '_'+name[1:] | 161 if name[0] == '.': return '_'+name[1:] |
153 return name | 162 return name |
154 | 163 |
155 n=name | 164 n=mapping.get(name,name) |
156 p=re.compile('([[ ~^:?\\\\*]|\.\.)') | 165 p=re.compile('([[ ~^:?\\\\*]|\.\.)') |
157 n=p.sub('_', n) | 166 n=p.sub('_', n) |
158 if n[-1] in ('/', '.'): n=n[:-1]+'_' | 167 if n[-1] in ('/', '.'): n=n[:-1]+'_' |
159 n='/'.join(map(dot,n.split('/'))) | 168 n='/'.join(map(dot,n.split('/'))) |
160 p=re.compile('_+') | 169 p=re.compile('_+') |
168 if filename[0] == '/': | 177 if filename[0] == '/': |
169 return filename[1:] | 178 return filename[1:] |
170 return filename | 179 return filename |
171 | 180 |
172 def export_commit(ui,repo,revision,old_marks,max,count,authors, | 181 def export_commit(ui,repo,revision,old_marks,max,count,authors, |
173 branchesmap,sob,brmap,hgtags,notes,encoding='',fn_encoding=''): | 182 branchesmap,sob,brmap,hgtags,encoding='',fn_encoding=''): |
174 def get_branchname(name): | 183 def get_branchname(name): |
175 if brmap.has_key(name): | 184 if brmap.has_key(name): |
176 return brmap[name] | 185 return brmap[name] |
177 n=sanitize_name(branchesmap.get(name,name)) | 186 n=sanitize_name(name, "branch", branchesmap) |
178 brmap[name]=n | 187 brmap[name]=n |
179 return n | 188 return n |
180 | 189 |
181 (revnode,_,user,(time,timezone),files,desc,branch,_)=get_changeset(ui,repo,revision,authors,encoding) | 190 (revnode,_,user,(time,timezone),files,desc,branch,_)=get_changeset(ui,repo,revision,authors,encoding) |
182 | 191 |
233 map(lambda r: wr('D %s' % r),removed) | 242 map(lambda r: wr('D %s' % r),removed) |
234 export_file_contents(ctx,man,added,hgtags,fn_encoding) | 243 export_file_contents(ctx,man,added,hgtags,fn_encoding) |
235 export_file_contents(ctx,man,changed,hgtags,fn_encoding) | 244 export_file_contents(ctx,man,changed,hgtags,fn_encoding) |
236 wr() | 245 wr() |
237 | 246 |
238 count=checkpoint(count) | 247 return checkpoint(count) |
239 count=generate_note(user,time,timezone,revision,ctx,count,notes) | 248 |
240 return count | 249 def export_note(ui,repo,revision,count,authors,encoding,is_first): |
241 | 250 (revnode,_,user,(time,timezone),_,_,_,_)=get_changeset(ui,repo,revision,authors,encoding) |
242 def generate_note(user,time,timezone,revision,ctx,count,notes): | 251 |
243 if not notes: | 252 parents = [p for p in repo.changelog.parentrevs(revision) if p >= 0] |
244 return count | 253 |
245 wr('commit refs/notes/hg') | 254 wr('commit refs/notes/hg') |
246 wr('committer %s %d %s' % (user,time,timezone)) | 255 wr('committer %s %d %s' % (user,time,timezone)) |
247 wr('data 0') | 256 wr('data 0') |
257 if is_first: | |
258 wr('from refs/notes/hg^0') | |
248 wr('N inline :%d' % (revision+1)) | 259 wr('N inline :%d' % (revision+1)) |
249 hg_hash=ctx.hex() | 260 hg_hash=repo.changectx(str(revision)).hex() |
250 wr('data %d' % (len(hg_hash))) | 261 wr('data %d' % (len(hg_hash))) |
251 wr_no_nl(hg_hash) | 262 wr_no_nl(hg_hash) |
252 wr() | 263 wr() |
253 return checkpoint(count) | 264 return checkpoint(count) |
254 | 265 |
266 wr('data %d' % (len(desc)+1)) # wtf? | |
267 wr(desc) | |
268 wr() | |
269 | |
255 def export_tags(ui,repo,old_marks,mapping_cache,count,authors,tagsmap): | 270 def export_tags(ui,repo,old_marks,mapping_cache,count,authors,tagsmap): |
256 l=repo.tagslist() | 271 l=repo.tagslist() |
257 for tag,node in l: | 272 for tag,node in l: |
258 # Remap the branch name | 273 # Remap the branch name |
259 tag=sanitize_name(tagsmap.get(tag,tag),"tag") | 274 tag=sanitize_name(tag,"tag",tagsmap) |
260 # ignore latest revision | 275 # ignore latest revision |
261 if tag=='tip': continue | 276 if tag=='tip': continue |
262 # ignore tags to nodes that are missing (ie, 'in the future') | 277 # ignore tags to nodes that are missing (ie, 'in the future') |
263 if node.encode('hex_codec') not in mapping_cache: | 278 if node.encode('hex_codec') not in mapping_cache: |
264 sys.stderr.write('Tag %s refers to unseen node %s\n' % (tag, node.encode('hex_codec'))) | 279 sys.stderr.write('Tag %s refers to unseen node %s\n' % (tag, node.encode('hex_codec'))) |
279 return count | 294 return count |
280 | 295 |
281 def load_mapping(name, filename): | 296 def load_mapping(name, filename): |
282 cache={} | 297 cache={} |
283 if not os.path.exists(filename): | 298 if not os.path.exists(filename): |
299 sys.stderr.write('Could not open mapping file [%s]\n' % (filename)) | |
284 return cache | 300 return cache |
285 f=open(filename,'r') | 301 f=open(filename,'r') |
286 l=0 | 302 l=0 |
287 a=0 | 303 a=0 |
288 lre=re.compile('^([^=]+)[ ]*=[ ]*(.+)$') | 304 lre=re.compile('^([^=]+)[ ]*=[ ]*(.+)$') |
309 if 'close' not in repo.changelog.read(h)[5]: | 325 if 'close' not in repo.changelog.read(h)[5]: |
310 tip = h | 326 tip = h |
311 break | 327 break |
312 return tip | 328 return tip |
313 | 329 |
314 def verify_heads(ui,repo,cache,force): | 330 def verify_heads(ui,repo,cache,force,branchesmap): |
315 branches={} | 331 branches={} |
316 for bn, heads in repo.branchmap().iteritems(): | 332 for bn, heads in repo.branchmap().iteritems(): |
317 branches[bn] = branchtip(repo, heads) | 333 branches[bn] = branchtip(repo, heads) |
318 l=[(-repo.changelog.rev(n), n, t) for t, n in branches.items()] | 334 l=[(-repo.changelog.rev(n), n, t) for t, n in branches.items()] |
319 l.sort() | 335 l.sort() |
320 | 336 |
321 # get list of hg's branches to verify, don't take all git has | 337 # get list of hg's branches to verify, don't take all git has |
322 for _,_,b in l: | 338 for _,_,b in l: |
323 b=get_branch(b) | 339 b=get_branch(b) |
324 sha1=get_git_sha1(b) | 340 sanitized_name=sanitize_name(b,"branch",branchesmap) |
325 c=cache.get(b) | 341 sha1=get_git_sha1(sanitized_name) |
342 c=cache.get(sanitized_name) | |
326 if sha1!=c: | 343 if sha1!=c: |
327 sys.stderr.write('Error: Branch [%s] modified outside hg-fast-export:' | 344 sys.stderr.write('Error: Branch [%s] modified outside hg-fast-export:' |
328 '\n%s (repo) != %s (cache)\n' % (b,sha1,c)) | 345 '\n%s (repo) != %s (cache)\n' % (b,sha1,c)) |
329 if not force: return False | 346 if not force: return False |
330 | 347 |
341 return True | 358 return True |
342 | 359 |
343 def hg2git(repourl,m,marksfile,mappingfile,headsfile,tipfile, | 360 def hg2git(repourl,m,marksfile,mappingfile,headsfile,tipfile, |
344 authors={},branchesmap={},tagsmap={}, | 361 authors={},branchesmap={},tagsmap={}, |
345 sob=False,force=False,hgtags=False,notes=False,encoding='',fn_encoding=''): | 362 sob=False,force=False,hgtags=False,notes=False,encoding='',fn_encoding=''): |
363 def check_cache(filename, contents): | |
364 if len(contents) == 0: | |
365 sys.stderr.write('Warning: %s does not contain any data, this will probably make an incremental import fail\n' % filename) | |
366 | |
346 _max=int(m) | 367 _max=int(m) |
347 | 368 |
348 old_marks=load_cache(marksfile,lambda s: int(s)-1) | 369 old_marks=load_cache(marksfile,lambda s: int(s)-1) |
349 mapping_cache=load_cache(mappingfile) | 370 mapping_cache=load_cache(mappingfile) |
350 heads_cache=load_cache(headsfile) | 371 heads_cache=load_cache(headsfile) |
351 state_cache=load_cache(tipfile) | 372 state_cache=load_cache(tipfile) |
352 | 373 |
374 if len(state_cache) != 0: | |
375 for (name, data) in [(marksfile, old_marks), | |
376 (mappingfile, mapping_cache), | |
377 (headsfile, state_cache)]: | |
378 check_cache(name, data) | |
379 | |
353 ui,repo=setup_repo(repourl) | 380 ui,repo=setup_repo(repourl) |
354 | 381 |
355 if not verify_heads(ui,repo,heads_cache,force): | 382 if not verify_heads(ui,repo,heads_cache,force,branchesmap): |
356 return 1 | 383 return 1 |
357 | 384 |
358 try: | 385 try: |
359 tip=repo.changelog.count() | 386 tip=repo.changelog.count() |
360 except AttributeError: | 387 except AttributeError: |
372 | 399 |
373 c=0 | 400 c=0 |
374 brmap={} | 401 brmap={} |
375 for rev in range(min,max): | 402 for rev in range(min,max): |
376 c=export_commit(ui,repo,rev,old_marks,max,c,authors,branchesmap, | 403 c=export_commit(ui,repo,rev,old_marks,max,c,authors,branchesmap, |
377 sob,brmap,hgtags,notes,encoding,fn_encoding) | 404 sob,brmap,hgtags,encoding,fn_encoding) |
405 if notes: | |
406 for rev in range(min,max): | |
407 c=export_note(ui,repo,rev,c,authors, encoding, rev == min and min != 0) | |
378 | 408 |
379 state_cache['tip']=max | 409 state_cache['tip']=max |
380 state_cache['repo']=repourl | 410 state_cache['repo']=repourl |
381 save_cache(tipfile,state_cache) | 411 save_cache(tipfile,state_cache) |
382 save_cache(mappingfile,mapping_cache) | 412 save_cache(mappingfile,mapping_cache) |