Show More
@@ -0,0 +1,37 b'' | |||||
|
1 | #!/bin/sh | |||
|
2 | ||||
|
3 | hg init rep; cd rep | |||
|
4 | ||||
|
5 | touch empty-file | |||
|
6 | python -c 'for x in range(10000): print x' > large-file | |||
|
7 | ||||
|
8 | hg addremove | |||
|
9 | ||||
|
10 | hg commit -m A | |||
|
11 | ||||
|
12 | rm large-file empty-file | |||
|
13 | python -c 'for x in range(10,10000): print x' > another-file | |||
|
14 | ||||
|
15 | hg addremove -s50 | |||
|
16 | ||||
|
17 | hg commit -m B | |||
|
18 | ||||
|
19 | cd .. | |||
|
20 | ||||
|
21 | hg init rep2; cd rep2 | |||
|
22 | ||||
|
23 | python -c 'for x in range(10000): print x' > large-file | |||
|
24 | python -c 'for x in range(50): print x' > tiny-file | |||
|
25 | ||||
|
26 | hg addremove | |||
|
27 | ||||
|
28 | hg commit -m A | |||
|
29 | ||||
|
30 | python -c 'for x in range(70): print x' > small-file | |||
|
31 | rm tiny-file | |||
|
32 | rm large-file | |||
|
33 | ||||
|
34 | hg addremove -s50 | |||
|
35 | ||||
|
36 | hg commit -m B | |||
|
37 |
@@ -0,0 +1,12 b'' | |||||
|
1 | adding empty-file | |||
|
2 | adding large-file | |||
|
3 | adding another-file | |||
|
4 | removing empty-file | |||
|
5 | removing large-file | |||
|
6 | recording removal of large-file as rename to another-file (99% similar) | |||
|
7 | adding large-file | |||
|
8 | adding tiny-file | |||
|
9 | adding small-file | |||
|
10 | removing large-file | |||
|
11 | removing tiny-file | |||
|
12 | recording removal of tiny-file as rename to small-file (82% similar) |
@@ -7,7 +7,7 b'' | |||||
7 |
|
7 | |||
8 | from node import * |
|
8 | from node import * | |
9 | from i18n import _ |
|
9 | from i18n import _ | |
10 | import os, sys, mdiff, util, templater, patch |
|
10 | import os, sys, mdiff, bdiff, util, templater, patch | |
11 |
|
11 | |||
12 | revrangesep = ':' |
|
12 | revrangesep = ':' | |
13 |
|
13 | |||
@@ -146,20 +146,29 b' def walk(repo, pats=[], opts={}, node=No' | |||||
146 | yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact |
|
146 | yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact | |
147 |
|
147 | |||
148 | def findrenames(repo, added=None, removed=None, threshold=0.5): |
|
148 | def findrenames(repo, added=None, removed=None, threshold=0.5): | |
|
149 | '''find renamed files -- yields (before, after, score) tuples''' | |||
149 | if added is None or removed is None: |
|
150 | if added is None or removed is None: | |
150 | added, removed = repo.status()[1:3] |
|
151 | added, removed = repo.status()[1:3] | |
151 | ctx = repo.changectx() |
|
152 | ctx = repo.changectx() | |
152 | for a in added: |
|
153 | for a in added: | |
153 | aa = repo.wread(a) |
|
154 | aa = repo.wread(a) | |
154 |
best |
|
155 | bestname, bestscore = None, threshold | |
155 | for r in removed: |
|
156 | for r in removed: | |
156 | rr = ctx.filectx(r).data() |
|
157 | rr = ctx.filectx(r).data() | |
157 | delta = mdiff.textdiff(aa, rr) |
|
158 | ||
158 | if len(delta) < len(aa): |
|
159 | # bdiff.blocks() returns blocks of matching lines | |
159 | myscore = 1.0 - (float(len(delta)) / len(aa)) |
|
160 | # count the number of bytes in each | |
160 | if bestscore is None or myscore > bestscore: |
|
161 | equal = 0 | |
161 | bestscore, bestname = myscore, r |
|
162 | alines = mdiff.splitnewlines(aa) | |
162 | if bestname and bestscore >= threshold: |
|
163 | matches = bdiff.blocks(aa, rr) | |
|
164 | for x1,x2,y1,y2 in matches: | |||
|
165 | for line in alines[x1:x2]: | |||
|
166 | equal += len(line) | |||
|
167 | ||||
|
168 | myscore = equal*2.0 / (len(aa)+len(rr)) | |||
|
169 | if myscore >= bestscore: | |||
|
170 | bestname, bestscore = r, myscore | |||
|
171 | if bestname: | |||
163 | yield bestname, a, bestscore |
|
172 | yield bestname, a, bestscore | |
164 |
|
173 | |||
165 | def addremove(repo, pats=[], opts={}, wlock=None, dry_run=None, |
|
174 | def addremove(repo, pats=[], opts={}, wlock=None, dry_run=None, |
General Comments 0
You need to be logged in to leave comments.
Login now