##// END OF EJS Templates
Refactor annotate copy support.
Brendan Cully -
r3172:5c93dd0a default
parent child Browse files
Show More
@@ -612,8 +612,9 b' def annotate(ui, repo, *pats, **opts):'
612 opmap = [['user', lambda x: ui.shortuser(x.user())],
612 opmap = [['user', lambda x: ui.shortuser(x.user())],
613 ['number', lambda x: str(x.rev())],
613 ['number', lambda x: str(x.rev())],
614 ['changeset', lambda x: short(x.node())],
614 ['changeset', lambda x: short(x.node())],
615 ['date', getdate]]
615 ['date', getdate], ['follow', lambda x: x.path()]]
616 if not opts['user'] and not opts['changeset'] and not opts['date']:
616 if (not opts['user'] and not opts['changeset'] and not opts['date']
617 and not opts['follow']):
617 opts['number'] = 1
618 opts['number'] = 1
618
619
619 ctx = repo.changectx(opts['rev'])
620 ctx = repo.changectx(opts['rev'])
@@ -625,7 +626,7 b' def annotate(ui, repo, *pats, **opts):'
625 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
626 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
626 continue
627 continue
627
628
628 lines = fctx.annotate()
629 lines = fctx.annotate(follow=opts.get('follow'))
629 pieces = []
630 pieces = []
630
631
631 for o, f in opmap:
632 for o, f in opmap:
@@ -2671,6 +2672,7 b' table = {'
2671 "^annotate":
2672 "^annotate":
2672 (annotate,
2673 (annotate,
2673 [('r', 'rev', '', _('annotate the specified revision')),
2674 [('r', 'rev', '', _('annotate the specified revision')),
2675 ('f', 'follow', None, _('follow file copies and renames')),
2674 ('a', 'text', None, _('treat all files as text')),
2676 ('a', 'text', None, _('treat all files as text')),
2675 ('u', 'user', None, _('list the author')),
2677 ('u', 'user', None, _('list the author')),
2676 ('d', 'date', None, _('list the date')),
2678 ('d', 'date', None, _('list the date')),
@@ -5,6 +5,10 b''
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from demandload import *
9 from node import *
10 demandload(globals(), 'bdiff')
11
8 from node import *
12 from node import *
9 from demandload import demandload
13 from demandload import demandload
10 demandload(globals(), "ancestor util")
14 demandload(globals(), "ancestor util")
@@ -165,13 +169,74 b' class filectx(object):'
165 return [ filectx(self._repo, self._path, fileid=x,
169 return [ filectx(self._repo, self._path, fileid=x,
166 filelog=self._filelog) for x in c ]
170 filelog=self._filelog) for x in c ]
167
171
168 def annotate(self):
172 def annotate(self, follow=False):
169 getctx = util.cachefunc(lambda x: filectx(self._repo, self._path,
173 '''returns a list of tuples of (ctx, line) for each line
170 changeid=x,
174 in the file, where ctx is the filectx of the node where
171 filelog=self._filelog))
175 that line was last changed'''
172 hist = self._filelog.annotate(self._filenode)
176
177 def decorate(text, rev):
178 return ([rev] * len(text.splitlines()), text)
179
180 def pair(parent, child):
181 for a1, a2, b1, b2 in bdiff.blocks(parent[1], child[1]):
182 child[0][b1:b2] = parent[0][a1:a2]
183 return child
184
185 getlog = util.cachefunc(lambda x: self._repo.file(x))
186 def getctx(path, fileid):
187 log = path == self._path and self._filelog or getlog(path)
188 return filectx(self._repo, path, fileid=fileid, filelog=log)
189 getctx = util.cachefunc(getctx)
190
191 def parents(f):
192 # we want to reuse filectx objects as much as possible
193 p = f._path
194 pl = [ (p, f._filelog.rev(n)) for n in f._filelog.parents(f._filenode) ]
195
196 if follow:
197 r = f.renamed()
198 if r:
199 pl[0] = (r[0], getlog(r[0]).rev(r[1]))
173
200
174 return [(getctx(rev), line) for rev, line in hist]
201 return [ getctx(p, n) for p, n in pl if n != -1 ]
202
203 # find all ancestors
204 needed = {self: 1}
205 visit = [self]
206 files = [self._path]
207 while visit:
208 f = visit.pop(0)
209 for p in parents(f):
210 if p not in needed:
211 needed[p] = 1
212 visit.append(p)
213 if p._path not in files:
214 files.append(p._path)
215 else:
216 # count how many times we'll use this
217 needed[p] += 1
218
219 # sort by revision (per file) which is a topological order
220 visit = []
221 files.reverse()
222 for f in files:
223 fn = [(n._filerev, n) for n in needed.keys() if n._path == f]
224 fn.sort()
225 visit.extend(fn)
226 hist = {}
227
228 for r, f in visit:
229 curr = decorate(f.data(), f)
230 for p in parents(f):
231 if p != nullid:
232 curr = pair(hist[p], curr)
233 # trim the history of unneeded revs
234 needed[p] -= 1
235 if not needed[p]:
236 del hist[p]
237 hist[f] = curr
238
239 return zip(hist[f][0], hist[f][1].splitlines(1))
175
240
176 def ancestor(self, fc2):
241 def ancestor(self, fc2):
177 """
242 """
@@ -1,5 +1,7 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 export HGMERGE=true
4
3 echo % init
5 echo % init
4 hg init
6 hg init
5
7
@@ -21,3 +23,53 b' hg annotate -u a'
21
23
22 echo % annotate -cdnu
24 echo % annotate -cdnu
23 hg annotate -cdnu a
25 hg annotate -cdnu a
26
27 cat <<EOF >>a
28 a
29 a
30 EOF
31 hg ci -ma1 -d '1 0'
32 hg cp a b
33 hg ci -mb -d '1 0'
34 cat <<EOF >> b
35 b
36 b
37 b
38 EOF
39 hg ci -mb2 -d '2 0'
40
41 echo % annotate b
42 hg annotate b
43 echo % annotate -nf b
44 hg annotate -nf b
45
46 hg up -C 2
47 cat <<EOF >> b
48 b
49 c
50 b
51 EOF
52 hg ci -mb2.1 -d '2 0'
53 hg merge
54 hg ci -mmergeb -d '3 0'
55 echo % annotate after merge
56 hg annotate -nf b
57
58 hg up -C 1
59 hg cp a b
60 cat <<EOF > b
61 a
62 z
63 a
64 EOF
65 hg ci -mc -d '3 0'
66 hg merge
67 cat <<EOF >> b
68 b
69 c
70 b
71 EOF
72 echo d >> b
73 hg ci -mmerge2 -d '4 0'
74 echo % annotate after rename merge
75 hg annotate -nf b
@@ -11,3 +11,40 b' 0: a'
11 nobody: a
11 nobody: a
12 % annotate -cdnu
12 % annotate -cdnu
13 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000: a
13 nobody 0 8435f90966e4 Thu Jan 01 00:00:01 1970 +0000: a
14 % annotate b
15 2: a
16 2: a
17 2: a
18 3: b
19 3: b
20 3: b
21 % annotate -nf b
22 0 a: a
23 1 a: a
24 1 a: a
25 3 b: b
26 3 b: b
27 3 b: b
28 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 merging b
30 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
31 (branch merge, don't forget to commit)
32 % annotate after merge
33 0 a: a
34 1 a: a
35 1 a: a
36 3 b: b
37 4 b: c
38 3 b: b
39 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
40 merging b
41 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
42 (branch merge, don't forget to commit)
43 % annotate after rename merge
44 0 a: a
45 6 b: z
46 1 a: a
47 3 b: b
48 4 b: c
49 3 b: b
50 7 b: d
General Comments 0
You need to be logged in to leave comments. Login now