##// END OF EJS Templates
automv: reuse existing scutil._markchanges() function
Martijn Pieters -
r28150:7a984cec default
parent child Browse files
Show More
@@ -1,92 +1,82 b''
1 1 # automv.py
2 2 #
3 3 # Copyright 2013-2016 Facebook, Inc.
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7 """Check for unrecorded moves at commit time (EXPERIMENTAL)
8 8
9 9 This extension checks at commit/amend time if any of the committed files
10 10 comes from an unrecorded mv.
11 11
12 12 The threshold at which a file is considered a move can be set with the
13 13 ``automv.similarity`` config option; the default value is 1.00.
14 14
15 15 """
16 16 from __future__ import absolute_import
17 17
18 18 from mercurial import (
19 19 commands,
20 20 copies,
21 21 extensions,
22 22 scmutil,
23 23 similar
24 24 )
25 25 from mercurial.i18n import _
26 26
27 27 def extsetup(ui):
28 28 entry = extensions.wrapcommand(
29 29 commands.table, 'commit', mvcheck)
30 30 entry[1].append(
31 31 ('', 'no-automv', None,
32 32 _('disable automatic file move detection')))
33 33
34 34 def mvcheck(orig, ui, repo, *pats, **opts):
35 35 """Hook to check for moves at commit time"""
36 36 disabled = opts.pop('no_automv', False)
37 37 if not disabled:
38 38 threshold = float(ui.config('automv', 'similarity', '1.00'))
39 39 if threshold > 0:
40 40 match = scmutil.match(repo[None], pats, opts)
41 41 added, removed = _interestingfiles(repo, match)
42 42 renames = _findrenames(repo, match, added, removed, threshold)
43 _markchanges(repo, renames)
43 scmutil._markchanges(repo, (), (), renames)
44 44
45 45 return orig(ui, repo, *pats, **opts)
46 46
47 47 def _interestingfiles(repo, matcher):
48 48 """Find what files were added or removed in this commit.
49 49
50 50 Returns a tuple of two lists: (added, removed). Only files not *already*
51 51 marked as moved are included in the added list.
52 52
53 53 """
54 54 stat = repo.status(match=matcher)
55 55 added = stat[1]
56 56 removed = stat[2]
57 57
58 58 copy = copies._forwardcopies(repo['.'], repo[None], matcher)
59 59 # remove the copy files for which we already have copy info
60 60 added = [f for f in added if f not in copy]
61 61
62 62 return added, removed
63 63
64 64 def _findrenames(repo, matcher, added, removed, similarity):
65 65 """Find what files in added are really moved files.
66 66
67 67 Any file named in removed that is at least similarity% similar to a file
68 68 in added is seen as a rename.
69 69
70 70 """
71 71 renames = {}
72 72 if similarity > 0:
73 73 for src, dst, score in similar.findrenames(
74 74 repo, added, removed, similarity):
75 75 if repo.ui.verbose:
76 76 repo.ui.status(
77 77 _('detected move of %s as %s (%d%% similar)\n') % (
78 78 matcher.rel(src), matcher.rel(dst), score * 100))
79 79 renames[dst] = src
80 80 if renames:
81 81 repo.ui.status(_('detected move of %d files\n') % len(renames))
82 82 return renames
83
84 def _markchanges(repo, renames):
85 """Marks the files in renames as copied."""
86 wctx = repo[None]
87 wlock = repo.wlock()
88 try:
89 for dst, src in renames.iteritems():
90 wctx.copy(src, dst)
91 finally:
92 wlock.release()
General Comments 0
You need to be logged in to leave comments. Login now