Mercurial > evolve
comparison hgext/directaccess.py @ 1339:0e2eb196923a
inhibit: create direct access extension
Since we want to use direct access without necessarily using inhibit, this
patch separates both extensions. Inhibit depends on direct access and we add
a test to check that it complains if that is not the case.
author | Laurent Charignon <lcharignon@fb.com> |
---|---|
date | Thu, 14 May 2015 11:23:40 -0700 |
parents | |
children | b00c2fe51ac8 |
comparison
equal
deleted
inserted
replaced
1338:77cbf9121e8a | 1339:0e2eb196923a |
---|---|
1 """ This extension provides direct access | |
2 It is the ability to refer and access hidden sha in commands provided that you | |
3 know their value. | |
4 For example hg log -r xxx where xxx is a commit has should work whether xxx is | |
5 hidden or not as we assume that the user knows what he is doing when referring | |
6 to xxx. | |
7 """ | |
8 from mercurial import extensions | |
9 from mercurial import cmdutil | |
10 from mercurial import repoview | |
11 from mercurial import branchmap | |
12 from mercurial import revset | |
13 from mercurial import error | |
14 from mercurial import commands | |
15 from mercurial.i18n import _ | |
16 | |
17 cmdtable = {} | |
18 command = cmdutil.command(cmdtable) | |
19 | |
20 # List of commands where no warning is shown for direct access | |
21 directaccesslevel = [ | |
22 # warning or not, extension (None if core), command name | |
23 (False, None, 'update'), | |
24 (False, None, 'export'), | |
25 (True, 'rebase', 'rebase'), | |
26 (False, 'evolve', 'prune'), | |
27 ] | |
28 | |
29 def reposetup(ui, repo): | |
30 repo._explicitaccess = set() | |
31 | |
32 def _computehidden(repo): | |
33 hidden = repoview.computehidden(repo) | |
34 cl = repo.changelog | |
35 dynamic = hidden & repo._explicitaccess | |
36 if dynamic: | |
37 blocked = cl.ancestors(dynamic, inclusive=True) | |
38 hidden = frozenset(r for r in hidden if r not in blocked) | |
39 return hidden | |
40 | |
41 def setupdirectaccess(): | |
42 """ Add two new filtername that behave like visible to provide direct access | |
43 and direct access with warning. Wraps the commands to setup direct access """ | |
44 repoview.filtertable.update({'visible-directaccess-nowarn': _computehidden}) | |
45 repoview.filtertable.update({'visible-directaccess-warn': _computehidden}) | |
46 branchmap.subsettable['visible-directaccess-nowarn'] = 'visible' | |
47 branchmap.subsettable['visible-directaccess-warn'] = 'visible' | |
48 | |
49 for warn, ext, cmd in directaccesslevel: | |
50 cmdtable = extensions.find(ext).cmdtable if ext else commands.table | |
51 wrapper = wrapwithwarning if warn else wrapwithoutwarning | |
52 try: | |
53 extensions.wrapcommand(cmdtable, cmd, wrapper) | |
54 except error.UnknownCommand: | |
55 pass | |
56 | |
57 def wrapwithoutwarning(orig, ui, repo, *args, **kwargs): | |
58 if repo and repo.filtername == 'visible': | |
59 repo = repo.filtered("visible-directaccess-nowarn") | |
60 return orig(ui, repo, *args, **kwargs) | |
61 | |
62 def wrapwithwarning(orig, ui, repo, *args, **kwargs): | |
63 if repo and repo.filtername == 'visible': | |
64 repo = repo.filtered("visible-directaccess-warn") | |
65 return orig(ui, repo, *args, **kwargs) | |
66 | |
67 def extsetup(ui): | |
68 extensions.wrapfunction(revset, 'posttreebuilthook', _posttreebuilthook) | |
69 setupdirectaccess() | |
70 | |
71 def gethashsymbols(tree): | |
72 # Returns the list of symbols of the tree that look like hashes | |
73 # for example for the revset 3::abe3ff it will return ('abe3ff') | |
74 if not tree: | |
75 return [] | |
76 | |
77 if len(tree) == 2 and tree[0] == "symbol": | |
78 try: | |
79 int(tree[1]) | |
80 return [] | |
81 except ValueError as e: | |
82 return [tree[1]] | |
83 elif len(tree) == 3: | |
84 return gethashsymbols(tree[1]) + gethashsymbols(tree[2]) | |
85 else: | |
86 return [] | |
87 | |
88 def _posttreebuilthook(orig, tree, repo): | |
89 # This is use to enabled direct hash access | |
90 # We extract the symbols that look like hashes and add them to the | |
91 # explicitaccess set | |
92 orig(tree, repo) | |
93 filternm = "" | |
94 if repo is not None: | |
95 filternm = repo.filtername | |
96 if filternm is not None and filternm.startswith('visible-directaccess'): | |
97 prelength = len(repo._explicitaccess) | |
98 accessbefore = set(repo._explicitaccess) | |
99 repo.symbols = gethashsymbols(tree) | |
100 cl = repo.unfiltered().changelog | |
101 for node in repo.symbols: | |
102 try: | |
103 node = cl._partialmatch(node) | |
104 except error.LookupError: | |
105 node = None | |
106 if node is not None: | |
107 rev = cl.rev(node) | |
108 if rev not in repo.changelog: | |
109 repo._explicitaccess.add(rev) | |
110 if prelength != len(repo._explicitaccess): | |
111 if repo.filtername != 'visible-directaccess-nowarn': | |
112 unhiddencommits = repo._explicitaccess - accessbefore | |
113 repo.ui.warn( _("Warning: accessing hidden changesets %s " | |
114 "for write operation\n") % | |
115 (",".join([str(repo.unfiltered()[l]) | |
116 for l in unhiddencommits]))) | |
117 repo.invalidatevolatilesets() |