##// END OF EJS Templates
convert: read git output in binary mode under Windows (issue 1359)
Patrick Mezard -
r7222:c1dc903d default
parent child Browse files
Show More
@@ -1,142 +1,142 b''
1 1 # git support for the convert extension
2 2
3 3 import os
4 4 from mercurial import util
5 5
6 6 from common import NoRepo, commit, converter_source, checktool
7 7
8 8 class convert_git(converter_source):
9 9 # Windows does not support GIT_DIR= construct while other systems
10 10 # cannot remove environment variable. Just assume none have
11 11 # both issues.
12 12 if hasattr(os, 'unsetenv'):
13 13 def gitcmd(self, s):
14 14 prevgitdir = os.environ.get('GIT_DIR')
15 15 os.environ['GIT_DIR'] = self.path
16 16 try:
17 return util.popen(s)
17 return util.popen(s, 'rb')
18 18 finally:
19 19 if prevgitdir is None:
20 20 del os.environ['GIT_DIR']
21 21 else:
22 22 os.environ['GIT_DIR'] = prevgitdir
23 23 else:
24 24 def gitcmd(self, s):
25 return util.popen('GIT_DIR=%s %s' % (self.path, s))
25 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
26 26
27 27 def __init__(self, ui, path, rev=None):
28 28 super(convert_git, self).__init__(ui, path, rev=rev)
29 29
30 30 if os.path.isdir(path + "/.git"):
31 31 path += "/.git"
32 32 if not os.path.exists(path + "/objects"):
33 33 raise NoRepo("%s does not look like a Git repo" % path)
34 34
35 35 checktool('git', 'git')
36 36
37 37 self.path = path
38 38
39 39 def getheads(self):
40 40 if not self.rev:
41 41 return self.gitcmd('git rev-parse --branches').read().splitlines()
42 42 else:
43 43 fh = self.gitcmd("git rev-parse --verify %s" % self.rev)
44 44 return [fh.read()[:-1]]
45 45
46 46 def catfile(self, rev, type):
47 47 if rev == "0" * 40: raise IOError()
48 48 fh = self.gitcmd("git cat-file %s %s" % (type, rev))
49 49 return fh.read()
50 50
51 51 def getfile(self, name, rev):
52 52 return self.catfile(rev, "blob")
53 53
54 54 def getmode(self, name, rev):
55 55 return self.modecache[(name, rev)]
56 56
57 57 def getchanges(self, version):
58 58 self.modecache = {}
59 59 fh = self.gitcmd("git diff-tree --root -m -r %s" % version)
60 60 changes = []
61 61 seen = {}
62 62 for l in fh:
63 63 if "\t" not in l:
64 64 continue
65 65 m, f = l[:-1].split("\t")
66 66 if f in seen:
67 67 continue
68 68 seen[f] = 1
69 69 m = m.split()
70 70 h = m[3]
71 71 p = (m[1] == "100755")
72 72 s = (m[1] == "120000")
73 73 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
74 74 changes.append((f, h))
75 75 return (changes, {})
76 76
77 77 def getcommit(self, version):
78 78 c = self.catfile(version, "commit") # read the commit hash
79 79 end = c.find("\n\n")
80 80 message = c[end+2:]
81 81 message = self.recode(message)
82 82 l = c[:end].splitlines()
83 83 manifest = l[0].split()[1]
84 84 parents = []
85 85 for e in l[1:]:
86 86 n, v = e.split(" ", 1)
87 87 if n == "author":
88 88 p = v.split()
89 89 tm, tz = p[-2:]
90 90 author = " ".join(p[:-2])
91 91 if author[0] == "<": author = author[1:-1]
92 92 author = self.recode(author)
93 93 if n == "committer":
94 94 p = v.split()
95 95 tm, tz = p[-2:]
96 96 committer = " ".join(p[:-2])
97 97 if committer[0] == "<": committer = committer[1:-1]
98 98 committer = self.recode(committer)
99 99 message += "\ncommitter: %s\n" % committer
100 100 if n == "parent": parents.append(v)
101 101
102 102 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
103 103 tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
104 104 date = tm + " " + str(tz)
105 105
106 106 c = commit(parents=parents, date=date, author=author, desc=message,
107 107 rev=version)
108 108 return c
109 109
110 110 def gettags(self):
111 111 tags = {}
112 112 fh = self.gitcmd('git ls-remote --tags "%s"' % self.path)
113 113 prefix = 'refs/tags/'
114 114 for line in fh:
115 115 line = line.strip()
116 116 if not line.endswith("^{}"):
117 117 continue
118 118 node, tag = line.split(None, 1)
119 119 if not tag.startswith(prefix):
120 120 continue
121 121 tag = tag[len(prefix):-3]
122 122 tags[tag] = node
123 123
124 124 return tags
125 125
126 126 def getchangedfiles(self, version, i):
127 127 changes = []
128 128 if i is None:
129 129 fh = self.gitcmd("git diff-tree --root -m -r %s" % version)
130 130 for l in fh:
131 131 if "\t" not in l:
132 132 continue
133 133 m, f = l[:-1].split("\t")
134 134 changes.append(f)
135 135 fh.close()
136 136 else:
137 137 fh = self.gitcmd('git diff-tree --name-only --root -r %s "%s^%s" --'
138 138 % (version, version, i+1))
139 139 changes = [f.rstrip('\n') for f in fh]
140 140 fh.close()
141 141
142 142 return changes
@@ -1,132 +1,149 b''
1 1 #!/bin/sh
2 2
3 3 "$TESTDIR/hghave" git || exit 80
4 4
5 5 echo "[extensions]" >> $HGRCPATH
6 6 echo "convert=" >> $HGRCPATH
7 7 echo 'hgext.graphlog =' >> $HGRCPATH
8 8
9 9 GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
10 10 GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
11 11 GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
12 12 GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"; export GIT_COMMITTER_NAME
13 13 GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"; export GIT_COMMITTER_EMAIL
14 14 GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"; export GIT_COMMITTER_DATE
15 15
16 16 count=10
17 17 commit()
18 18 {
19 19 GIT_AUTHOR_DATE="2007-01-01 00:00:$count +0000"
20 20 GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
21 21 git commit "$@" >/dev/null 2>/dev/null || echo "git commit error"
22 22 count=`expr $count + 1`
23 23 }
24 24
25 25 mkdir git-repo
26 26 cd git-repo
27 27 git init-db >/dev/null 2>/dev/null
28 28 echo a > a
29 29 mkdir d
30 30 echo b > d/b
31 31 git add a d
32 32 commit -a -m t1
33 33
34 34 # Remove the directory, then try to replace it with a file
35 35 # (issue 754)
36 36 git rm -f d/b
37 37 commit -m t2
38 38 echo d > d
39 39 git add d
40 40 commit -m t3
41 41
42 42 echo b >> a
43 43 commit -a -m t4.1
44 44
45 45 git checkout -b other HEAD^ >/dev/null 2>/dev/null
46 46 echo c > a
47 47 echo a >> a
48 48 commit -a -m t4.2
49 49
50 50 git checkout master >/dev/null 2>/dev/null
51 51 git pull --no-commit . other > /dev/null 2>/dev/null
52 52 commit -m 'Merge branch other'
53 53 cd ..
54 54
55 55 hg convert --datesort git-repo
56 56
57 57 hg -R git-repo-hg tip -v
58 58
59 59 count=10
60 60 mkdir git-repo2
61 61 cd git-repo2
62 62 git init-db >/dev/null 2>/dev/null
63 63
64 64 echo foo > foo
65 65 git add foo
66 66 commit -a -m 'add foo'
67 67
68 68 echo >> foo
69 69 commit -a -m 'change foo'
70 70
71 71 git checkout -b Bar HEAD^ >/dev/null 2>/dev/null
72 72 echo quux >> quux
73 73 git add quux
74 74 commit -a -m 'add quux'
75 75
76 76 echo bar > bar
77 77 git add bar
78 78 commit -a -m 'add bar'
79 79
80 80 git checkout -b Baz HEAD^ >/dev/null 2>/dev/null
81 81 echo baz > baz
82 82 git add baz
83 83 commit -a -m 'add baz'
84 84
85 85 git checkout master >/dev/null 2>/dev/null
86 86 git pull --no-commit . Bar Baz > /dev/null 2>/dev/null
87 87 commit -m 'Octopus merge'
88 88
89 89 echo bar >> bar
90 90 commit -a -m 'change bar'
91 91
92 92 git checkout -b Foo HEAD^ >/dev/null 2>/dev/null
93 93 echo >> foo
94 94 commit -a -m 'change foo'
95 95
96 96 git checkout master >/dev/null 2>/dev/null
97 97 git pull --no-commit -s ours . Foo > /dev/null 2>/dev/null
98 98 commit -m 'Discard change to foo'
99 99
100 100 cd ..
101 101
102 102 glog()
103 103 {
104 104 hg glog --template '#rev# "#desc|firstline#" files: #files#\n' "$@"
105 105 }
106 106
107 107 splitrepo()
108 108 {
109 109 msg="$1"
110 110 files="$2"
111 111 opts=$3
112 112 echo "% $files: $msg"
113 113 prefix=`echo "$files" | sed -e 's/ /-/g'`
114 114 fmap="$prefix.fmap"
115 115 repo="$prefix.repo"
116 116 for i in $files; do
117 117 echo "include $i" >> "$fmap"
118 118 done
119 119 hg -q convert $opts --filemap "$fmap" --datesort git-repo2 "$repo"
120 120 glog -R "$repo"
121 121 hg -R "$repo" manifest --debug
122 122 }
123 123
124 124 echo '% full conversion'
125 125 hg -q convert --datesort git-repo2 fullrepo
126 126 glog -R fullrepo
127 127 hg -R fullrepo manifest --debug
128 128
129 129 splitrepo 'octopus merge' 'foo bar baz'
130 130
131 131 splitrepo 'only some parents of an octopus merge; "discard" a head' 'foo baz quux'
132 132
133 echo
134 echo '% test binary conversion (issue 1359)'
135 mkdir git-repo3
136 cd git-repo3
137 git init-db >/dev/null 2>/dev/null
138 python -c 'file("b", "wb").write("".join([chr(i) for i in range(256)])*16)'
139 git add b
140 commit -a -m addbinary
141 cd ..
142
143 echo '% convert binary file'
144 hg convert git-repo3 git-repo3-hg
145
146 cd git-repo3-hg
147 hg up -C
148 python -c 'print len(file("b", "rb").read())'
149
@@ -1,90 +1,100 b''
1 1 rm 'd/b'
2 2 assuming destination git-repo-hg
3 3 initializing destination git-repo-hg repository
4 4 scanning source...
5 5 sorting...
6 6 converting...
7 7 5 t1
8 8 4 t2
9 9 3 t3
10 10 2 t4.1
11 11 1 t4.2
12 12 0 Merge branch other
13 13 changeset: 5:4ab1af49a271
14 14 tag: tip
15 15 parent: 3:0222ab0998d7
16 16 parent: 4:5333c870e3c2
17 17 user: test <test@example.org>
18 18 date: Mon Jan 01 00:00:15 2007 +0000
19 19 files: a
20 20 description:
21 21 Merge branch other
22 22
23 23 committer: test <test@example.org>
24 24
25 25
26 26 % full conversion
27 27 o 9 "Discard change to foo" files: foo
28 28 |\
29 29 | o 8 "change foo" files: foo
30 30 | |
31 31 o | 7 "change bar" files: bar
32 32 |/
33 33 o 6 "(octopus merge fixup)" files:
34 34 |\
35 35 | o 5 "Octopus merge" files: baz
36 36 | |\
37 37 o | | 4 "add baz" files: baz
38 38 | | |
39 39 +---o 3 "add bar" files: bar
40 40 | |
41 41 o | 2 "add quux" files: quux
42 42 | |
43 43 | o 1 "change foo" files: foo
44 44 |/
45 45 o 0 "add foo" files: foo
46 46
47 47 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
48 48 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
49 49 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
50 50 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
51 51 % foo bar baz: octopus merge
52 52 o 8 "Discard change to foo" files: foo
53 53 |\
54 54 | o 7 "change foo" files: foo
55 55 | |
56 56 o | 6 "change bar" files: bar
57 57 |/
58 58 o 5 "(octopus merge fixup)" files:
59 59 |\
60 60 | o 4 "Octopus merge" files: baz
61 61 | |\
62 62 o | | 3 "add baz" files: baz
63 63 | | |
64 64 +---o 2 "add bar" files: bar
65 65 | |
66 66 | o 1 "change foo" files: foo
67 67 |/
68 68 o 0 "add foo" files: foo
69 69
70 70 245a3b8bc653999c2b22cdabd517ccb47aecafdf 644 bar
71 71 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
72 72 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
73 73 % foo baz quux: only some parents of an octopus merge; "discard" a head
74 74 o 6 "Discard change to foo" files: foo
75 75 |
76 76 o 5 "change foo" files: foo
77 77 |
78 78 o 4 "Octopus merge" files:
79 79 |\
80 80 | o 3 "add baz" files: baz
81 81 | |
82 82 | o 2 "add quux" files: quux
83 83 | |
84 84 o | 1 "change foo" files: foo
85 85 |/
86 86 o 0 "add foo" files: foo
87 87
88 88 354ae8da6e890359ef49ade27b68bbc361f3ca88 644 baz
89 89 9277c9cc8dd4576fc01a17939b4351e5ada93466 644 foo
90 90 88dfeab657e8cf2cef3dec67b914f49791ae76b1 644 quux
91
92 % test binary conversion (issue 1359)
93 % convert binary file
94 initializing destination git-repo3-hg repository
95 scanning source...
96 sorting...
97 converting...
98 0 addbinary
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 4096
General Comments 0
You need to be logged in to leave comments. Login now