##// END OF EJS Templates
convert_git: avoid returning two entries for the same file in getchanges...
Alexis S. L. Carvalho -
r5335:88e931f7 default
parent child Browse files
Show More
@@ -1,123 +1,128 b''
1 # git support for the convert extension
1 # git support for the convert extension
2
2
3 import os
3 import os
4 from mercurial import util
4 from mercurial import util
5
5
6 from common import NoRepo, commit, converter_source
6 from common import NoRepo, commit, converter_source
7
7
8 def recode(s):
8 def recode(s):
9 try:
9 try:
10 return s.decode("utf-8").encode("utf-8")
10 return s.decode("utf-8").encode("utf-8")
11 except:
11 except:
12 try:
12 try:
13 return s.decode("latin-1").encode("utf-8")
13 return s.decode("latin-1").encode("utf-8")
14 except:
14 except:
15 return s.decode("utf-8", "replace").encode("utf-8")
15 return s.decode("utf-8", "replace").encode("utf-8")
16
16
17 class convert_git(converter_source):
17 class convert_git(converter_source):
18 # Windows does not support GIT_DIR= construct while other systems
18 # Windows does not support GIT_DIR= construct while other systems
19 # cannot remove environment variable. Just assume none have
19 # cannot remove environment variable. Just assume none have
20 # both issues.
20 # both issues.
21 if hasattr(os, 'unsetenv'):
21 if hasattr(os, 'unsetenv'):
22 def gitcmd(self, s):
22 def gitcmd(self, s):
23 prevgitdir = os.environ.get('GIT_DIR')
23 prevgitdir = os.environ.get('GIT_DIR')
24 os.environ['GIT_DIR'] = self.path
24 os.environ['GIT_DIR'] = self.path
25 try:
25 try:
26 return os.popen(s)
26 return os.popen(s)
27 finally:
27 finally:
28 if prevgitdir is None:
28 if prevgitdir is None:
29 del os.environ['GIT_DIR']
29 del os.environ['GIT_DIR']
30 else:
30 else:
31 os.environ['GIT_DIR'] = prevgitdir
31 os.environ['GIT_DIR'] = prevgitdir
32 else:
32 else:
33 def gitcmd(self, s):
33 def gitcmd(self, s):
34 return os.popen('GIT_DIR=%s %s' % (self.path, s))
34 return os.popen('GIT_DIR=%s %s' % (self.path, s))
35
35
36 def __init__(self, ui, path):
36 def __init__(self, ui, path):
37 if os.path.isdir(path + "/.git"):
37 if os.path.isdir(path + "/.git"):
38 path += "/.git"
38 path += "/.git"
39 self.path = path
39 self.path = path
40 self.ui = ui
40 self.ui = ui
41 if not os.path.exists(path + "/objects"):
41 if not os.path.exists(path + "/objects"):
42 raise NoRepo("couldn't open GIT repo %s" % path)
42 raise NoRepo("couldn't open GIT repo %s" % path)
43
43
44 def getheads(self):
44 def getheads(self):
45 fh = self.gitcmd("git-rev-parse --verify HEAD")
45 fh = self.gitcmd("git-rev-parse --verify HEAD")
46 return [fh.read()[:-1]]
46 return [fh.read()[:-1]]
47
47
48 def catfile(self, rev, type):
48 def catfile(self, rev, type):
49 if rev == "0" * 40: raise IOError()
49 if rev == "0" * 40: raise IOError()
50 fh = self.gitcmd("git-cat-file %s %s 2>%s" % (type, rev,
50 fh = self.gitcmd("git-cat-file %s %s 2>%s" % (type, rev,
51 util.nulldev))
51 util.nulldev))
52 return fh.read()
52 return fh.read()
53
53
54 def getfile(self, name, rev):
54 def getfile(self, name, rev):
55 return self.catfile(rev, "blob")
55 return self.catfile(rev, "blob")
56
56
57 def getmode(self, name, rev):
57 def getmode(self, name, rev):
58 return self.modecache[(name, rev)]
58 return self.modecache[(name, rev)]
59
59
60 def getchanges(self, version):
60 def getchanges(self, version):
61 self.modecache = {}
61 self.modecache = {}
62 fh = self.gitcmd("git-diff-tree --root -m -r %s" % version)
62 fh = self.gitcmd("git-diff-tree --root -m -r %s" % version)
63 changes = []
63 changes = []
64 seen = {}
64 for l in fh:
65 for l in fh:
65 if "\t" not in l: continue
66 if "\t" not in l:
67 continue
66 m, f = l[:-1].split("\t")
68 m, f = l[:-1].split("\t")
69 if f in seen:
70 continue
71 seen[f] = 1
67 m = m.split()
72 m = m.split()
68 h = m[3]
73 h = m[3]
69 p = (m[1] == "100755")
74 p = (m[1] == "100755")
70 s = (m[1] == "120000")
75 s = (m[1] == "120000")
71 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
76 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
72 changes.append((f, h))
77 changes.append((f, h))
73 return changes
78 return changes
74
79
75 def getcommit(self, version):
80 def getcommit(self, version):
76 c = self.catfile(version, "commit") # read the commit hash
81 c = self.catfile(version, "commit") # read the commit hash
77 end = c.find("\n\n")
82 end = c.find("\n\n")
78 message = c[end+2:]
83 message = c[end+2:]
79 message = recode(message)
84 message = recode(message)
80 l = c[:end].splitlines()
85 l = c[:end].splitlines()
81 manifest = l[0].split()[1]
86 manifest = l[0].split()[1]
82 parents = []
87 parents = []
83 for e in l[1:]:
88 for e in l[1:]:
84 n, v = e.split(" ", 1)
89 n, v = e.split(" ", 1)
85 if n == "author":
90 if n == "author":
86 p = v.split()
91 p = v.split()
87 tm, tz = p[-2:]
92 tm, tz = p[-2:]
88 author = " ".join(p[:-2])
93 author = " ".join(p[:-2])
89 if author[0] == "<": author = author[1:-1]
94 if author[0] == "<": author = author[1:-1]
90 author = recode(author)
95 author = recode(author)
91 if n == "committer":
96 if n == "committer":
92 p = v.split()
97 p = v.split()
93 tm, tz = p[-2:]
98 tm, tz = p[-2:]
94 committer = " ".join(p[:-2])
99 committer = " ".join(p[:-2])
95 if committer[0] == "<": committer = committer[1:-1]
100 if committer[0] == "<": committer = committer[1:-1]
96 committer = recode(committer)
101 committer = recode(committer)
97 message += "\ncommitter: %s\n" % committer
102 message += "\ncommitter: %s\n" % committer
98 if n == "parent": parents.append(v)
103 if n == "parent": parents.append(v)
99
104
100 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
105 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
101 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
106 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
102 date = tm + " " + str(tz)
107 date = tm + " " + str(tz)
103 author = author or "unknown"
108 author = author or "unknown"
104
109
105 c = commit(parents=parents, date=date, author=author, desc=message)
110 c = commit(parents=parents, date=date, author=author, desc=message)
106 return c
111 return c
107
112
108 def gettags(self):
113 def gettags(self):
109 tags = {}
114 tags = {}
110 fh = self.gitcmd('git-ls-remote --tags "%s" 2>%s' % (self.path,
115 fh = self.gitcmd('git-ls-remote --tags "%s" 2>%s' % (self.path,
111 util.nulldev))
116 util.nulldev))
112 prefix = 'refs/tags/'
117 prefix = 'refs/tags/'
113 for line in fh:
118 for line in fh:
114 line = line.strip()
119 line = line.strip()
115 if not line.endswith("^{}"):
120 if not line.endswith("^{}"):
116 continue
121 continue
117 node, tag = line.split(None, 1)
122 node, tag = line.split(None, 1)
118 if not tag.startswith(prefix):
123 if not tag.startswith(prefix):
119 continue
124 continue
120 tag = tag[len(prefix):-3]
125 tag = tag[len(prefix):-3]
121 tags[tag] = node
126 tags[tag] = node
122
127
123 return tags
128 return tags
@@ -1,19 +1,46 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 "$TESTDIR/hghave" git || exit 80
3 "$TESTDIR/hghave" git || exit 80
4
4
5 echo "[extensions]" >> $HGRCPATH
5 echo "[extensions]" >> $HGRCPATH
6 echo "convert=" >> $HGRCPATH
6 echo "convert=" >> $HGRCPATH
7
7
8 GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
9 GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
10 GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
11 GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
12 GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
13 GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
14
15 count=10
16 commit()
17 {
18 GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000"
19 GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
20 git commit "$@" >/dev/null 2>/dev/null || echo "git commit error"
21 count=`expr $count + 1`
22 }
23
8 mkdir git-repo
24 mkdir git-repo
9 cd git-repo
25 cd git-repo
10 git init-db >/dev/null 2>/dev/null
26 git init-db >/dev/null 2>/dev/null
11 echo a > a
27 echo a > a
12 git add a
28 git add a
13 git commit -m t1 >/dev/null 2>/dev/null || echo "git commit error"
29 commit -m t1
30
14 echo b >> a
31 echo b >> a
15 git commit -a -m t2 >/dev/null || echo "git commit error"
32 commit -a -m t2.1
33
34 git checkout -b other HEAD^ >/dev/null 2>/dev/null
35 echo c > a
36 echo a >> a
37 commit -a -m t2.2
38
39 git checkout master >/dev/null 2>/dev/null
40 git pull --no-commit . other > /dev/null 2>/dev/null
41 commit -m 'Merge branch other'
16 cd ..
42 cd ..
17
43
18 hg convert git-repo
44 hg convert --datesort git-repo
19
45
46 hg -R git-repo-hg tip -v
@@ -1,7 +1,22 b''
1 assuming destination git-repo-hg
1 assuming destination git-repo-hg
2 initializing destination git-repo-hg repository
2 initializing destination git-repo-hg repository
3 scanning source...
3 scanning source...
4 sorting...
4 sorting...
5 converting...
5 converting...
6 1 t1
6 3 t1
7 0 t2
7 2 t2.1
8 1 t2.2
9 0 Merge branch other
10 changeset: 3:f0873470732d
11 tag: tip
12 parent: 1:cb991dbbb06b
13 parent: 2:600bef931ca4
14 user: test <test@example.org>
15 date: Mon Jan 01 00:00:13 2007 +0000
16 files: a
17 description:
18 Merge branch other
19
20 committer: test <test@example.org>
21
22
General Comments 0
You need to be logged in to leave comments. Login now