annotate extra/fast-export/hg-fast-export.py @ 1628:9c5f8e24dadc live tip

Quieten this cron script
author Chris Cannam
date Tue, 25 Aug 2020 11:38:49 +0100
parents 3ad53f43483d
children
rev   line source
chris@1544 1 #!/usr/bin/env python
chris@1544 2
chris@1544 3 # Copyright (c) 2007, 2008 Rocco Rutte <pdmef@gmx.net> and others.
chris@1544 4 # License: MIT <http://www.opensource.org/licenses/mit-license.php>
chris@1544 5
chris@1544 6 from mercurial import node
chris@1544 7 from hg2git import setup_repo,fixup_user,get_branch,get_changeset
chris@1544 8 from hg2git import load_cache,save_cache,get_git_sha1,set_default_branch,set_origin_name
chris@1544 9 from optparse import OptionParser
chris@1544 10 import re
chris@1544 11 import sys
chris@1544 12 import os
chris@1544 13
chris@1544 14 if sys.platform == "win32":
chris@1544 15 # On Windows, sys.stdout is initially opened in text mode, which means that
chris@1544 16 # when a LF (\n) character is written to sys.stdout, it will be converted
chris@1544 17 # into CRLF (\r\n). That makes git blow up, so use this platform-specific
chris@1544 18 # code to change the mode of sys.stdout to binary.
chris@1544 19 import msvcrt
chris@1544 20 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
chris@1544 21
chris@1544 22 # silly regex to catch Signed-off-by lines in log message
chris@1544 23 sob_re=re.compile('^Signed-[Oo]ff-[Bb]y: (.+)$')
chris@1544 24 # insert 'checkpoint' command after this many commits or none at all if 0
chris@1544 25 cfg_checkpoint_count=0
chris@1544 26 # write some progress message every this many file contents written
chris@1544 27 cfg_export_boundary=1000
chris@1544 28
chris@1544 29 def gitmode(flags):
chris@1544 30 return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
chris@1544 31
chris@1544 32 def wr_no_nl(msg=''):
chris@1544 33 if msg:
chris@1544 34 sys.stdout.write(msg)
chris@1544 35
chris@1544 36 def wr(msg=''):
chris@1544 37 wr_no_nl(msg)
chris@1544 38 sys.stdout.write('\n')
chris@1544 39 #map(lambda x: sys.stderr.write('\t[%s]\n' % x),msg.split('\n'))
chris@1544 40
chris@1544 41 def checkpoint(count):
chris@1544 42 count=count+1
chris@1544 43 if cfg_checkpoint_count>0 and count%cfg_checkpoint_count==0:
chris@1544 44 sys.stderr.write("Checkpoint after %d commits\n" % count)
chris@1544 45 wr('checkpoint')
chris@1544 46 wr()
chris@1544 47 return count
chris@1544 48
chris@1544 49 def revnum_to_revref(rev, old_marks):
chris@1544 50 """Convert an hg revnum to a git-fast-import rev reference (an SHA1
chris@1544 51 or a mark)"""
chris@1544 52 return old_marks.get(rev) or ':%d' % (rev+1)
chris@1544 53
chris@1544 54 def file_mismatch(f1,f2):
chris@1544 55 """See if two revisions of a file are not equal."""
chris@1544 56 return node.hex(f1)!=node.hex(f2)
chris@1544 57
chris@1544 58 def split_dict(dleft,dright,l=[],c=[],r=[],match=file_mismatch):
chris@1544 59 """Loop over our repository and find all changed and missing files."""
chris@1544 60 for left in dleft.keys():
chris@1544 61 right=dright.get(left,None)
chris@1544 62 if right==None:
chris@1544 63 # we have the file but our parent hasn't: add to left set
chris@1544 64 l.append(left)
chris@1544 65 elif match(dleft[left],right) or gitmode(dleft.flags(left))!=gitmode(dright.flags(left)):
chris@1544 66 # we have it but checksums mismatch: add to center set
chris@1544 67 c.append(left)
chris@1544 68 for right in dright.keys():
chris@1544 69 left=dleft.get(right,None)
chris@1544 70 if left==None:
chris@1544 71 # if parent has file but we don't: add to right set
chris@1544 72 r.append(right)
chris@1544 73 # change is already handled when comparing child against parent
chris@1544 74 return l,c,r
chris@1544 75
chris@1544 76 def get_filechanges(repo,revision,parents,mleft):
chris@1544 77 """Given some repository and revision, find all changed/deleted files."""
chris@1544 78 l,c,r=[],[],[]
chris@1544 79 for p in parents:
chris@1544 80 if p<0: continue
chris@1544 81 mright=repo.changectx(p).manifest()
chris@1544 82 l,c,r=split_dict(mleft,mright,l,c,r)
chris@1544 83 l.sort()
chris@1544 84 c.sort()
chris@1544 85 r.sort()
chris@1544 86 return l,c,r
chris@1544 87
chris@1544 88 def get_author(logmessage,committer,authors):
chris@1544 89 """As git distincts between author and committer of a patch, try to
chris@1544 90 extract author by detecting Signed-off-by lines.
chris@1544 91
chris@1544 92 This walks from the end of the log message towards the top skipping
chris@1544 93 empty lines. Upon the first non-empty line, it walks all Signed-off-by
chris@1544 94 lines upwards to find the first one. For that (if found), it extracts
chris@1544 95 authorship information the usual way (authors table, cleaning, etc.)
chris@1544 96
chris@1544 97 If no Signed-off-by line is found, this defaults to the committer.
chris@1544 98
chris@1544 99 This may sound stupid (and it somehow is), but in log messages we
chris@1544 100 accidentially may have lines in the middle starting with
chris@1544 101 "Signed-off-by: foo" and thus matching our detection regex. Prevent
chris@1544 102 that."""
chris@1544 103
chris@1544 104 loglines=logmessage.split('\n')
chris@1544 105 i=len(loglines)
chris@1544 106 # from tail walk to top skipping empty lines
chris@1544 107 while i>=0:
chris@1544 108 i-=1
chris@1544 109 if len(loglines[i].strip())==0: continue
chris@1544 110 break
chris@1544 111 if i>=0:
chris@1544 112 # walk further upwards to find first sob line, store in 'first'
chris@1544 113 first=None
chris@1544 114 while i>=0:
chris@1544 115 m=sob_re.match(loglines[i])
chris@1544 116 if m==None: break
chris@1544 117 first=m
chris@1544 118 i-=1
chris@1544 119 # if the last non-empty line matches our Signed-Off-by regex: extract username
chris@1544 120 if first!=None:
chris@1544 121 r=fixup_user(first.group(1),authors)
chris@1544 122 return r
chris@1544 123 return committer
chris@1544 124
chris@1544 125 def export_file_contents(ctx,manifest,files,hgtags,encoding=''):
chris@1544 126 count=0
chris@1544 127 max=len(files)
chris@1544 128 for file in files:
chris@1544 129 # Skip .hgtags files. They only get us in trouble.
chris@1544 130 if not hgtags and file == ".hgtags":
chris@1544 131 sys.stderr.write('Skip %s\n' % (file))
chris@1544 132 continue
chris@1544 133 d=ctx.filectx(file).data()
chris@1544 134 if encoding:
chris@1544 135 filename=file.decode(encoding).encode('utf8')
chris@1544 136 else:
chris@1544 137 filename=file
chris@1544 138 wr('M %s inline %s' % (gitmode(manifest.flags(file)),
chris@1544 139 strip_leading_slash(filename)))
chris@1544 140 wr('data %d' % len(d)) # had some trouble with size()
chris@1544 141 wr(d)
chris@1544 142 count+=1
chris@1544 143 if count%cfg_export_boundary==0:
chris@1544 144 sys.stderr.write('Exported %d/%d files\n' % (count,max))
chris@1544 145 if max>cfg_export_boundary:
chris@1544 146 sys.stderr.write('Exported %d/%d files\n' % (count,max))
chris@1544 147
Chris@1567 148 def sanitize_name(name,what="branch", mapping={}):
chris@1544 149 """Sanitize input roughly according to git-check-ref-format(1)"""
chris@1544 150
Chris@1567 151 # NOTE: Do not update this transform to work around
Chris@1567 152 # incompatibilities on your platform. If you change it and it starts
Chris@1567 153 # modifying names which previously were not touched it will break
Chris@1567 154 # preexisting setups which are doing incremental imports.
Chris@1567 155 #
Chris@1567 156 # Use the -B and -T options to mangle branch and tag names
Chris@1567 157 # instead. If you have a source repository where this is too much
Chris@1567 158 # work to do manually, write a tool that does it for you.
Chris@1567 159
chris@1544 160 def dot(name):
chris@1544 161 if name[0] == '.': return '_'+name[1:]
chris@1544 162 return name
chris@1544 163
Chris@1567 164 n=mapping.get(name,name)
chris@1544 165 p=re.compile('([[ ~^:?\\\\*]|\.\.)')
chris@1544 166 n=p.sub('_', n)
chris@1544 167 if n[-1] in ('/', '.'): n=n[:-1]+'_'
chris@1544 168 n='/'.join(map(dot,n.split('/')))
chris@1544 169 p=re.compile('_+')
chris@1544 170 n=p.sub('_', n)
chris@1544 171
chris@1544 172 if n!=name:
chris@1544 173 sys.stderr.write('Warning: sanitized %s [%s] to [%s]\n' % (what,name,n))
chris@1544 174 return n
chris@1544 175
chris@1544 176 def strip_leading_slash(filename):
chris@1544 177 if filename[0] == '/':
chris@1544 178 return filename[1:]
chris@1544 179 return filename
chris@1544 180
chris@1544 181 def export_commit(ui,repo,revision,old_marks,max,count,authors,
Chris@1567 182 branchesmap,sob,brmap,hgtags,encoding='',fn_encoding=''):
chris@1544 183 def get_branchname(name):
chris@1544 184 if brmap.has_key(name):
chris@1544 185 return brmap[name]
Chris@1567 186 n=sanitize_name(name, "branch", branchesmap)
chris@1544 187 brmap[name]=n
chris@1544 188 return n
chris@1544 189
chris@1544 190 (revnode,_,user,(time,timezone),files,desc,branch,_)=get_changeset(ui,repo,revision,authors,encoding)
chris@1544 191
chris@1544 192 branch=get_branchname(branch)
chris@1544 193
chris@1544 194 parents = [p for p in repo.changelog.parentrevs(revision) if p >= 0]
chris@1544 195
chris@1544 196 if len(parents)==0 and revision != 0:
chris@1544 197 wr('reset refs/heads/%s' % branch)
chris@1544 198
chris@1544 199 wr('commit refs/heads/%s' % branch)
chris@1544 200 wr('mark :%d' % (revision+1))
chris@1544 201 if sob:
chris@1544 202 wr('author %s %d %s' % (get_author(desc,user,authors),time,timezone))
chris@1544 203 wr('committer %s %d %s' % (user,time,timezone))
chris@1544 204 wr('data %d' % (len(desc)+1)) # wtf?
chris@1544 205 wr(desc)
chris@1544 206 wr()
chris@1544 207
chris@1544 208 ctx=repo.changectx(str(revision))
chris@1544 209 man=ctx.manifest()
chris@1544 210 added,changed,removed,type=[],[],[],''
chris@1544 211
chris@1544 212 if len(parents) == 0:
chris@1544 213 # first revision: feed in full manifest
chris@1544 214 added=man.keys()
chris@1544 215 added.sort()
chris@1544 216 type='full'
chris@1544 217 else:
chris@1544 218 wr('from %s' % revnum_to_revref(parents[0], old_marks))
chris@1544 219 if len(parents) == 1:
chris@1544 220 # later non-merge revision: feed in changed manifest
chris@1544 221 # if we have exactly one parent, just take the changes from the
chris@1544 222 # manifest without expensively comparing checksums
chris@1544 223 f=repo.status(repo.lookup(parents[0]),revnode)[:3]
chris@1544 224 added,changed,removed=f[1],f[0],f[2]
chris@1544 225 type='simple delta'
chris@1544 226 else: # a merge with two parents
chris@1544 227 wr('merge %s' % revnum_to_revref(parents[1], old_marks))
chris@1544 228 # later merge revision: feed in changed manifest
chris@1544 229 # for many files comparing checksums is expensive so only do it for
chris@1544 230 # merges where we really need it due to hg's revlog logic
chris@1544 231 added,changed,removed=get_filechanges(repo,revision,parents,man)
chris@1544 232 type='thorough delta'
chris@1544 233
chris@1544 234 sys.stderr.write('%s: Exporting %s revision %d/%d with %d/%d/%d added/changed/removed files\n' %
chris@1544 235 (branch,type,revision+1,max,len(added),len(changed),len(removed)))
chris@1544 236
chris@1544 237 if fn_encoding:
chris@1544 238 removed=[r.decode(fn_encoding).encode('utf8') for r in removed]
chris@1544 239
chris@1544 240 removed=[strip_leading_slash(x) for x in removed]
chris@1544 241
chris@1544 242 map(lambda r: wr('D %s' % r),removed)
chris@1544 243 export_file_contents(ctx,man,added,hgtags,fn_encoding)
chris@1544 244 export_file_contents(ctx,man,changed,hgtags,fn_encoding)
chris@1544 245 wr()
chris@1544 246
Chris@1567 247 return checkpoint(count)
chris@1544 248
Chris@1567 249 def export_note(ui,repo,revision,count,authors,encoding,is_first):
Chris@1567 250 (revnode,_,user,(time,timezone),_,_,_,_)=get_changeset(ui,repo,revision,authors,encoding)
Chris@1567 251
Chris@1567 252 parents = [p for p in repo.changelog.parentrevs(revision) if p >= 0]
Chris@1567 253
chris@1544 254 wr('commit refs/notes/hg')
chris@1544 255 wr('committer %s %d %s' % (user,time,timezone))
chris@1544 256 wr('data 0')
Chris@1567 257 if is_first:
Chris@1567 258 wr('from refs/notes/hg^0')
chris@1544 259 wr('N inline :%d' % (revision+1))
Chris@1567 260 hg_hash=repo.changectx(str(revision)).hex()
chris@1544 261 wr('data %d' % (len(hg_hash)))
chris@1544 262 wr_no_nl(hg_hash)
chris@1544 263 wr()
chris@1544 264 return checkpoint(count)
Chris@1567 265
Chris@1567 266 wr('data %d' % (len(desc)+1)) # wtf?
Chris@1567 267 wr(desc)
Chris@1567 268 wr()
Chris@1567 269
chris@1544 270 def export_tags(ui,repo,old_marks,mapping_cache,count,authors,tagsmap):
chris@1544 271 l=repo.tagslist()
chris@1544 272 for tag,node in l:
chris@1544 273 # Remap the branch name
Chris@1567 274 tag=sanitize_name(tag,"tag",tagsmap)
chris@1544 275 # ignore latest revision
chris@1544 276 if tag=='tip': continue
chris@1544 277 # ignore tags to nodes that are missing (ie, 'in the future')
chris@1544 278 if node.encode('hex_codec') not in mapping_cache:
chris@1544 279 sys.stderr.write('Tag %s refers to unseen node %s\n' % (tag, node.encode('hex_codec')))
chris@1544 280 continue
chris@1544 281
chris@1544 282 rev=int(mapping_cache[node.encode('hex_codec')])
chris@1544 283
chris@1544 284 ref=revnum_to_revref(rev, old_marks)
chris@1544 285 if ref==None:
chris@1544 286 sys.stderr.write('Failed to find reference for creating tag'
chris@1544 287 ' %s at r%d\n' % (tag,rev))
chris@1544 288 continue
chris@1544 289 sys.stderr.write('Exporting tag [%s] at [hg r%d] [git %s]\n' % (tag,rev,ref))
chris@1544 290 wr('reset refs/tags/%s' % tag)
chris@1544 291 wr('from %s' % ref)
chris@1544 292 wr()
chris@1544 293 count=checkpoint(count)
chris@1544 294 return count
chris@1544 295
chris@1544 296 def load_mapping(name, filename):
chris@1544 297 cache={}
chris@1544 298 if not os.path.exists(filename):
Chris@1567 299 sys.stderr.write('Could not open mapping file [%s]\n' % (filename))
chris@1544 300 return cache
chris@1544 301 f=open(filename,'r')
chris@1544 302 l=0
chris@1544 303 a=0
chris@1544 304 lre=re.compile('^([^=]+)[ ]*=[ ]*(.+)$')
chris@1544 305 for line in f.readlines():
chris@1544 306 l+=1
chris@1544 307 line=line.strip()
chris@1544 308 if line=='' or line[0]=='#':
chris@1544 309 continue
chris@1544 310 m=lre.match(line)
chris@1544 311 if m==None:
chris@1544 312 sys.stderr.write('Invalid file format in [%s], line %d\n' % (filename,l))
chris@1544 313 continue
chris@1544 314 # put key:value in cache, key without ^:
chris@1544 315 cache[m.group(1).strip()]=m.group(2).strip()
chris@1544 316 a+=1
chris@1544 317 f.close()
chris@1544 318 sys.stderr.write('Loaded %d %s\n' % (a, name))
chris@1544 319 return cache
chris@1544 320
chris@1544 321 def branchtip(repo, heads):
chris@1544 322 '''return the tipmost branch head in heads'''
chris@1544 323 tip = heads[-1]
chris@1544 324 for h in reversed(heads):
chris@1544 325 if 'close' not in repo.changelog.read(h)[5]:
chris@1544 326 tip = h
chris@1544 327 break
chris@1544 328 return tip
chris@1544 329
Chris@1567 330 def verify_heads(ui,repo,cache,force,branchesmap):
chris@1544 331 branches={}
chris@1544 332 for bn, heads in repo.branchmap().iteritems():
chris@1544 333 branches[bn] = branchtip(repo, heads)
chris@1544 334 l=[(-repo.changelog.rev(n), n, t) for t, n in branches.items()]
chris@1544 335 l.sort()
chris@1544 336
chris@1544 337 # get list of hg's branches to verify, don't take all git has
chris@1544 338 for _,_,b in l:
chris@1544 339 b=get_branch(b)
Chris@1567 340 sanitized_name=sanitize_name(b,"branch",branchesmap)
Chris@1567 341 sha1=get_git_sha1(sanitized_name)
Chris@1567 342 c=cache.get(sanitized_name)
chris@1544 343 if sha1!=c:
chris@1544 344 sys.stderr.write('Error: Branch [%s] modified outside hg-fast-export:'
chris@1544 345 '\n%s (repo) != %s (cache)\n' % (b,sha1,c))
chris@1544 346 if not force: return False
chris@1544 347
chris@1544 348 # verify that branch has exactly one head
chris@1544 349 t={}
chris@1544 350 for h in repo.heads():
chris@1544 351 (_,_,_,_,_,_,branch,_)=get_changeset(ui,repo,h)
chris@1544 352 if t.get(branch,False):
chris@1544 353 sys.stderr.write('Error: repository has at least one unnamed head: hg r%s\n' %
chris@1544 354 repo.changelog.rev(h))
chris@1544 355 if not force: return False
chris@1544 356 t[branch]=True
chris@1544 357
chris@1544 358 return True
chris@1544 359
chris@1544 360 def hg2git(repourl,m,marksfile,mappingfile,headsfile,tipfile,
chris@1544 361 authors={},branchesmap={},tagsmap={},
chris@1544 362 sob=False,force=False,hgtags=False,notes=False,encoding='',fn_encoding=''):
Chris@1567 363 def check_cache(filename, contents):
Chris@1567 364 if len(contents) == 0:
Chris@1567 365 sys.stderr.write('Warning: %s does not contain any data, this will probably make an incremental import fail\n' % filename)
Chris@1567 366
chris@1544 367 _max=int(m)
chris@1544 368
chris@1544 369 old_marks=load_cache(marksfile,lambda s: int(s)-1)
chris@1544 370 mapping_cache=load_cache(mappingfile)
chris@1544 371 heads_cache=load_cache(headsfile)
chris@1544 372 state_cache=load_cache(tipfile)
chris@1544 373
Chris@1567 374 if len(state_cache) != 0:
Chris@1567 375 for (name, data) in [(marksfile, old_marks),
Chris@1567 376 (mappingfile, mapping_cache),
Chris@1567 377 (headsfile, state_cache)]:
Chris@1567 378 check_cache(name, data)
Chris@1567 379
chris@1544 380 ui,repo=setup_repo(repourl)
chris@1544 381
Chris@1567 382 if not verify_heads(ui,repo,heads_cache,force,branchesmap):
chris@1544 383 return 1
chris@1544 384
chris@1544 385 try:
chris@1544 386 tip=repo.changelog.count()
chris@1544 387 except AttributeError:
chris@1544 388 tip=len(repo)
chris@1544 389
chris@1544 390 min=int(state_cache.get('tip',0))
chris@1544 391 max=_max
chris@1544 392 if _max<0 or max>tip:
chris@1544 393 max=tip
chris@1544 394
chris@1544 395 for rev in range(0,max):
chris@1544 396 (revnode,_,_,_,_,_,_,_)=get_changeset(ui,repo,rev,authors)
chris@1544 397 mapping_cache[revnode.encode('hex_codec')] = str(rev)
chris@1544 398
chris@1544 399
chris@1544 400 c=0
chris@1544 401 brmap={}
chris@1544 402 for rev in range(min,max):
chris@1544 403 c=export_commit(ui,repo,rev,old_marks,max,c,authors,branchesmap,
Chris@1567 404 sob,brmap,hgtags,encoding,fn_encoding)
Chris@1567 405 if notes:
Chris@1567 406 for rev in range(min,max):
Chris@1567 407 c=export_note(ui,repo,rev,c,authors, encoding, rev == min and min != 0)
chris@1544 408
chris@1544 409 state_cache['tip']=max
chris@1544 410 state_cache['repo']=repourl
chris@1544 411 save_cache(tipfile,state_cache)
chris@1544 412 save_cache(mappingfile,mapping_cache)
chris@1544 413
chris@1544 414 c=export_tags(ui,repo,old_marks,mapping_cache,c,authors,tagsmap)
chris@1544 415
chris@1544 416 sys.stderr.write('Issued %d commands\n' % c)
chris@1544 417
chris@1544 418 return 0
chris@1544 419
chris@1544 420 if __name__=='__main__':
chris@1544 421 def bail(parser,opt):
chris@1544 422 sys.stderr.write('Error: No %s option given\n' % opt)
chris@1544 423 parser.print_help()
chris@1544 424 sys.exit(2)
chris@1544 425
chris@1544 426 parser=OptionParser()
chris@1544 427
chris@1544 428 parser.add_option("-m","--max",type="int",dest="max",
chris@1544 429 help="Maximum hg revision to import")
chris@1544 430 parser.add_option("--mapping",dest="mappingfile",
chris@1544 431 help="File to read last run's hg-to-git SHA1 mapping")
chris@1544 432 parser.add_option("--marks",dest="marksfile",
chris@1544 433 help="File to read git-fast-import's marks from")
chris@1544 434 parser.add_option("--heads",dest="headsfile",
chris@1544 435 help="File to read last run's git heads from")
chris@1544 436 parser.add_option("--status",dest="statusfile",
chris@1544 437 help="File to read status from")
chris@1544 438 parser.add_option("-r","--repo",dest="repourl",
chris@1544 439 help="URL of repo to import")
chris@1544 440 parser.add_option("-s",action="store_true",dest="sob",
chris@1544 441 default=False,help="Enable parsing Signed-off-by lines")
chris@1544 442 parser.add_option("--hgtags",action="store_true",dest="hgtags",
chris@1544 443 default=False,help="Enable exporting .hgtags files")
chris@1544 444 parser.add_option("-A","--authors",dest="authorfile",
chris@1544 445 help="Read authormap from AUTHORFILE")
chris@1544 446 parser.add_option("-B","--branches",dest="branchesfile",
chris@1544 447 help="Read branch map from BRANCHESFILE")
chris@1544 448 parser.add_option("-T","--tags",dest="tagsfile",
chris@1544 449 help="Read tags map from TAGSFILE")
chris@1544 450 parser.add_option("-f","--force",action="store_true",dest="force",
chris@1544 451 default=False,help="Ignore validation errors by force")
chris@1544 452 parser.add_option("-M","--default-branch",dest="default_branch",
chris@1544 453 help="Set the default branch")
chris@1544 454 parser.add_option("-o","--origin",dest="origin_name",
chris@1544 455 help="use <name> as namespace to track upstream")
chris@1544 456 parser.add_option("--hg-hash",action="store_true",dest="notes",
chris@1544 457 default=False,help="Annotate commits with the hg hash as git notes in the hg namespace")
chris@1544 458 parser.add_option("-e",dest="encoding",
chris@1544 459 help="Assume commit and author strings retrieved from Mercurial are encoded in <encoding>")
chris@1544 460 parser.add_option("--fe",dest="fn_encoding",
chris@1544 461 help="Assume file names from Mercurial are encoded in <filename_encoding>")
chris@1544 462
chris@1544 463 (options,args)=parser.parse_args()
chris@1544 464
chris@1544 465 m=-1
chris@1544 466 if options.max!=None: m=options.max
chris@1544 467
chris@1544 468 if options.marksfile==None: bail(parser,'--marks')
chris@1544 469 if options.mappingfile==None: bail(parser,'--mapping')
chris@1544 470 if options.headsfile==None: bail(parser,'--heads')
chris@1544 471 if options.statusfile==None: bail(parser,'--status')
chris@1544 472 if options.repourl==None: bail(parser,'--repo')
chris@1544 473
chris@1544 474 a={}
chris@1544 475 if options.authorfile!=None:
chris@1544 476 a=load_mapping('authors', options.authorfile)
chris@1544 477
chris@1544 478 b={}
chris@1544 479 if options.branchesfile!=None:
chris@1544 480 b=load_mapping('branches', options.branchesfile)
chris@1544 481
chris@1544 482 t={}
chris@1544 483 if options.tagsfile!=None:
chris@1544 484 t=load_mapping('tags', options.tagsfile)
chris@1544 485
chris@1544 486 if options.default_branch!=None:
chris@1544 487 set_default_branch(options.default_branch)
chris@1544 488
chris@1544 489 if options.origin_name!=None:
chris@1544 490 set_origin_name(options.origin_name)
chris@1544 491
chris@1544 492 encoding=''
chris@1544 493 if options.encoding!=None:
chris@1544 494 encoding=options.encoding
chris@1544 495
chris@1544 496 fn_encoding=encoding
chris@1544 497 if options.fn_encoding!=None:
chris@1544 498 fn_encoding=options.fn_encoding
chris@1544 499
chris@1544 500 sys.exit(hg2git(options.repourl,m,options.marksfile,options.mappingfile,
chris@1544 501 options.headsfile, options.statusfile,
chris@1544 502 authors=a,branchesmap=b,tagsmap=t,
chris@1544 503 sob=options.sob,force=options.force,hgtags=options.hgtags,
chris@1544 504 notes=options.notes,encoding=encoding,fn_encoding=fn_encoding))