##// END OF EJS Templates
copies: rewrite copy detection for non-merge users...
Matt Mackall -
r15775:91eb4512 default
parent child Browse files
Show More
@@ -5206,17 +5206,7 b' def status(ui, repo, *pats, **opts):'
5206 changestates = zip(states, 'MAR!?IC', stat)
5206 changestates = zip(states, 'MAR!?IC', stat)
5207
5207
5208 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5208 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5209 ctx1 = repo[node1]
5209 copy = copies.pathcopies(repo[node1], repo[node2])
5210 ctx2 = repo[node2]
5211 added = stat[1]
5212 if node2 is None:
5213 added = stat[0] + stat[1] # merged?
5214
5215 for k, v in copies.pathcopies(ctx1, ctx2).iteritems():
5216 if k in added:
5217 copy[k] = v
5218 elif v in added:
5219 copy[v] = k
5220
5210
5221 for state, char, files in changestates:
5211 for state, char, files in changestates:
5222 if state in show:
5212 if state in show:
@@ -84,8 +84,89 b' def _findlimit(repo, a, b):'
84 return None
84 return None
85 return limit
85 return limit
86
86
87 def pathcopies(c1, c2):
87 def _chain(src, dst, a, b):
88 return mergecopies(c1._repo, c1, c2, c1._repo["null"], False)[0]
88 '''chain two sets of copies a->b'''
89 t = a.copy()
90 for k, v in b.iteritems():
91 if v in t:
92 # found a chain
93 if t[v] != k:
94 # file wasn't renamed back to itself
95 t[k] = t[v]
96 if v not in dst:
97 # chain was a rename, not a copy
98 del t[v]
99 if v in src:
100 # file is a copy of an existing file
101 t[k] = v
102 return t
103
104 def _tracefile(fctx, actx):
105 '''return file context that is the ancestor of fctx present in actx'''
106 stop = actx.rev()
107 am = actx.manifest()
108
109 for f in fctx.ancestors():
110 if am.get(f.path(), None) == f.filenode():
111 return f
112 if f.rev() < stop:
113 return None
114
115 def _dirstatecopies(d):
116 ds = d._repo.dirstate
117 c = ds.copies().copy()
118 for k in c.keys():
119 if ds[k] not in 'anm':
120 del c[k]
121 return c
122
123 def _forwardcopies(a, b):
124 '''find {dst@b: src@a} copy mapping where a is an ancestor of b'''
125
126 # check for working copy
127 w = None
128 if b.rev() is None:
129 w = b
130 b = w.p1()
131 if a == b:
132 # short-circuit to avoid issues with merge states
133 return _dirstatecopies(w)
134
135 # find where new files came from
136 # we currently don't try to find where old files went, too expensive
137 # this means we can miss a case like 'hg rm b; hg cp a b'
138 cm = {}
139 for f in b:
140 if f not in a:
141 ofctx = _tracefile(b[f], a)
142 if ofctx:
143 cm[f] = ofctx.path()
144
145 # combine copies from dirstate if necessary
146 if w is not None:
147 cm = _chain(a, w, cm, _dirstatecopies(w))
148
149 return cm
150
151 def _backwardcopies(a, b):
152 # because the forward mapping is 1:n, we can lose renames here
153 # in particular, we find renames better than copies
154 f = _forwardcopies(b, a)
155 r = {}
156 for k, v in f.iteritems():
157 r[v] = k
158 return r
159
160 def pathcopies(x, y):
161 '''find {dst@y: src@x} copy mapping for directed compare'''
162 if x == y or not x or not y:
163 return {}
164 a = y.ancestor(x)
165 if a == x:
166 return _forwardcopies(x, y)
167 if a == y:
168 return _backwardcopies(x, y)
169 return _chain(x, y, _backwardcopies(x, a), _forwardcopies(a, y))
89
170
90 def mergecopies(repo, c1, c2, ca, checkdirs=True):
171 def mergecopies(repo, c1, c2, ca, checkdirs=True):
91 """
172 """
@@ -149,13 +149,11 b' Check patcha is still a git patch:'
149 -b
149 -b
150 +a
150 +a
151 +c
151 +c
152 diff --git a/a b/aa
152 diff --git a/aa b/aa
153 copy from a
153 new file mode 100644
154 copy to aa
154 --- /dev/null
155 --- a/a
156 +++ b/aa
155 +++ b/aa
157 @@ -1,1 +1,1 @@
156 @@ -0,0 +1,1 @@
158 -b
159 +a
157 +a
160
158
161 Check patcha2 is still a regular patch:
159 Check patcha2 is still a regular patch:
@@ -560,6 +560,7 b' make a new branch and get diff/status ou'
560
560
561 - parent to root: --rev . --rev 0
561 - parent to root: --rev . --rev 0
562 M a
562 M a
563 b
563 R b
564 R b
564
565
565 diff --git a/a b/a
566 diff --git a/a b/a
@@ -611,6 +612,7 b' make a new branch and get diff/status ou'
611
612
612 - parent to branch: --rev . --rev 2
613 - parent to branch: --rev . --rev 2
613 M a
614 M a
615 b
614 A x/y
616 A x/y
615 R b
617 R b
616
618
@@ -906,6 +908,7 b' make a new branch and get diff/status ou'
906
908
907 - parent to root: --rev . --rev 0
909 - parent to root: --rev . --rev 0
908 M a
910 M a
911 b
909 R b
912 R b
910 R c
913 R c
911
914
@@ -975,6 +978,7 b' make a new branch and get diff/status ou'
975
978
976 - parent to branch: --rev . --rev 2
979 - parent to branch: --rev . --rev 2
977 M a
980 M a
981 b
978 A x/y
982 A x/y
979 R b
983 R b
980 R c
984 R c
General Comments 0
You need to be logged in to leave comments. Login now