annotate hgext/fix.py @ 42194:0da689a60163

fix: allow fixer tools to return metadata in addition to the file content With this change, fixer tools can be configured to output a JSON object that will be parsed and passed to hooks that can be used to print summaries of what code was formatted or perform other post-fixing work. The motivation for this change is to allow parallel executions of a "meta-formatter" tool to report back statistics, which are then aggregated and processed after all formatting has completed. Providing an extensible mechanism inside fix.py is far simpler, and more portable, than trying to make a tool like this communicate through some other channel. Differential Revision: https://phab.mercurial-scm.org/D6167
author Danny Hooper <hooper@google.com>
date Thu, 21 Mar 2019 18:32:45 -0700
parents 8f427f7c1f71
children 9ed63cd0026c
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
1 # fix - rewrite file content in changesets and working copy
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
2 #
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
3 # Copyright 2018 Google LLC.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
4 #
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
7 """rewrite file content in changesets or working copy (EXPERIMENTAL)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
8
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
9 Provides a command that runs configured tools on the contents of modified files,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
10 writing back any fixes to the working copy or replacing changesets.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
11
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
12 Here is an example configuration that causes :hg:`fix` to apply automatic
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
13 formatting fixes to modified lines in C++ code::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
14
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
15 [fix]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
16 clang-format:command=clang-format --assume-filename={rootpath}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
17 clang-format:linerange=--lines={first}:{last}
40533
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
18 clang-format:pattern=set:**.cpp or **.hpp
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
19
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
20 The :command suboption forms the first part of the shell command that will be
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
21 used to fix a file. The content of the file is passed on standard input, and the
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
22 fixed file content is expected on standard output. Any output on standard error
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
23 will be displayed as a warning. If the exit status is not zero, the file will
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
24 not be affected. A placeholder warning is displayed if there is a non-zero exit
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
25 status but no standard error output. Some values may be substituted into the
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
26 command::
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
27
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
28 {rootpath} The path of the file being fixed, relative to the repo root
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
29 {basename} The name of the file being fixed, without the directory path
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
30
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
31 If the :linerange suboption is set, the tool will only be run if there are
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
32 changed lines in a file. The value of this suboption is appended to the shell
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
33 command once for every range of changed lines in the file. Some values may be
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
34 substituted into the command::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
35
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
36 {first} The 1-based line number of the first line in the modified range
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
37 {last} The 1-based line number of the last line in the modified range
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
38
40533
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
39 The :pattern suboption determines which files will be passed through each
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
40 configured tool. See :hg:`help patterns` for possible values. If there are file
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
41 arguments to :hg:`fix`, the intersection of these patterns is used.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
42
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
43 There is also a configurable limit for the maximum size of file that will be
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
44 processed by :hg:`fix`::
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
45
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
46 [fix]
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
47 maxfilesize = 2MB
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
48
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
49 Normally, execution of configured tools will continue after a failure (indicated
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
50 by a non-zero exit status). It can also be configured to abort after the first
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
51 such failure, so that no files will be affected if any tool fails. This abort
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
52 will also cause :hg:`fix` to exit with a non-zero status::
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
53
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
54 [fix]
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
55 failure = abort
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
56
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
57 When multiple tools are configured to affect a file, they execute in an order
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
58 defined by the :priority suboption. The priority suboption has a default value
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
59 of zero for each tool. Tools are executed in order of descending priority. The
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
60 execution order of tools with equal priority is unspecified. For example, you
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
61 could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
62 in a text file by ensuring that 'sort' runs before 'head'::
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
63
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
64 [fix]
41126
d8f5c615e811 tests: use more portable flags in test-fix.t
Danny Hooper <hooper@google.com>
parents: 40570
diff changeset
65 sort:command = sort -n
d8f5c615e811 tests: use more portable flags in test-fix.t
Danny Hooper <hooper@google.com>
parents: 40570
diff changeset
66 head:command = head -n 10
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
67 sort:pattern = numbers.txt
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
68 head:pattern = numbers.txt
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
69 sort:priority = 2
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
70 head:priority = 1
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
71
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
72 To account for changes made by each tool, the line numbers used for incremental
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
73 formatting are recomputed before executing the next tool. So, each tool may see
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
74 different values for the arguments added by the :linerange suboption.
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
75
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
76 Each fixer tool is allowed to return some metadata in addition to the fixed file
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
77 content. The metadata must be placed before the file content on stdout,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
78 separated from the file content by a zero byte. The metadata is parsed as a JSON
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
79 value (so, it should be UTF-8 encoded and contain no zero bytes). A fixer tool
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
80 is expected to produce this metadata encoding if and only if the :metadata
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
81 suboption is true::
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
82
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
83 [fix]
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
84 tool:command = tool --prepend-json-metadata
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
85 tool:metadata = true
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
86
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
87 The metadata values are passed to hooks, which can be used to print summaries or
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
88 perform other post-fixing work. The supported hooks are::
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
89
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
90 "postfixfile"
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
91 Run once for each file in each revision where any fixer tools made changes
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
92 to the file content. Provides "$HG_REV" and "$HG_PATH" to identify the file,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
93 and "$HG_METADATA" with a map of fixer names to metadata values from fixer
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
94 tools that affected the file. Fixer tools that didn't affect the file have a
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
95 valueof None. Only fixer tools that executed are present in the metadata.
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
96
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
97 "postfix"
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
98 Run once after all files and revisions have been handled. Provides
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
99 "$HG_REPLACEMENTS" with information about what revisions were created and
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
100 made obsolete. Provides a boolean "$HG_WDIRWRITTEN" to indicate whether any
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
101 files in the working copy were updated. Provides a list "$HG_METADATA"
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
102 mapping fixer tool names to lists of metadata values returned from
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
103 executions that modified a file. This aggregates the same metadata
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
104 previously passed to the "postfixfile" hook.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
105 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
106
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
107 from __future__ import absolute_import
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
108
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
109 import collections
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
110 import itertools
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
111 import json
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
112 import os
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
113 import re
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
114 import subprocess
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
115
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
116 from mercurial.i18n import _
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
117 from mercurial.node import nullrev
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
118 from mercurial.node import wdirrev
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
119
39826
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
120 from mercurial.utils import (
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
121 procutil,
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
122 )
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
123
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
124 from mercurial import (
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
125 cmdutil,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
126 context,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
127 copies,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
128 error,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
129 mdiff,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
130 merge,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
131 obsolete,
37618
1edf3738e000 fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents: 37595
diff changeset
132 pycompat,
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
133 registrar,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
134 scmutil,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
135 util,
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
136 worker,
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
137 )
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
138
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
139 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
140 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
141 # be specifying the version(s) of Mercurial they are tested with, or
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
142 # leave the attribute unspecified.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
143 testedwith = 'ships-with-hg-core'
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
144
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
145 cmdtable = {}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
146 command = registrar.command(cmdtable)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
147
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
148 configtable = {}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
149 configitem = registrar.configitem(configtable)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
150
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
151 # Register the suboptions allowed for each configured fixer, and default values.
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
152 FIXER_ATTRS = {
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
153 'command': None,
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
154 'linerange': None,
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
155 'fileset': None,
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
156 'pattern': None,
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
157 'priority': 0,
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
158 'metadata': False,
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
159 }
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
160
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
161 for key, default in FIXER_ATTRS.items():
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
162 configitem('fix', '.*(:%s)?' % key, default=default, generic=True)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
163
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
164 # A good default size allows most source code files to be fixed, but avoids
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
165 # letting fixer tools choke on huge inputs, which could be surprising to the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
166 # user.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
167 configitem('fix', 'maxfilesize', default='2MB')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
168
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
169 # Allow fix commands to exit non-zero if an executed fixer tool exits non-zero.
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
170 # This helps users do shell scripts that stop when a fixer tool signals a
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
171 # problem.
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
172 configitem('fix', 'failure', default='continue')
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
173
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
174 def checktoolfailureaction(ui, message, hint=None):
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
175 """Abort with 'message' if fix.failure=abort"""
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
176 action = ui.config('fix', 'failure')
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
177 if action not in ('continue', 'abort'):
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
178 raise error.Abort(_('unknown fix.failure action: %s') % (action,),
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
179 hint=_('use "continue" or "abort"'))
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
180 if action == 'abort':
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
181 raise error.Abort(message, hint=hint)
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
182
38949
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
183 allopt = ('', 'all', False, _('fix all non-public non-obsolete revisions'))
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
184 baseopt = ('', 'base', [], _('revisions to diff against (overrides automatic '
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
185 'selection, and applies to every revision being '
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
186 'fixed)'), _('REV'))
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
187 revopt = ('r', 'rev', [], _('revisions to fix'), _('REV'))
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
188 wdiropt = ('w', 'working-dir', False, _('fix the working directory'))
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
189 wholeopt = ('', 'whole', False, _('always fix every line of a file'))
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
190 usage = _('[OPTION]... [FILE]...')
b0c591950e51 fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents: 38860
diff changeset
191
40293
c303d65d2e34 help: assigning categories to existing commands
rdamazio@google.com
parents: 39836
diff changeset
192 @command('fix', [allopt, baseopt, revopt, wdiropt, wholeopt], usage,
c303d65d2e34 help: assigning categories to existing commands
rdamazio@google.com
parents: 39836
diff changeset
193 helpcategory=command.CATEGORY_FILE_CONTENTS)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
194 def fix(ui, repo, *pats, **opts):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
195 """rewrite file content in changesets or working directory
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
196
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
197 Runs any configured tools to fix the content of files. Only affects files
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
198 with changes, unless file arguments are provided. Only affects changed lines
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
199 of files, unless the --whole flag is used. Some tools may always affect the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
200 whole file regardless of --whole.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
201
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
202 If revisions are specified with --rev, those revisions will be checked, and
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
203 they may be replaced with new revisions that have fixed file content. It is
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
204 desirable to specify all descendants of each specified revision, so that the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
205 fixes propagate to the descendants. If all descendants are fixed at the same
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
206 time, no merging, rebasing, or evolution will be required.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
207
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
208 If --working-dir is used, files with uncommitted changes in the working copy
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
209 will be fixed. If the checked-out revision is also fixed, the working
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
210 directory will update to the replacement revision.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
211
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
212 When determining what lines of each file to fix at each revision, the whole
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
213 set of revisions being fixed is considered, so that fixes to earlier
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
214 revisions are not forgotten in later ones. The --base flag can be used to
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
215 override this default behavior, though it is not usually desirable to do so.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
216 """
37618
1edf3738e000 fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents: 37595
diff changeset
217 opts = pycompat.byteskwargs(opts)
37595
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37213
diff changeset
218 if opts['all']:
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37213
diff changeset
219 if opts['rev']:
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37213
diff changeset
220 raise error.Abort(_('cannot specify both "--rev" and "--all"'))
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37213
diff changeset
221 opts['rev'] = ['not public() and not obsolete()']
e2506748b47f fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents: 37213
diff changeset
222 opts['working_dir'] = True
38420
c1f4364f9336 fix: include cleanupnodes() in transaction
Martin von Zweigbergk <martinvonz@google.com>
parents: 37774
diff changeset
223 with repo.wlock(), repo.lock(), repo.transaction('fix'):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
224 revstofix = getrevstofix(ui, repo, opts)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
225 basectxs = getbasectxs(repo, opts, revstofix)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
226 workqueue, numitems = getworkqueue(ui, repo, pats, opts, revstofix,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
227 basectxs)
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
228 fixers = getfixers(ui)
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
229
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
230 # There are no data dependencies between the workers fixing each file
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
231 # revision, so we can use all available parallelism.
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
232 def getfixes(items):
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
233 for rev, path in items:
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
234 ctx = repo[rev]
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
235 olddata = ctx[path].data()
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
236 metadata, newdata = fixfile(ui, opts, fixers, ctx, path,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
237 basectxs[rev])
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
238 # Don't waste memory/time passing unchanged content back, but
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
239 # produce one result per item either way.
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
240 yield (rev, path, metadata,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
241 newdata if newdata != olddata else None)
40431
8ebb05f747e5 fix: disable use of thread-based worker
Yuya Nishihara <yuya@tcha.org>
parents: 40293
diff changeset
242 results = worker.worker(ui, 1.0, getfixes, tuple(), workqueue,
8ebb05f747e5 fix: disable use of thread-based worker
Yuya Nishihara <yuya@tcha.org>
parents: 40293
diff changeset
243 threadsafe=False)
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
244
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
245 # We have to hold on to the data for each successor revision in memory
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
246 # until all its parents are committed. We ensure this by committing and
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
247 # freeing memory for the revisions in some topological order. This
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
248 # leaves a little bit of memory efficiency on the table, but also makes
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
249 # the tests deterministic. It might also be considered a feature since
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
250 # it makes the results more easily reproducible.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
251 filedata = collections.defaultdict(dict)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
252 aggregatemetadata = collections.defaultdict(list)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
253 replacements = {}
38950
35bc4b6e132d fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents: 38949
diff changeset
254 wdirwritten = False
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
255 commitorder = sorted(revstofix, reverse=True)
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
256 with ui.makeprogress(topic=_('fixing'), unit=_('files'),
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
257 total=sum(numitems.values())) as progress:
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
258 for rev, path, filerevmetadata, newdata in results:
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
259 progress.increment(item=path)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
260 for fixername, fixermetadata in filerevmetadata.items():
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
261 aggregatemetadata[fixername].append(fixermetadata)
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
262 if newdata is not None:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
263 filedata[rev][path] = newdata
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
264 hookargs = {
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
265 'rev': rev,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
266 'path': path,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
267 'metadata': filerevmetadata,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
268 }
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
269 repo.hook('postfixfile', throw=False,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
270 **pycompat.strkwargs(hookargs))
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
271 numitems[rev] -= 1
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
272 # Apply the fixes for this and any other revisions that are
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
273 # ready and sitting at the front of the queue. Using a loop here
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
274 # prevents the queue from being blocked by the first revision to
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
275 # be ready out of order.
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
276 while commitorder and not numitems[commitorder[-1]]:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
277 rev = commitorder.pop()
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
278 ctx = repo[rev]
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
279 if rev == wdirrev:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
280 writeworkingdir(repo, ctx, filedata[rev], replacements)
38950
35bc4b6e132d fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents: 38949
diff changeset
281 wdirwritten = bool(filedata[rev])
38537
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
282 else:
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
283 replacerev(ui, repo, ctx, filedata[rev], replacements)
a3be09e277e9 fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents: 38536
diff changeset
284 del filedata[rev]
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
285
38950
35bc4b6e132d fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents: 38949
diff changeset
286 cleanup(repo, replacements, wdirwritten)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
287 hookargs = {
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
288 'replacements': replacements,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
289 'wdirwritten': wdirwritten,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
290 'metadata': aggregatemetadata,
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
291 }
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
292 repo.hook('postfix', throw=True, **pycompat.strkwargs(hookargs))
38811
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
293
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
294 def cleanup(repo, replacements, wdirwritten):
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
295 """Calls scmutil.cleanupnodes() with the given replacements.
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
296
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
297 "replacements" is a dict from nodeid to nodeid, with one key and one value
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
298 for every revision that was affected by fixing. This is slightly different
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
299 from cleanupnodes().
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
300
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
301 "wdirwritten" is a bool which tells whether the working copy was affected by
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
302 fixing, since it has no entry in "replacements".
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
303
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
304 Useful as a hook point for extending "hg fix" with output summarizing the
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
305 effects of the command, though we choose not to output anything here.
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
306 """
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
307 replacements = {prec: [succ] for prec, succ in replacements.iteritems()}
64535d43c103 fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents: 38770
diff changeset
308 scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
309
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
310 def getworkqueue(ui, repo, pats, opts, revstofix, basectxs):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
311 """"Constructs the list of files to be fixed at specific revisions
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
312
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
313 It is up to the caller how to consume the work items, and the only
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
314 dependence between them is that replacement revisions must be committed in
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
315 topological order. Each work item represents a file in the working copy or
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
316 in some revision that should be fixed and written back to the working copy
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
317 or into a replacement revision.
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
318
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
319 Work items for the same revision are grouped together, so that a worker
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
320 pool starting with the first N items in parallel is likely to finish the
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
321 first revision's work before other revisions. This can allow us to write
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
322 the result to disk and reduce memory footprint. At time of writing, the
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
323 partition strategy in worker.py seems favorable to this. We also sort the
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
324 items by ascending revision number to match the order in which we commit
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
325 the fixes later.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
326 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
327 workqueue = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
328 numitems = collections.defaultdict(int)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
329 maxfilesize = ui.configbytes('fix', 'maxfilesize')
38536
5ffe2041d427 fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents: 38423
diff changeset
330 for rev in sorted(revstofix):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
331 fixctx = repo[rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
332 match = scmutil.match(fixctx, pats, opts)
42009
8f427f7c1f71 fix: make the order of the work queue deterministic
Danny Hooper <hooper@google.com>
parents: 42008
diff changeset
333 for path in sorted(pathstofix(
8f427f7c1f71 fix: make the order of the work queue deterministic
Danny Hooper <hooper@google.com>
parents: 42008
diff changeset
334 ui, repo, pats, opts, match, basectxs[rev], fixctx)):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
335 fctx = fixctx[path]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
336 if fctx.islink():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
337 continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
338 if fctx.size() > maxfilesize:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
339 ui.warn(_('ignoring file larger than %s: %s\n') %
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
340 (util.bytecount(maxfilesize), path))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
341 continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
342 workqueue.append((rev, path))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
343 numitems[rev] += 1
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
344 return workqueue, numitems
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
345
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
346 def getrevstofix(ui, repo, opts):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
347 """Returns the set of revision numbers that should be fixed"""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
348 revs = set(scmutil.revrange(repo, opts['rev']))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
349 for rev in revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
350 checkfixablectx(ui, repo, repo[rev])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
351 if revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
352 cmdutil.checkunfinished(repo)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
353 checknodescendants(repo, revs)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
354 if opts.get('working_dir'):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
355 revs.add(wdirrev)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
356 if list(merge.mergestate.read(repo).unresolved()):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
357 raise error.Abort('unresolved conflicts', hint="use 'hg resolve'")
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
358 if not revs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
359 raise error.Abort(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
360 'no changesets specified', hint='use --rev or --working-dir')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
361 return revs
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
362
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
363 def checknodescendants(repo, revs):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
364 if (not obsolete.isenabled(repo, obsolete.allowunstableopt) and
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
365 repo.revs('(%ld::) - (%ld)', revs, revs)):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
366 raise error.Abort(_('can only fix a changeset together '
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
367 'with all its descendants'))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
368
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
369 def checkfixablectx(ui, repo, ctx):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
370 """Aborts if the revision shouldn't be replaced with a fixed one."""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
371 if not ctx.mutable():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
372 raise error.Abort('can\'t fix immutable changeset %s' %
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
373 (scmutil.formatchangeid(ctx),))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
374 if ctx.obsolete():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
375 # It would be better to actually check if the revision has a successor.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
376 allowdivergence = ui.configbool('experimental',
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
377 'evolution.allowdivergence')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
378 if not allowdivergence:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
379 raise error.Abort('fixing obsolete revision could cause divergence')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
380
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
381 def pathstofix(ui, repo, pats, opts, match, basectxs, fixctx):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
382 """Returns the set of files that should be fixed in a context
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
383
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
384 The result depends on the base contexts; we include any file that has
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
385 changed relative to any of the base contexts. Base contexts should be
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
386 ancestors of the context being fixed.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
387 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
388 files = set()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
389 for basectx in basectxs:
38770
260c17eaf3f7 fix: use ctx1.status(ctx2) instead of repo.status(ctx1, ctx2)
Martin von Zweigbergk <martinvonz@google.com>
parents: 38590
diff changeset
390 stat = basectx.status(fixctx, match=match, listclean=bool(pats),
260c17eaf3f7 fix: use ctx1.status(ctx2) instead of repo.status(ctx1, ctx2)
Martin von Zweigbergk <martinvonz@google.com>
parents: 38590
diff changeset
391 listunknown=bool(pats))
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
392 files.update(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
393 set(itertools.chain(stat.added, stat.modified, stat.clean,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
394 stat.unknown)))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
395 return files
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
396
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
397 def lineranges(opts, path, basectxs, fixctx, content2):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
398 """Returns the set of line ranges that should be fixed in a file
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
399
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
400 Of the form [(10, 20), (30, 40)].
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
401
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
402 This depends on the given base contexts; we must consider lines that have
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
403 changed versus any of the base contexts, and whether the file has been
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
404 renamed versus any of them.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
405
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
406 Another way to understand this is that we exclude line ranges that are
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
407 common to the file in all base contexts.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
408 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
409 if opts.get('whole'):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
410 # Return a range containing all lines. Rely on the diff implementation's
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
411 # idea of how many lines are in the file, instead of reimplementing it.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
412 return difflineranges('', content2)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
413
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
414 rangeslist = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
415 for basectx in basectxs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
416 basepath = copies.pathcopies(basectx, fixctx).get(path, path)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
417 if basepath in basectx:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
418 content1 = basectx[basepath].data()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
419 else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
420 content1 = ''
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
421 rangeslist.extend(difflineranges(content1, content2))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
422 return unionranges(rangeslist)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
423
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
424 def unionranges(rangeslist):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
425 """Return the union of some closed intervals
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
426
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
427 >>> unionranges([])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
428 []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
429 >>> unionranges([(1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
430 [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
431 >>> unionranges([(1, 100), (1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
432 [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
433 >>> unionranges([(1, 100), (2, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
434 [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
435 >>> unionranges([(1, 99), (1, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
436 [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
437 >>> unionranges([(1, 100), (40, 60)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
438 [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
439 >>> unionranges([(1, 49), (50, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
440 [(1, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
441 >>> unionranges([(1, 48), (50, 100)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
442 [(1, 48), (50, 100)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
443 >>> unionranges([(1, 2), (3, 4), (5, 6)])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
444 [(1, 6)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
445 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
446 rangeslist = sorted(set(rangeslist))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
447 unioned = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
448 if rangeslist:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
449 unioned, rangeslist = [rangeslist[0]], rangeslist[1:]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
450 for a, b in rangeslist:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
451 c, d = unioned[-1]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
452 if a > d + 1:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
453 unioned.append((a, b))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
454 else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
455 unioned[-1] = (c, max(b, d))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
456 return unioned
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
457
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
458 def difflineranges(content1, content2):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
459 """Return list of line number ranges in content2 that differ from content1.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
460
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
461 Line numbers are 1-based. The numbers are the first and last line contained
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
462 in the range. Single-line ranges have the same line number for the first and
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
463 last line. Excludes any empty ranges that result from lines that are only
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
464 present in content1. Relies on mdiff's idea of where the line endings are in
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
465 the string.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
466
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
467 >>> from mercurial import pycompat
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
468 >>> lines = lambda s: b'\\n'.join([c for c in pycompat.iterbytestr(s)])
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
469 >>> difflineranges2 = lambda a, b: difflineranges(lines(a), lines(b))
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
470 >>> difflineranges2(b'', b'')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
471 []
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
472 >>> difflineranges2(b'a', b'')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
473 []
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
474 >>> difflineranges2(b'', b'A')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
475 [(1, 1)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
476 >>> difflineranges2(b'a', b'a')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
477 []
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
478 >>> difflineranges2(b'a', b'A')
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
479 [(1, 1)]
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
480 >>> difflineranges2(b'ab', b'')
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
481 []
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
482 >>> difflineranges2(b'', b'AB')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
483 [(1, 2)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
484 >>> difflineranges2(b'abc', b'ac')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
485 []
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
486 >>> difflineranges2(b'ab', b'aCb')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
487 [(2, 2)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
488 >>> difflineranges2(b'abc', b'aBc')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
489 [(2, 2)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
490 >>> difflineranges2(b'ab', b'AB')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
491 [(1, 2)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
492 >>> difflineranges2(b'abcde', b'aBcDe')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
493 [(2, 2), (4, 4)]
37213
893ff8c3bc57 py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents: 37207
diff changeset
494 >>> difflineranges2(b'abcde', b'aBCDe')
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
495 [(2, 4)]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
496 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
497 ranges = []
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
498 for lines, kind in mdiff.allblocks(content1, content2):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
499 firstline, lastline = lines[2:4]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
500 if kind == '!' and firstline != lastline:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
501 ranges.append((firstline + 1, lastline))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
502 return ranges
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
503
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
504 def getbasectxs(repo, opts, revstofix):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
505 """Returns a map of the base contexts for each revision
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
506
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
507 The base contexts determine which lines are considered modified when we
38590
f068495a1c28 fix: add test case that shows why --whole with --base is useful
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
508 attempt to fix just the modified lines in a file. It also determines which
f068495a1c28 fix: add test case that shows why --whole with --base is useful
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
509 files we attempt to fix, so it is important to compute this even when
f068495a1c28 fix: add test case that shows why --whole with --base is useful
Danny Hooper <hooper@google.com>
parents: 38537
diff changeset
510 --whole is used.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
511 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
512 # The --base flag overrides the usual logic, and we give every revision
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
513 # exactly the set of baserevs that the user specified.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
514 if opts.get('base'):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
515 baserevs = set(scmutil.revrange(repo, opts.get('base')))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
516 if not baserevs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
517 baserevs = {nullrev}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
518 basectxs = {repo[rev] for rev in baserevs}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
519 return {rev: basectxs for rev in revstofix}
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
520
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
521 # Proceed in topological order so that we can easily determine each
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
522 # revision's baserevs by looking at its parents and their baserevs.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
523 basectxs = collections.defaultdict(set)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
524 for rev in sorted(revstofix):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
525 ctx = repo[rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
526 for pctx in ctx.parents():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
527 if pctx.rev() in basectxs:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
528 basectxs[rev].update(basectxs[pctx.rev()])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
529 else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
530 basectxs[rev].add(pctx)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
531 return basectxs
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
532
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
533 def fixfile(ui, opts, fixers, fixctx, path, basectxs):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
534 """Run any configured fixers that should affect the file in this context
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
535
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
536 Returns the file content that results from applying the fixers in some order
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
537 starting with the file's content in the fixctx. Fixers that support line
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
538 ranges will affect lines that have changed relative to any of the basectxs
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
539 (i.e. they will only avoid lines that are common to all basectxs).
38967
a009589cd32a fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents: 38950
diff changeset
540
a009589cd32a fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents: 38950
diff changeset
541 A fixer tool's stdout will become the file's new content if and only if it
a009589cd32a fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents: 38950
diff changeset
542 exits with code zero.
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
543 """
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
544 metadata = {}
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
545 newdata = fixctx[path].data()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
546 for fixername, fixer in fixers.iteritems():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
547 if fixer.affects(opts, fixctx, path):
38860
257c9846b532 fix: compute changed lines lazily to make whole-file fixer tools faster
Danny Hooper <hooper@google.com>
parents: 38811
diff changeset
548 rangesfn = lambda: lineranges(opts, path, basectxs, fixctx, newdata)
257c9846b532 fix: compute changed lines lazily to make whole-file fixer tools faster
Danny Hooper <hooper@google.com>
parents: 38811
diff changeset
549 command = fixer.command(ui, path, rangesfn)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
550 if command is None:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
551 continue
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
552 ui.debug('subprocess: %s\n' % (command,))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
553 proc = subprocess.Popen(
39836
f1d6021453c2 py3: remove a couple of superfluous calls to pycompat.rapply()
Matt Harbison <matt_harbison@yahoo.com>
parents: 39826
diff changeset
554 procutil.tonativestr(command),
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
555 shell=True,
39826
c31ce080eb75 py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents: 38967
diff changeset
556 cwd=procutil.tonativestr(b'/'),
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
557 stdin=subprocess.PIPE,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
558 stdout=subprocess.PIPE,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
559 stderr=subprocess.PIPE)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
560 stdout, stderr = proc.communicate(newdata)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
561 if stderr:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
562 showstderr(ui, fixctx.rev(), fixername, stderr)
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
563 newerdata = stdout
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
564 if fixer.shouldoutputmetadata():
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
565 try:
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
566 metadatajson, newerdata = stdout.split('\0', 1)
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
567 metadata[fixername] = json.loads(metadatajson)
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
568 except ValueError:
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
569 ui.warn(_('ignored invalid output from fixer tool: %s\n') %
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
570 (fixername,))
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
571 continue
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
572 else:
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
573 metadata[fixername] = None
38967
a009589cd32a fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents: 38950
diff changeset
574 if proc.returncode == 0:
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
575 newdata = newerdata
40532
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
576 else:
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
577 if not stderr:
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
578 message = _('exited with status %d\n') % (proc.returncode,)
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
579 showstderr(ui, fixctx.rev(), fixername, message)
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
580 checktoolfailureaction(
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
581 ui, _('no fixes will be applied'),
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
582 hint=_('use --config fix.failure=continue to apply any '
93bab80993f4 fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents: 40431
diff changeset
583 'successful fixes anyway'))
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
584 return metadata, newdata
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
585
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
586 def showstderr(ui, rev, fixername, stderr):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
587 """Writes the lines of the stderr string as warnings on the ui
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
588
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
589 Uses the revision number and fixername to give more context to each line of
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
590 the error message. Doesn't include file names, since those take up a lot of
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
591 space and would tend to be included in the error message if they were
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
592 relevant.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
593 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
594 for line in re.split('[\r\n]+', stderr):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
595 if line:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
596 ui.warn(('['))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
597 if rev is None:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
598 ui.warn(_('wdir'), label='evolve.rev')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
599 else:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
600 ui.warn((str(rev)), label='evolve.rev')
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
601 ui.warn(('] %s: %s\n') % (fixername, line))
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
602
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
603 def writeworkingdir(repo, ctx, filedata, replacements):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
604 """Write new content to the working copy and check out the new p1 if any
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
605
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
606 We check out a new revision if and only if we fixed something in both the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
607 working directory and its parent revision. This avoids the need for a full
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
608 update/merge, and means that the working directory simply isn't affected
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
609 unless the --working-dir flag is given.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
610
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
611 Directly updates the dirstate for the affected files.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
612 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
613 for path, data in filedata.iteritems():
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
614 fctx = ctx[path]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
615 fctx.write(data, fctx.flags())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
616 if repo.dirstate[path] == 'n':
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
617 repo.dirstate.normallookup(path)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
618
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
619 oldparentnodes = repo.dirstate.parents()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
620 newparentnodes = [replacements.get(n, n) for n in oldparentnodes]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
621 if newparentnodes != oldparentnodes:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
622 repo.setparents(*newparentnodes)
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
623
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
624 def replacerev(ui, repo, ctx, filedata, replacements):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
625 """Commit a new revision like the given one, but with file content changes
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
626
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
627 "ctx" is the original revision to be replaced by a modified one.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
628
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
629 "filedata" is a dict that maps paths to their new file content. All other
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
630 paths will be recreated from the original revision without changes.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
631 "filedata" may contain paths that didn't exist in the original revision;
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
632 they will be added.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
633
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
634 "replacements" is a dict that maps a single node to a single node, and it is
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
635 updated to indicate the original revision is replaced by the newly created
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
636 one. No entry is added if the replacement's node already exists.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
637
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
638 The new revision has the same parents as the old one, unless those parents
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
639 have already been replaced, in which case those replacements are the parents
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
640 of this new revision. Thus, if revisions are replaced in topological order,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
641 there is no need to rebase them into the original topology later.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
642 """
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
643
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
644 p1rev, p2rev = repo.changelog.parentrevs(ctx.rev())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
645 p1ctx, p2ctx = repo[p1rev], repo[p2rev]
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
646 newp1node = replacements.get(p1ctx.node(), p1ctx.node())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
647 newp2node = replacements.get(p2ctx.node(), p2ctx.node())
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
648
40570
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
649 # We don't want to create a revision that has no changes from the original,
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
650 # but we should if the original revision's parent has been replaced.
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
651 # Otherwise, we would produce an orphan that needs no actual human
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
652 # intervention to evolve. We can't rely on commit() to avoid creating the
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
653 # un-needed revision because the extra field added below produces a new hash
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
654 # regardless of file content changes.
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
655 if (not filedata and
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
656 p1ctx.node() not in replacements and
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
657 p2ctx.node() not in replacements):
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
658 return
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
659
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
660 def filectxfn(repo, memctx, path):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
661 if path not in ctx:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
662 return None
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
663 fctx = ctx[path]
41994
550a172a603b memctx: rename constructor argument "copied" to "copysource" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41777
diff changeset
664 copysource = fctx.copysource()
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
665 return context.memfilectx(
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
666 repo,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
667 memctx,
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
668 path=fctx.path(),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
669 data=filedata.get(path, fctx.data()),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
670 islink=fctx.islink(),
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
671 isexec=fctx.isexec(),
41994
550a172a603b memctx: rename constructor argument "copied" to "copysource" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 41777
diff changeset
672 copysource=copysource)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
673
40570
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
674 extra = ctx.extra().copy()
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
675 extra['fix_source'] = ctx.hex()
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
676
38423
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
677 memctx = context.memctx(
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
678 repo,
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
679 parents=(newp1node, newp2node),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
680 text=ctx.description(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
681 files=set(ctx.files()) | set(filedata.keys()),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
682 filectxfn=filectxfn,
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
683 user=ctx.user(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
684 date=ctx.date(),
40570
ad71c792a8d8 fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents: 40566
diff changeset
685 extra=extra,
38423
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
686 branch=ctx.branch(),
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
687 editor=None)
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
688 sucnode = memctx.commit()
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
689 prenode = ctx.node()
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
690 if prenode == sucnode:
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
691 ui.debug('node %s already existed\n' % (ctx.hex()))
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
692 else:
32fba6fe893d scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents: 38420
diff changeset
693 replacements[ctx.node()] = sucnode
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
694
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
695 def getfixers(ui):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
696 """Returns a map of configured fixer tools indexed by their names
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
697
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
698 Each value is a Fixer object with methods that implement the behavior of the
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
699 fixer's config suboptions. Does not validate the config values.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
700 """
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
701 fixers = {}
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
702 for name in fixernames(ui):
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
703 fixers[name] = Fixer()
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
704 attrs = ui.configsuboptions('fix', name)[1]
40533
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
705 if 'fileset' in attrs and 'pattern' not in attrs:
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
706 ui.warn(_('the fix.tool:fileset config name is deprecated; '
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
707 'please rename it to fix.tool:pattern\n'))
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
708 attrs['pattern'] = attrs['fileset']
40566
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
709 for key, default in FIXER_ATTRS.items():
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
710 setattr(fixers[name], pycompat.sysstr('_' + key),
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
711 attrs.get(key, default))
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
712 fixers[name]._priority = int(fixers[name]._priority)
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
713 return collections.OrderedDict(
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
714 sorted(fixers.items(), key=lambda item: item[1]._priority,
b9557567cc3f fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents: 40533
diff changeset
715 reverse=True))
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
716
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
717 def fixernames(ui):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
718 """Returns the names of [fix] config options that have suboptions"""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
719 names = set()
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
720 for k, v in ui.configitems('fix'):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
721 if ':' in k:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
722 names.add(k.split(':', 1)[0])
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
723 return names
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
724
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
725 class Fixer(object):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
726 """Wraps the raw config values for a fixer with methods"""
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
727
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
728 def affects(self, opts, fixctx, path):
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
729 """Should this fixer run on the file at the given path and context?"""
40533
2ecf5c24d0cd fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents: 40532
diff changeset
730 return scmutil.match(fixctx, [self._pattern], opts)(path)
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
731
42194
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
732 def shouldoutputmetadata(self):
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
733 """Should the stdout of this fixer start with JSON and a null byte?"""
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
734 return self._metadata
0da689a60163 fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents: 42009
diff changeset
735
38860
257c9846b532 fix: compute changed lines lazily to make whole-file fixer tools faster
Danny Hooper <hooper@google.com>
parents: 38811
diff changeset
736 def command(self, ui, path, rangesfn):
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
737 """A shell command to use to invoke this fixer on the given file/lines
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
738
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
739 May return None if there is no appropriate command to run for the given
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
740 parameters.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
741 """
37774
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
742 expand = cmdutil.rendercommandtemplate
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
743 parts = [expand(ui, self._command,
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
744 {'rootpath': path, 'basename': os.path.basename(path)})]
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
745 if self._linerange:
38860
257c9846b532 fix: compute changed lines lazily to make whole-file fixer tools faster
Danny Hooper <hooper@google.com>
parents: 38811
diff changeset
746 ranges = rangesfn()
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
747 if not ranges:
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
748 # No line ranges to fix, so don't run the fixer.
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
749 return None
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
750 for first, last in ranges:
37774
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
751 parts.append(expand(ui, self._linerange,
d6970628b95f fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents: 37618
diff changeset
752 {'first': first, 'last': last}))
37183
ded5ea279a93 fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff changeset
753 return ' '.join(parts)