##// END OF EJS Templates
automv: new experimental extension...
Martijn Pieters -
r28129:7c40b4b7 default
parent child Browse files
Show More
@@ -0,0 +1,83
1 # automv.py
2 #
3 # Copyright 2013-2016 Facebook, Inc.
4 #
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
7 """Check for unrecorded moves at commit time (EXPERIMENTAL)
8
9 This extension checks at commit/amend time if any of the committed files
10 comes from an unrecorded mv.
11
12 The threshold at which a file is considered a move can be set with the
13 ``automv.similarity`` config option; the default value is 1.00.
14
15 """
16 from __future__ import absolute_import
17
18 from mercurial import (
19 commands,
20 copies,
21 extensions,
22 scmutil,
23 similar
24 )
25 from mercurial.i18n import _
26
27 def extsetup(ui):
28 entry = extensions.wrapcommand(
29 commands.table, 'commit', mvcheck)
30 entry[1].append(
31 ('', 'no-automv', None,
32 _('disable automatic file move detection')))
33
34 def mvcheck(orig, ui, repo, *pats, **opts):
35 disabled = opts.pop('no_automv', False)
36 if not disabled:
37 threshold = float(ui.config('automv', 'similarity', '1.00'))
38 if threshold > 0:
39 match = scmutil.match(repo[None], pats, opts)
40 added, removed = _interestingfiles(repo, match)
41 renames = _findrenames(repo, match, added, removed, threshold)
42 _markchanges(repo, renames)
43
44 # developer config: automv.testmode
45 if not ui.configbool('automv', 'testmode'):
46 return orig(ui, repo, *pats, **opts)
47
48 def _interestingfiles(repo, matcher):
49 stat = repo.status(repo['.'], repo[None], matcher)
50 added = stat[1]
51 removed = stat[2]
52
53 copy = copies._forwardcopies(repo['.'], repo[None], matcher)
54 # remove the copy files for which we already have copy info
55 added = [f for f in added if f not in copy]
56
57 return added, removed
58
59 def _findrenames(repo, matcher, added, removed, similarity):
60 """Find renames from removed files of the current commit/amend files
61 to the added ones"""
62 renames = {}
63 if similarity > 0:
64 for src, dst, score in similar.findrenames(
65 repo, added, removed, similarity):
66 if repo.ui.verbose:
67 repo.ui.status(
68 _('detected move of %s as %s (%d%% similar)\n') % (
69 matcher.rel(src), matcher.rel(dst), score * 100))
70 renames[dst] = src
71 if renames:
72 repo.ui.status(_('detected move of %d files\n') % len(renames))
73 return renames
74
75 def _markchanges(repo, renames):
76 """Marks the files in renames as copied."""
77 wctx = repo[None]
78 wlock = repo.wlock()
79 try:
80 for dst, src in renames.iteritems():
81 wctx.copy(src, dst)
82 finally:
83 wlock.release()
@@ -0,0 +1,285
1 $ cat >> $HGRCPATH << EOF
2 > [extensions]
3 > automv=
4 > rebase=
5 > EOF
6
7 Setup repo
8
9 $ hg init repo
10 $ cd repo
11
12 Test automv command for commit
13
14 $ echo 'foo' > a.txt
15 $ hg add a.txt
16 $ hg commit -m 'init repo with a'
17
18 mv/rm/add
19 $ mv a.txt b.txt
20 $ hg rm a.txt
21 $ hg add b.txt
22 $ hg status -C
23 A b.txt
24 R a.txt
25 $ hg commit -m 'msg'
26 detected move of 1 files
27 $ hg status --change . -C
28 A b.txt
29 a.txt
30 R a.txt
31 $ hg up -r 0
32 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
33
34 mv/rm/add/modif
35 $ mv a.txt b.txt
36 $ hg rm a.txt
37 $ hg add b.txt
38 $ printf '\nfoo\n' >> b.txt
39 $ hg status -C
40 A b.txt
41 R a.txt
42 $ hg commit -m 'msg'
43 created new head
44 $ hg status --change . -C
45 A b.txt
46 R a.txt
47 $ hg up -r 0
48 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
49
50 mv/rm/add/modif/changethreshold
51 $ mv a.txt b.txt
52 $ hg rm a.txt
53 $ hg add b.txt
54 $ printf '\nfoo\n' >> b.txt
55 $ hg status -C
56 A b.txt
57 R a.txt
58 $ hg commit --config automv.similarity='0.6' -m 'msg'
59 detected move of 1 files
60 created new head
61 $ hg status --change . -C
62 A b.txt
63 a.txt
64 R a.txt
65 $ hg up -r 0
66 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
67
68 mv
69 $ mv a.txt b.txt
70 $ hg status -C
71 ! a.txt
72 ? b.txt
73 $ hg commit -m 'msg'
74 nothing changed (1 missing files, see 'hg status')
75 [1]
76 $ hg status -C
77 ! a.txt
78 ? b.txt
79 $ hg revert -aqC
80 $ rm b.txt
81
82 mv/rm/add/notincommitfiles
83 $ mv a.txt b.txt
84 $ hg rm a.txt
85 $ hg add b.txt
86 $ echo 'bar' > c.txt
87 $ hg add c.txt
88 $ hg status -C
89 A b.txt
90 A c.txt
91 R a.txt
92 $ hg commit c.txt -m 'msg'
93 created new head
94 $ hg status --change . -C
95 A c.txt
96 $ hg status -C
97 A b.txt
98 R a.txt
99 $ hg up -r 0
100 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
101 $ hg rm a.txt
102 $ echo 'bar' > c.txt
103 $ hg add c.txt
104 $ hg commit -m 'msg'
105 detected move of 1 files
106 created new head
107 $ hg status --change . -C
108 A b.txt
109 a.txt
110 A c.txt
111 R a.txt
112 $ hg up -r 0
113 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
114
115 mv/rm/add/--no-automv
116 $ mv a.txt b.txt
117 $ hg rm a.txt
118 $ hg add b.txt
119 $ hg status -C
120 A b.txt
121 R a.txt
122 $ hg commit --no-automv -m 'msg'
123 created new head
124 $ hg status --change . -C
125 A b.txt
126 R a.txt
127 $ hg up -r 0
128 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
129
130 Test automv command for commit --amend
131
132 mv/rm/add
133 $ echo 'c' > c.txt
134 $ hg add c.txt
135 $ hg commit -m 'revision to amend to'
136 created new head
137 $ mv a.txt b.txt
138 $ hg rm a.txt
139 $ hg add b.txt
140 $ hg status -C
141 A b.txt
142 R a.txt
143 $ hg commit --amend -m 'amended'
144 detected move of 1 files
145 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-amend-backup.hg (glob)
146 $ hg status --change . -C
147 A b.txt
148 a.txt
149 A c.txt
150 R a.txt
151 $ hg up -r 0
152 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
153
154 mv/rm/add/modif
155 $ echo 'c' > c.txt
156 $ hg add c.txt
157 $ hg commit -m 'revision to amend to'
158 created new head
159 $ mv a.txt b.txt
160 $ hg rm a.txt
161 $ hg add b.txt
162 $ printf '\nfoo\n' >> b.txt
163 $ hg status -C
164 A b.txt
165 R a.txt
166 $ hg commit --amend -m 'amended'
167 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-amend-backup.hg (glob)
168 $ hg status --change . -C
169 A b.txt
170 A c.txt
171 R a.txt
172 $ hg up -r 0
173 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
174
175 mv/rm/add/modif/changethreshold
176 $ echo 'c' > c.txt
177 $ hg add c.txt
178 $ hg commit -m 'revision to amend to'
179 created new head
180 $ mv a.txt b.txt
181 $ hg rm a.txt
182 $ hg add b.txt
183 $ printf '\nfoo\n' >> b.txt
184 $ hg status -C
185 A b.txt
186 R a.txt
187 $ hg commit --amend --config automv.similarity='0.6' -m 'amended'
188 detected move of 1 files
189 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-amend-backup.hg (glob)
190 $ hg status --change . -C
191 A b.txt
192 a.txt
193 A c.txt
194 R a.txt
195 $ hg up -r 0
196 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
197
198 mv
199 $ echo 'c' > c.txt
200 $ hg add c.txt
201 $ hg commit -m 'revision to amend to'
202 created new head
203 $ mv a.txt b.txt
204 $ hg status -C
205 ! a.txt
206 ? b.txt
207 $ hg commit --amend -m 'amended'
208 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-amend-backup.hg (glob)
209 $ hg status -C
210 ! a.txt
211 ? b.txt
212 $ hg up -Cr 0
213 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
214
215 mv/rm/add/notincommitfiles
216 $ echo 'c' > c.txt
217 $ hg add c.txt
218 $ hg commit -m 'revision to amend to'
219 created new head
220 $ mv a.txt b.txt
221 $ hg rm a.txt
222 $ hg add b.txt
223 $ echo 'bar' > d.txt
224 $ hg add d.txt
225 $ hg status -C
226 A b.txt
227 A d.txt
228 R a.txt
229 $ hg commit --amend -m 'amended' d.txt
230 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-amend-backup.hg (glob)
231 $ hg status --change . -C
232 A c.txt
233 A d.txt
234 $ hg status -C
235 A b.txt
236 R a.txt
237 $ hg commit --amend -m 'amended'
238 detected move of 1 files
239 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-amend-backup.hg (glob)
240 $ hg status --change . -C
241 A b.txt
242 a.txt
243 A c.txt
244 A d.txt
245 R a.txt
246 $ hg up -r 0
247 1 files updated, 0 files merged, 3 files removed, 0 files unresolved
248
249 mv/rm/add/--no-automv
250 $ echo 'c' > c.txt
251 $ hg add c.txt
252 $ hg commit -m 'revision to amend to'
253 created new head
254 $ mv a.txt b.txt
255 $ hg rm a.txt
256 $ hg add b.txt
257 $ hg status -C
258 A b.txt
259 R a.txt
260 $ hg commit --amend -m 'amended' --no-automv
261 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-amend-backup.hg (glob)
262 $ hg status --change . -C
263 A b.txt
264 A c.txt
265 R a.txt
266 $ hg up -r 0
267 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
268
269 mv/rm/commit/add/amend
270 $ echo 'c' > c.txt
271 $ hg add c.txt
272 $ hg commit -m 'revision to amend to'
273 created new head
274 $ mv a.txt b.txt
275 $ hg rm a.txt
276 $ hg status -C
277 R a.txt
278 ? b.txt
279 $ hg commit -m "removed a"
280 $ hg add b.txt
281 $ hg commit --amend -m 'amended'
282 saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-amend-backup.hg (glob)
283 $ hg status --change . -C
284 A b.txt
285 R a.txt
General Comments 0
You need to be logged in to leave comments. Login now