Fix TypeError when using -M command line argument
[fast-export.git] / hg2git.py
blob3839f539fc311409796aec8c22a8418e6d3de0b1
1 #!/usr/bin/env python2
3 # Copyright (c) 2007, 2008 Rocco Rutte <pdmef@gmx.net> and others.
4 # License: MIT <http://www.opensource.org/licenses/mit-license.php>
6 from mercurial import hg,util,ui,templatefilters
7 from mercurial import error as hgerror
8 from mercurial.scmutil import revsymbol,binnode
10 import re
11 import os
12 import sys
13 import subprocess
15 PY2 = sys.version_info.major < 3
16 if PY2:
17 str = unicode
18 fsencode = lambda s: s.encode(sys.getfilesystemencoding())
19 else:
20 from os import fsencode
22 # default git branch name
23 cfg_master=b'master'
24 # default origin name
25 origin_name=b''
26 # silly regex to see if user field has email address
27 user_re=re.compile(b'([^<]+) (<[^>]*>)$')
28 # silly regex to clean out user names
29 user_clean_re=re.compile(b'^["]([^"]+)["]$')
31 def set_default_branch(name):
32 global cfg_master
33 cfg_master = name.encode('utf8') if not isinstance(name, bytes) else name
35 def set_origin_name(name):
36 global origin_name
37 origin_name = name
39 def setup_repo(url):
40 try:
41 myui=ui.ui(interactive=False)
42 except TypeError:
43 myui=ui.ui()
44 myui.setconfig(b'ui', b'interactive', b'off')
45 # Avoids a warning when the repository has obsolete markers
46 myui.setconfig(b'experimental', b'evolution.createmarkers', True)
47 return myui,hg.repository(myui, fsencode(url)).unfiltered()
49 def fixup_user(user,authors):
50 user=user.strip(b"\"")
51 if authors!=None:
52 # if we have an authors table, try to get mapping
53 # by defaulting to the current value of 'user'
54 user=authors.get(user,user)
55 name,mail,m=b'',b'',user_re.match(user)
56 if m==None:
57 # if we don't have 'Name <mail>' syntax, extract name
58 # and mail from hg helpers. this seems to work pretty well.
59 # if email doesn't contain @, replace it with devnull@localhost
60 name=templatefilters.person(user)
61 mail=b'<%s>' % templatefilters.email(user)
62 if b'@' not in mail:
63 mail = b'<devnull@localhost>'
64 else:
65 # if we have 'Name <mail>' syntax, everything is fine :)
66 name,mail=m.group(1),m.group(2)
68 # remove any silly quoting from username
69 m2=user_clean_re.match(name)
70 if m2!=None:
71 name=m2.group(1)
72 return b'%s %s' % (name,mail)
74 def get_branch(name):
75 # 'HEAD' is the result of a bug in mutt's cvs->hg conversion,
76 # other CVS imports may need it, too
77 if name==b'HEAD' or name==b'default' or name==b'':
78 name=cfg_master
79 if origin_name:
80 return origin_name + b'/' + name
81 return name
83 def get_changeset(ui,repo,revision,authors={},encoding=''):
84 # Starting with Mercurial 4.6 lookup no longer accepts raw hashes
85 # for lookups. Work around it by changing our behaviour depending on
86 # how it fails
87 try:
88 node=repo.lookup(revision)
89 except (TypeError, hgerror.ProgrammingError):
90 node=binnode(revsymbol(repo, b"%d" % revision)) # We were given a numeric rev
91 except hgerror.RepoLookupError:
92 node=revision # We got a raw hash
93 (manifest,user,(time,timezone),files,desc,extra)=repo.changelog.read(node)
94 if encoding:
95 user=user.decode(encoding).encode('utf8')
96 desc=desc.decode(encoding).encode('utf8')
97 tz=b"%+03d%02d" % (-timezone // 3600, ((-timezone % 3600) // 60))
98 branch=get_branch(extra.get(b'branch', b'master'))
99 return (node,manifest,fixup_user(user,authors),(time,tz),files,desc,branch,extra)
101 def mangle_key(key):
102 return key
104 def load_cache(filename,get_key=mangle_key):
105 cache={}
106 if not os.path.exists(filename):
107 return cache
108 f=open(filename,'rb')
110 for line in f.readlines():
111 l+=1
112 fields=line.split(b' ')
113 if fields==None or not len(fields)==2 or fields[0][0:1]!=b':':
114 sys.stderr.write('Invalid file format in [%s], line %d\n' % (filename,l))
115 continue
116 # put key:value in cache, key without ^:
117 cache[get_key(fields[0][1:])]=fields[1].split(b'\n')[0]
118 f.close()
119 return cache
121 def save_cache(filename,cache):
122 f=open(filename,'wb')
123 for key, value in cache.items():
124 if not isinstance(key, bytes):
125 key = str(key).encode('utf8')
126 if not isinstance(value, bytes):
127 value = str(value).encode('utf8')
128 f.write(b':%s %s\n' % (key, value))
129 f.close()
131 def get_git_sha1(name,type='heads'):
132 try:
133 # use git-rev-parse to support packed refs
134 ref="refs/%s/%s" % (type,name.decode('utf8'))
135 l=subprocess.check_output(["git", "rev-parse", "--verify", "--quiet", ref])
136 if l == None or len(l) == 0:
137 return None
138 return l[0:40]
139 except subprocess.CalledProcessError:
140 return None