##// END OF EJS Templates
convert: cvs.py - Allow user to use built-in CVS changeset code....
Frank Kingswood -
r6690:127e8c34 default
parent child Browse files
Show More
@@ -0,0 +1,60
1 #!/bin/sh
2
3 # This is http://www.selenic.com/mercurial/bts/issue1148
4
5 "$TESTDIR/hghave" cvs || exit 80
6
7 cvscall()
8 {
9 cvs -f "$@"
10 }
11
12 echo "[extensions]" >> $HGRCPATH
13 echo "convert = " >> $HGRCPATH
14 echo "graphlog = " >> $HGRCPATH
15 echo "[convert]" >> $HGRCPATH
16 echo "cvsps=builtin" >> $HGRCPATH
17
18 echo % create cvs repository
19 mkdir cvsrepo
20 cd cvsrepo
21 export CVSROOT=`pwd`
22 export CVS_OPTIONS=-f
23 cd ..
24
25 cvscall -q -d "$CVSROOT" init
26
27 echo % Create a new project
28
29 mkdir src
30 cd src
31 echo "1" > a > b
32 cvscall import -m "init" src v0 r0
33 cd ..
34 cvscall co src
35 cd src
36
37 echo % Branch the project
38
39 cvscall tag -b BRANCH
40 cvscall up -r BRANCH
41
42 echo % Modify file a, then b, then a
43
44 echo "2" > a
45 cvscall ci -m "mod a" | grep '<--' | sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
46
47 echo "2" > b
48 cvscall ci -m "mod b" | grep '<--' | sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
49
50 echo "3" > a
51 cvscall ci -m "mod a again" | grep '<--' | sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
52
53 echo % Convert
54
55 cd ..
56 hg convert src | sed -e 's/connecting to.*cvsrepo/connecting to cvsrepo/g'
57
58 echo % Check the result
59
60 hg -R src-hg glog --template '#rev# (#branches#) #desc# files: #files#\n'
@@ -0,0 +1,53
1 % create cvs repository
2 % Create a new project
3 N src/a
4 N src/b
5
6 No conflicts created by this import
7
8 cvs checkout: Updating src
9 U src/a
10 U src/b
11 % Branch the project
12 cvs tag: Tagging .
13 T a
14 T b
15 cvs update: Updating .
16 % Modify file a, then b, then a
17 cvs commit: Examining .
18 checking in src/a,v
19 cvs commit: Examining .
20 checking in src/b,v
21 cvs commit: Examining .
22 checking in src/a,v
23 % Convert
24 assuming destination src-hg
25 initializing destination src-hg repository
26 using builtin cvsps
27 collecting CVS rlog
28 7 log entries
29 creating changesets
30 5 changeset entries
31 connecting to cvsrepo
32 scanning source...
33 sorting...
34 converting...
35 4 Initial revision
36 3 init
37 2 mod a
38 1 mod b
39 0 mod a again
40 updating tags
41 % Check the result
42 o 5 () update tags files: .hgtags
43 |
44 | o 4 (BRANCH) mod a again files: a
45 | |
46 | o 3 (BRANCH) mod b files: b
47 | |
48 | o 2 (BRANCH) mod a files: a
49 | |
50 | o 1 (v0) init files:
51 |/
52 o 0 () Initial revision files: a b
53
@@ -0,0 +1,99
1 #!/bin/sh
2
3 "$TESTDIR/hghave" cvs || exit 80
4
5 cvscall()
6 {
7 cvs -f "$@"
8 }
9
10 echo "[extensions]" >> $HGRCPATH
11 echo "convert = " >> $HGRCPATH
12 echo "graphlog = " >> $HGRCPATH
13 echo "[convert]" >> $HGRCPATH
14 echo "cvsps=builtin" >> $HGRCPATH
15
16 echo % create cvs repository
17 mkdir cvsrepo
18 cd cvsrepo
19 export CVSROOT=`pwd`
20 export CVS_OPTIONS=-f
21 cd ..
22
23 cvscall -q -d "$CVSROOT" init
24
25 echo % create source directory
26 mkdir src-temp
27 cd src-temp
28 echo a > a
29 mkdir b
30 cd b
31 echo c > c
32 cd ..
33
34 echo % import source directory
35 cvscall -q import -m import src INITIAL start
36 cd ..
37
38 echo % checkout source directory
39 cvscall -q checkout src
40
41 echo % commit a new revision changing b/c
42 cd src
43 sleep 1
44 echo c >> b/c
45 cvscall -q commit -mci0 . | grep '<--' |\
46 sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
47 cd ..
48
49 echo % convert fresh repo
50 hg convert src src-hg | sed -e 's/connecting to.*cvsrepo/connecting to cvsrepo/g'
51 cat src-hg/a
52 cat src-hg/b/c
53
54 echo % convert fresh repo with --filemap
55 echo include b/c > filemap
56 hg convert --filemap filemap src src-filemap | sed -e 's/connecting to.*cvsrepo/connecting to cvsrepo/g'
57 cat src-hg/b/c
58 hg -R src-filemap log --template '#rev# #desc# files: #files#\n'
59
60 echo % commit new file revisions
61 cd src
62 echo a >> a
63 echo c >> b/c
64 cvscall -q commit -mci1 . | grep '<--' |\
65 sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
66 cd ..
67
68 echo % convert again
69 hg convert src src-hg | sed -e 's/connecting to.*cvsrepo/connecting to cvsrepo/g'
70 cat src-hg/a
71 cat src-hg/b/c
72
73 echo % convert again with --filemap
74 hg convert --filemap filemap src src-filemap | sed -e 's/connecting to.*cvsrepo/connecting to cvsrepo/g'
75 cat src-hg/b/c
76 hg -R src-filemap log --template '#rev# #desc# files: #files#\n'
77
78 echo % commit branch
79 cd src
80 cvs -q update -r1.1 b/c
81 cvs -q tag -b branch
82 cvs -q update -r branch
83 echo d >> b/c
84 cvs -q commit -mci2 . | grep '<--' |\
85 sed -e 's:.*src/\(.*\),v.*:checking in src/\1,v:g'
86 cd ..
87
88 echo % convert again
89 hg convert src src-hg | sed -e 's/connecting to.*cvsrepo/connecting to cvsrepo/g'
90 cat src-hg/a
91 cat src-hg/b/c
92
93 echo % convert again with --filemap
94 hg convert --filemap filemap src src-filemap | sed -e 's/connecting to.*cvsrepo/connecting to cvsrepo/g'
95 cat src-hg/b/c
96 hg -R src-filemap log --template '#rev# #desc# files: #files#\n'
97
98 echo "graphlog = " >> $HGRCPATH
99 hg -R src-hg glog --template '#rev# (#branches#) #desc# files: #files#\n'
@@ -0,0 +1,139
1 % create cvs repository
2 % create source directory
3 % import source directory
4 N src/a
5 N src/b/c
6
7 No conflicts created by this import
8
9 % checkout source directory
10 U src/a
11 U src/b/c
12 % commit a new revision changing b/c
13 checking in src/b/c,v
14 % convert fresh repo
15 initializing destination src-hg repository
16 using builtin cvsps
17 collecting CVS rlog
18 5 log entries
19 creating changesets
20 3 changeset entries
21 connecting to cvsrepo
22 scanning source...
23 sorting...
24 converting...
25 2 Initial revision
26 1 import
27 0 ci0
28 updating tags
29 a
30 c
31 c
32 % convert fresh repo with --filemap
33 initializing destination src-filemap repository
34 using builtin cvsps
35 collecting CVS rlog
36 5 log entries
37 creating changesets
38 3 changeset entries
39 connecting to cvsrepo
40 scanning source...
41 sorting...
42 converting...
43 2 Initial revision
44 1 import
45 rolling back last transaction
46 0 ci0
47 updating tags
48 c
49 c
50 2 update tags files: .hgtags
51 1 ci0 files: b/c
52 0 Initial revision files: b/c
53 % commit new file revisions
54 checking in src/a,v
55 checking in src/b/c,v
56 % convert again
57 using builtin cvsps
58 collecting CVS rlog
59 7 log entries
60 creating changesets
61 4 changeset entries
62 connecting to cvsrepo
63 scanning source...
64 sorting...
65 converting...
66 0 ci1
67 a
68 a
69 c
70 c
71 c
72 % convert again with --filemap
73 using builtin cvsps
74 collecting CVS rlog
75 7 log entries
76 creating changesets
77 4 changeset entries
78 connecting to cvsrepo
79 scanning source...
80 sorting...
81 converting...
82 0 ci1
83 c
84 c
85 c
86 3 ci1 files: b/c
87 2 update tags files: .hgtags
88 1 ci0 files: b/c
89 0 Initial revision files: b/c
90 % commit branch
91 U b/c
92 T a
93 T b/c
94 checking in src/b/c,v
95 % convert again
96 using builtin cvsps
97 collecting CVS rlog
98 8 log entries
99 creating changesets
100 5 changeset entries
101 connecting to cvsrepo
102 scanning source...
103 sorting...
104 converting...
105 0 ci2
106 a
107 a
108 c
109 d
110 % convert again with --filemap
111 using builtin cvsps
112 collecting CVS rlog
113 8 log entries
114 creating changesets
115 5 changeset entries
116 connecting to cvsrepo
117 scanning source...
118 sorting...
119 converting...
120 0 ci2
121 c
122 d
123 4 ci2 files: b/c
124 3 ci1 files: b/c
125 2 update tags files: .hgtags
126 1 ci0 files: b/c
127 0 Initial revision files: b/c
128 o 5 (branch) ci2 files: b/c
129 |
130 | o 4 () ci1 files: a b/c
131 | |
132 | o 3 () update tags files: .hgtags
133 | |
134 | o 2 () ci0 files: b/c
135 |/
136 | o 1 (INITIAL) import files:
137 |/
138 o 0 () Initial revision files: a b/c
139
@@ -1,315 +1,355
1 1 # CVS conversion code inspired by hg-cvs-import and git-cvsimport
2 2
3 3 import os, locale, re, socket
4 4 from cStringIO import StringIO
5 5 from mercurial import util
6 from mercurial.i18n import _
6 7
7 8 from common import NoRepo, commit, converter_source, checktool
9 import cvsps
8 10
9 11 class convert_cvs(converter_source):
10 12 def __init__(self, ui, path, rev=None):
11 13 super(convert_cvs, self).__init__(ui, path, rev=rev)
12 14
13 15 cvs = os.path.join(path, "CVS")
14 16 if not os.path.exists(cvs):
15 17 raise NoRepo("%s does not look like a CVS checkout" % path)
16 18
19 checktool('cvs')
17 20 self.cmd = ui.config('convert', 'cvsps', 'cvsps -A -u --cvs-direct -q')
18 21 cvspsexe = self.cmd.split(None, 1)[0]
19 for tool in (cvspsexe, 'cvs'):
20 checktool(tool)
22 self.builtin = cvspsexe == 'builtin'
23
24 if not self.builtin:
25 checktool(cvspsexe)
21 26
22 27 self.changeset = {}
23 28 self.files = {}
24 29 self.tags = {}
25 30 self.lastbranch = {}
26 31 self.parent = {}
27 32 self.socket = None
28 33 self.cvsroot = file(os.path.join(cvs, "Root")).read()[:-1]
29 34 self.cvsrepo = file(os.path.join(cvs, "Repository")).read()[:-1]
30 35 self.encoding = locale.getpreferredencoding()
31 self._parse()
36
37 self._parse(ui)
32 38 self._connect()
33 39
34 def _parse(self):
40 def _parse(self, ui):
35 41 if self.changeset:
36 42 return
37 43
38 44 maxrev = 0
39 45 cmd = self.cmd
40 46 if self.rev:
41 47 # TODO: handle tags
42 48 try:
43 49 # patchset number?
44 50 maxrev = int(self.rev)
45 51 except ValueError:
46 52 try:
47 53 # date
48 54 util.parsedate(self.rev, ['%Y/%m/%d %H:%M:%S'])
49 55 cmd = '%s -d "1970/01/01 00:00:01" -d "%s"' % (cmd, self.rev)
50 56 except util.Abort:
51 57 raise util.Abort('revision %s is not a patchset number or date' % self.rev)
52 58
53 59 d = os.getcwd()
54 60 try:
55 61 os.chdir(self.path)
56 62 id = None
57 63 state = 0
58 64 filerevids = {}
59 for l in util.popen(cmd):
60 if state == 0: # header
61 if l.startswith("PatchSet"):
62 id = l[9:-2]
63 if maxrev and int(id) > maxrev:
64 # ignore everything
65 state = 3
66 elif l.startswith("Date"):
67 date = util.parsedate(l[6:-1], ["%Y/%m/%d %H:%M:%S"])
68 date = util.datestr(date)
69 elif l.startswith("Branch"):
70 branch = l[8:-1]
71 self.parent[id] = self.lastbranch.get(branch, 'bad')
72 self.lastbranch[branch] = id
73 elif l.startswith("Ancestor branch"):
74 ancestor = l[17:-1]
75 # figure out the parent later
76 self.parent[id] = self.lastbranch[ancestor]
77 elif l.startswith("Author"):
78 author = self.recode(l[8:-1])
79 elif l.startswith("Tag:") or l.startswith("Tags:"):
80 t = l[l.index(':')+1:]
81 t = [ut.strip() for ut in t.split(',')]
82 if (len(t) > 1) or (t[0] and (t[0] != "(none)")):
83 self.tags.update(dict.fromkeys(t, id))
84 elif l.startswith("Log:"):
85 # switch to gathering log
86 state = 1
87 log = ""
88 elif state == 1: # log
89 if l == "Members: \n":
90 # switch to gathering members
91 files = {}
92 oldrevs = []
93 log = self.recode(log[:-1])
94 state = 2
95 else:
96 # gather log
97 log += l
98 elif state == 2: # members
99 if l == "\n": # start of next entry
100 state = 0
101 p = [self.parent[id]]
102 if id == "1":
103 p = []
104 if branch == "HEAD":
105 branch = ""
106 if branch:
107 latest = None
108 # the last changeset that contains a base
109 # file is our parent
110 for r in oldrevs:
111 latest = max(filerevids.get(r, None), latest)
112 if latest:
113 p = [latest]
65
66 if self.builtin:
67 # builtin cvsps code
68 ui.status(_('using builtin cvsps\n'))
69
70 db = cvsps.createlog(ui, cache='update')
71 db = cvsps.createchangeset(ui, db,
72 fuzz=int(ui.config('convert', 'cvsps.fuzz', 60)),
73 mergeto=ui.config('convert', 'cvsps.mergeto', None),
74 mergefrom=ui.config('convert', 'cvsps.mergefrom', None))
75
76 for cs in db:
77 if maxrev and cs.id>maxrev:
78 break
79 id = str(cs.id)
80 cs.author = self.recode(cs.author)
81 self.lastbranch[cs.branch] = id
82 cs.comment = self.recode(cs.comment)
83 date = util.datestr(cs.date)
84 self.tags.update(dict.fromkeys(cs.tags, id))
85
86 files = {}
87 for f in cs.entries:
88 files[f.file] = "%s%s" % ('.'.join([str(x) for x in f.revision]),
89 ['', '(DEAD)'][f.dead])
114 90
115 # add current commit to set
116 c = commit(author=author, date=date, parents=p,
117 desc=log, branch=branch)
118 self.changeset[id] = c
119 self.files[id] = files
120 else:
121 colon = l.rfind(':')
122 file = l[1:colon]
123 rev = l[colon+1:-2]
124 oldrev, rev = rev.split("->")
125 files[file] = rev
91 # add current commit to set
92 c = commit(author=cs.author, date=date,
93 parents=[str(p.id) for p in cs.parents],
94 desc=cs.comment, branch=cs.branch or '')
95 self.changeset[id] = c
96 self.files[id] = files
97 else:
98 # external cvsps
99 for l in util.popen(cmd):
100 if state == 0: # header
101 if l.startswith("PatchSet"):
102 id = l[9:-2]
103 if maxrev and int(id) > maxrev:
104 # ignore everything
105 state = 3
106 elif l.startswith("Date"):
107 date = util.parsedate(l[6:-1], ["%Y/%m/%d %H:%M:%S"])
108 date = util.datestr(date)
109 elif l.startswith("Branch"):
110 branch = l[8:-1]
111 self.parent[id] = self.lastbranch.get(branch, 'bad')
112 self.lastbranch[branch] = id
113 elif l.startswith("Ancestor branch"):
114 ancestor = l[17:-1]
115 # figure out the parent later
116 self.parent[id] = self.lastbranch[ancestor]
117 elif l.startswith("Author"):
118 author = self.recode(l[8:-1])
119 elif l.startswith("Tag:") or l.startswith("Tags:"):
120 t = l[l.index(':')+1:]
121 t = [ut.strip() for ut in t.split(',')]
122 if (len(t) > 1) or (t[0] and (t[0] != "(none)")):
123 self.tags.update(dict.fromkeys(t, id))
124 elif l.startswith("Log:"):
125 # switch to gathering log
126 state = 1
127 log = ""
128 elif state == 1: # log
129 if l == "Members: \n":
130 # switch to gathering members
131 files = {}
132 oldrevs = []
133 log = self.recode(log[:-1])
134 state = 2
135 else:
136 # gather log
137 log += l
138 elif state == 2: # members
139 if l == "\n": # start of next entry
140 state = 0
141 p = [self.parent[id]]
142 if id == "1":
143 p = []
144 if branch == "HEAD":
145 branch = ""
146 if branch:
147 latest = None
148 # the last changeset that contains a base
149 # file is our parent
150 for r in oldrevs:
151 latest = max(filerevids.get(r, None), latest)
152 if latest:
153 p = [latest]
126 154
127 # save some information for identifying branch points
128 oldrevs.append("%s:%s" % (oldrev, file))
129 filerevids["%s:%s" % (rev, file)] = id
130 elif state == 3:
131 # swallow all input
132 continue
155 # add current commit to set
156 c = commit(author=author, date=date, parents=p,
157 desc=log, branch=branch)
158 self.changeset[id] = c
159 self.files[id] = files
160 else:
161 colon = l.rfind(':')
162 file = l[1:colon]
163 rev = l[colon+1:-2]
164 oldrev, rev = rev.split("->")
165 files[file] = rev
166
167 # save some information for identifying branch points
168 oldrevs.append("%s:%s" % (oldrev, file))
169 filerevids["%s:%s" % (rev, file)] = id
170 elif state == 3:
171 # swallow all input
172 continue
133 173
134 174 self.heads = self.lastbranch.values()
135 175 finally:
136 176 os.chdir(d)
137 177
138 178 def _connect(self):
139 179 root = self.cvsroot
140 180 conntype = None
141 181 user, host = None, None
142 182 cmd = ['cvs', 'server']
143 183
144 184 self.ui.status("connecting to %s\n" % root)
145 185
146 186 if root.startswith(":pserver:"):
147 187 root = root[9:]
148 188 m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)',
149 189 root)
150 190 if m:
151 191 conntype = "pserver"
152 192 user, passw, serv, port, root = m.groups()
153 193 if not user:
154 194 user = "anonymous"
155 195 if not port:
156 196 port = 2401
157 197 else:
158 198 port = int(port)
159 199 format0 = ":pserver:%s@%s:%s" % (user, serv, root)
160 200 format1 = ":pserver:%s@%s:%d%s" % (user, serv, port, root)
161 201
162 202 if not passw:
163 203 passw = "A"
164 204 pf = open(os.path.join(os.environ["HOME"], ".cvspass"))
165 205 for line in pf.read().splitlines():
166 206 part1, part2 = line.split(' ', 1)
167 207 if part1 == '/1':
168 208 # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
169 209 part1, part2 = part2.split(' ', 1)
170 210 format = format1
171 211 else:
172 212 # :pserver:user@example.com:/cvsroot/foo Ah<Z
173 213 format = format0
174 214 if part1 == format:
175 215 passw = part2
176 216 break
177 217 pf.close()
178 218
179 219 sck = socket.socket()
180 220 sck.connect((serv, port))
181 221 sck.send("\n".join(["BEGIN AUTH REQUEST", root, user, passw,
182 222 "END AUTH REQUEST", ""]))
183 223 if sck.recv(128) != "I LOVE YOU\n":
184 224 raise util.Abort("CVS pserver authentication failed")
185 225
186 226 self.writep = self.readp = sck.makefile('r+')
187 227
188 228 if not conntype and root.startswith(":local:"):
189 229 conntype = "local"
190 230 root = root[7:]
191 231
192 232 if not conntype:
193 233 # :ext:user@host/home/user/path/to/cvsroot
194 234 if root.startswith(":ext:"):
195 235 root = root[5:]
196 236 m = re.match(r'(?:([^@:/]+)@)?([^:/]+):?(.*)', root)
197 237 # Do not take Windows path "c:\foo\bar" for a connection strings
198 238 if os.path.isdir(root) or not m:
199 239 conntype = "local"
200 240 else:
201 241 conntype = "rsh"
202 242 user, host, root = m.group(1), m.group(2), m.group(3)
203 243
204 244 if conntype != "pserver":
205 245 if conntype == "rsh":
206 246 rsh = os.environ.get("CVS_RSH") or "ssh"
207 247 if user:
208 248 cmd = [rsh, '-l', user, host] + cmd
209 249 else:
210 250 cmd = [rsh, host] + cmd
211 251
212 252 # popen2 does not support argument lists under Windows
213 253 cmd = [util.shellquote(arg) for arg in cmd]
214 254 cmd = util.quotecommand(' '.join(cmd))
215 255 self.writep, self.readp = os.popen2(cmd, 'b')
216 256
217 257 self.realroot = root
218 258
219 259 self.writep.write("Root %s\n" % root)
220 260 self.writep.write("Valid-responses ok error Valid-requests Mode"
221 261 " M Mbinary E Checked-in Created Updated"
222 262 " Merged Removed\n")
223 263 self.writep.write("valid-requests\n")
224 264 self.writep.flush()
225 265 r = self.readp.readline()
226 266 if not r.startswith("Valid-requests"):
227 267 raise util.Abort("server sucks")
228 268 if "UseUnchanged" in r:
229 269 self.writep.write("UseUnchanged\n")
230 270 self.writep.flush()
231 271 r = self.readp.readline()
232 272
233 273 def getheads(self):
234 274 return self.heads
235 275
236 276 def _getfile(self, name, rev):
237 277
238 278 def chunkedread(fp, count):
239 279 # file-objects returned by socked.makefile() do not handle
240 280 # large read() requests very well.
241 281 chunksize = 65536
242 282 output = StringIO()
243 283 while count > 0:
244 284 data = fp.read(min(count, chunksize))
245 285 if not data:
246 286 raise util.Abort("%d bytes missing from remote file" % count)
247 287 count -= len(data)
248 288 output.write(data)
249 289 return output.getvalue()
250 290
251 291 if rev.endswith("(DEAD)"):
252 292 raise IOError
253 293
254 294 args = ("-N -P -kk -r %s --" % rev).split()
255 295 args.append(self.cvsrepo + '/' + name)
256 296 for x in args:
257 297 self.writep.write("Argument %s\n" % x)
258 298 self.writep.write("Directory .\n%s\nco\n" % self.realroot)
259 299 self.writep.flush()
260 300
261 301 data = ""
262 302 while 1:
263 303 line = self.readp.readline()
264 304 if line.startswith("Created ") or line.startswith("Updated "):
265 305 self.readp.readline() # path
266 306 self.readp.readline() # entries
267 307 mode = self.readp.readline()[:-1]
268 308 count = int(self.readp.readline()[:-1])
269 309 data = chunkedread(self.readp, count)
270 310 elif line.startswith(" "):
271 311 data += line[1:]
272 312 elif line.startswith("M "):
273 313 pass
274 314 elif line.startswith("Mbinary "):
275 315 count = int(self.readp.readline()[:-1])
276 316 data = chunkedread(self.readp, count)
277 317 else:
278 318 if line == "ok\n":
279 319 return (data, "x" in mode and "x" or "")
280 320 elif line.startswith("E "):
281 321 self.ui.warn("cvs server: %s\n" % line[2:])
282 322 elif line.startswith("Remove"):
283 323 l = self.readp.readline()
284 324 l = self.readp.readline()
285 325 if l != "ok\n":
286 326 raise util.Abort("unknown CVS response: %s" % l)
287 327 else:
288 328 raise util.Abort("unknown CVS response: %s" % line)
289 329
290 330 def getfile(self, file, rev):
291 331 data, mode = self._getfile(file, rev)
292 332 self.modecache[(file, rev)] = mode
293 333 return data
294 334
295 335 def getmode(self, file, rev):
296 336 return self.modecache[(file, rev)]
297 337
298 338 def getchanges(self, rev):
299 339 self.modecache = {}
300 340 files = self.files[rev]
301 341 cl = files.items()
302 342 cl.sort()
303 343 return (cl, {})
304 344
305 345 def getcommit(self, rev):
306 346 return self.changeset[rev]
307 347
308 348 def gettags(self):
309 349 return self.tags
310 350
311 351 def getchangedfiles(self, rev, i):
312 352 files = self.files[rev].keys()
313 353 files.sort()
314 354 return files
315 355
General Comments 0
You need to be logged in to leave comments. Login now