Mercurial > public > mercurial-scm > hg-stable
annotate hgext/fix.py @ 43058:808a57a08470
fix: add :enabled sub-config for fixer tools
This allows distributing opt-in fixer tool configurations in .hgrc
files. This may be useful for adding default configs in core, or for
orgranizations that want to provide configs to their users.
Tools are still enabled by default because it would be confusing to add a
config and find that it has no effect until you add enabled=true.
Differential Revision: https://phab.mercurial-scm.org/D6975
author | Danny Hooper <hooper@google.com> |
---|---|
date | Sat, 05 Oct 2019 07:10:34 -0700 |
parents | e9f503074044 |
children | 2372284d9457 |
rev | line source |
---|---|
37185
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} |
40583
2ecf5c24d0cd
fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents:
40582
diff
changeset
|
18 clang-format:pattern=set:**.cpp or **.hpp |
37185
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 |
40582
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
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:
40417
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:
40417
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:
40417
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:
40417
diff
changeset
|
26 command:: |
37185
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 |
42772
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
39 Deleted sections of a file will be ignored by :linerange, because there is no |
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
40 corresponding line range in the version being fixed. |
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
41 |
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
42 By default, tools that set :linerange will only be executed if there is at least |
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
43 one changed line range. This is meant to prevent accidents like running a code |
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
44 formatter in such a way that it unexpectedly reformats the whole file. If such a |
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
45 tool needs to operate on unchanged files, it should set the :skipclean suboption |
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
46 to false. |
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
47 |
40583
2ecf5c24d0cd
fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents:
40582
diff
changeset
|
48 The :pattern suboption determines which files will be passed through each |
2ecf5c24d0cd
fix: rename :fileset subconfig to :pattern
Danny Hooper <hooper@google.com>
parents:
40582
diff
changeset
|
49 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:
40582
diff
changeset
|
50 arguments to :hg:`fix`, the intersection of these patterns is used. |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
51 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
52 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
|
53 processed by :hg:`fix`:: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
54 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
55 [fix] |
40582
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
56 maxfilesize = 2MB |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
57 |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
58 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:
40417
diff
changeset
|
59 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:
40417
diff
changeset
|
60 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:
40417
diff
changeset
|
61 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:
40417
diff
changeset
|
62 |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
63 [fix] |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
64 failure = abort |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
65 |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
66 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:
40583
diff
changeset
|
67 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:
40583
diff
changeset
|
68 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:
40583
diff
changeset
|
69 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:
40583
diff
changeset
|
70 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:
40583
diff
changeset
|
71 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:
40583
diff
changeset
|
72 |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
73 [fix] |
41129
d8f5c615e811
tests: use more portable flags in test-fix.t
Danny Hooper <hooper@google.com>
parents:
40617
diff
changeset
|
74 sort:command = sort -n |
d8f5c615e811
tests: use more portable flags in test-fix.t
Danny Hooper <hooper@google.com>
parents:
40617
diff
changeset
|
75 head:command = head -n 10 |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
76 sort:pattern = numbers.txt |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
77 head:pattern = numbers.txt |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
78 sort:priority = 2 |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
79 head:priority = 1 |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
80 |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
81 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:
40583
diff
changeset
|
82 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:
40583
diff
changeset
|
83 different values for the arguments added by the :linerange suboption. |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
84 |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
85 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
|
86 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
|
87 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
|
88 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
|
89 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
|
90 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
|
91 |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
92 [fix] |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
93 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
|
94 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
|
95 |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
96 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
|
97 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
|
98 |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
99 "postfixfile" |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
100 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
|
101 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
|
102 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
|
103 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
|
104 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
|
105 |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
106 "postfix" |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
107 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
|
108 "$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
|
109 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
|
110 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
|
111 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
|
112 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
|
113 previously passed to the "postfixfile" hook. |
42700
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
114 |
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
115 Fixer tools are run the in repository's root directory. This allows them to read |
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
116 configuration files from the working copy, or even write to the working copy. |
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
117 The working copy is not updated to match the revision being fixed. In fact, |
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
118 several revisions may be fixed in parallel. Writes to the working copy are not |
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
119 amended into the revision being fixed; fixer tools should always write fixed |
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
120 file content back to stdout as documented above. |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
121 """ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
122 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
123 from __future__ import absolute_import |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
124 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
125 import collections |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
126 import itertools |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
127 import json |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
128 import os |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
129 import re |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
130 import subprocess |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
131 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
132 from mercurial.i18n import _ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
133 from mercurial.node import nullrev |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
134 from mercurial.node import wdirrev |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
135 |
39831
c31ce080eb75
py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents:
39005
diff
changeset
|
136 from mercurial.utils import ( |
c31ce080eb75
py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents:
39005
diff
changeset
|
137 procutil, |
42772
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
138 stringutil, |
39831
c31ce080eb75
py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents:
39005
diff
changeset
|
139 ) |
c31ce080eb75
py3: convert arguments, cwd and env to native strings when spawning subprocess
Matt Harbison <matt_harbison@yahoo.com>
parents:
39005
diff
changeset
|
140 |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
141 from mercurial import ( |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
142 cmdutil, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
143 context, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
144 copies, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
145 error, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
146 mdiff, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
147 merge, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
148 obsolete, |
37618
1edf3738e000
fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents:
37595
diff
changeset
|
149 pycompat, |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
150 registrar, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
151 scmutil, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
152 util, |
38537
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
153 worker, |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
154 ) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
155 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
156 # 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
|
157 # 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
|
158 # 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
|
159 # leave the attribute unspecified. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
160 testedwith = 'ships-with-hg-core' |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
161 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
162 cmdtable = {} |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
163 command = registrar.command(cmdtable) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
164 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
165 configtable = {} |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
166 configitem = registrar.configitem(configtable) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
167 |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
168 # Register the suboptions allowed for each configured fixer, and default values. |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
169 FIXER_ATTRS = { |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
170 'command': None, |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
171 'linerange': None, |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
172 'pattern': None, |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
173 'priority': 0, |
42773
2d70b1118af2
fix: correctly parse the :metadata subconfig
Danny Hooper <hooper@google.com>
parents:
42772
diff
changeset
|
174 'metadata': 'false', |
42772
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
175 'skipclean': 'true', |
43058
808a57a08470
fix: add :enabled sub-config for fixer tools
Danny Hooper <hooper@google.com>
parents:
42774
diff
changeset
|
176 'enabled': 'true', |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
177 } |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
178 |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
179 for key, default in FIXER_ATTRS.items(): |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
180 configitem('fix', '.*(:%s)?' % key, default=default, generic=True) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
181 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
182 # 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
|
183 # 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
|
184 # user. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
185 configitem('fix', 'maxfilesize', default='2MB') |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
186 |
40582
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
187 # 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:
40417
diff
changeset
|
188 # 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:
40417
diff
changeset
|
189 # problem. |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
190 configitem('fix', 'failure', default='continue') |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
191 |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
192 def checktoolfailureaction(ui, message, hint=None): |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
193 """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:
40417
diff
changeset
|
194 action = ui.config('fix', 'failure') |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
195 if action not in ('continue', 'abort'): |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
196 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:
40417
diff
changeset
|
197 hint=_('use "continue" or "abort"')) |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
198 if action == 'abort': |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
199 raise error.Abort(message, hint=hint) |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
200 |
38987
b0c591950e51
fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents:
38899
diff
changeset
|
201 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:
38899
diff
changeset
|
202 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:
38899
diff
changeset
|
203 '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:
38899
diff
changeset
|
204 'fixed)'), _('REV')) |
b0c591950e51
fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents:
38899
diff
changeset
|
205 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:
38899
diff
changeset
|
206 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:
38899
diff
changeset
|
207 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:
38899
diff
changeset
|
208 usage = _('[OPTION]... [FILE]...') |
b0c591950e51
fix: pull out flag definitions to make them re-usable from extensions
Danny Hooper <hooper@google.com>
parents:
38899
diff
changeset
|
209 |
40293
c303d65d2e34
help: assigning categories to existing commands
rdamazio@google.com
parents:
39841
diff
changeset
|
210 @command('fix', [allopt, baseopt, revopt, wdiropt, wholeopt], usage, |
c303d65d2e34
help: assigning categories to existing commands
rdamazio@google.com
parents:
39841
diff
changeset
|
211 helpcategory=command.CATEGORY_FILE_CONTENTS) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
212 def fix(ui, repo, *pats, **opts): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
213 """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
|
214 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
215 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
|
216 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
|
217 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
|
218 whole file regardless of --whole. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
219 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
220 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
|
221 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
|
222 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
|
223 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
|
224 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
|
225 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
226 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
|
227 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
|
228 directory will update to the replacement revision. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
229 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
230 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
|
231 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
|
232 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
|
233 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
|
234 """ |
37618
1edf3738e000
fix: port most of the way to python 3
Augie Fackler <augie@google.com>
parents:
37595
diff
changeset
|
235 opts = pycompat.byteskwargs(opts) |
37595
e2506748b47f
fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents:
37215
diff
changeset
|
236 if opts['all']: |
e2506748b47f
fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents:
37215
diff
changeset
|
237 if opts['rev']: |
e2506748b47f
fix: add --all flag to fix non-public non-obsolete revisions
Danny Hooper <hooper@google.com>
parents:
37215
diff
changeset
|
238 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:
37215
diff
changeset
|
239 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:
37215
diff
changeset
|
240 opts['working_dir'] = True |
38426
c1f4364f9336
fix: include cleanupnodes() in transaction
Martin von Zweigbergk <martinvonz@google.com>
parents:
37774
diff
changeset
|
241 with repo.wlock(), repo.lock(), repo.transaction('fix'): |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
242 revstofix = getrevstofix(ui, repo, opts) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
243 basectxs = getbasectxs(repo, opts, revstofix) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
244 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
|
245 basectxs) |
38537
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
246 fixers = getfixers(ui) |
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
247 |
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
248 # 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:
38429
diff
changeset
|
249 # revision, so we can use all available parallelism. |
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
250 def getfixes(items): |
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
251 for rev, path in items: |
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
252 ctx = repo[rev] |
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
253 olddata = ctx[path].data() |
42700
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
254 metadata, newdata = fixfile(ui, repo, opts, fixers, ctx, path, |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
255 basectxs[rev]) |
38537
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
256 # 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:
38429
diff
changeset
|
257 # produce one result per item either way. |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
258 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
|
259 newdata if newdata != olddata else None) |
40417
8ebb05f747e5
fix: disable use of thread-based worker
Yuya Nishihara <yuya@tcha.org>
parents:
40293
diff
changeset
|
260 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
|
261 threadsafe=False) |
38537
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
262 |
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
263 # 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:
38429
diff
changeset
|
264 # 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:
38429
diff
changeset
|
265 # 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:
38429
diff
changeset
|
266 # 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:
38429
diff
changeset
|
267 # 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:
38429
diff
changeset
|
268 # it makes the results more easily reproducible. |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
269 filedata = collections.defaultdict(dict) |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
270 aggregatemetadata = collections.defaultdict(list) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
271 replacements = {} |
38988
35bc4b6e132d
fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents:
38987
diff
changeset
|
272 wdirwritten = False |
38537
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
273 commitorder = sorted(revstofix, reverse=True) |
38538
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
274 with ui.makeprogress(topic=_('fixing'), unit=_('files'), |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
275 total=sum(numitems.values())) as progress: |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
276 for rev, path, filerevmetadata, newdata in results: |
38538
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
277 progress.increment(item=path) |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
278 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
|
279 aggregatemetadata[fixername].append(fixermetadata) |
38538
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
280 if newdata is not None: |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
281 filedata[rev][path] = newdata |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
282 hookargs = { |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
283 '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
|
284 '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
|
285 '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
|
286 } |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
287 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
|
288 **pycompat.strkwargs(hookargs)) |
38538
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
289 numitems[rev] -= 1 |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
290 # 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:
38537
diff
changeset
|
291 # 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:
38537
diff
changeset
|
292 # 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:
38537
diff
changeset
|
293 # be ready out of order. |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
294 while commitorder and not numitems[commitorder[-1]]: |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
295 rev = commitorder.pop() |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
296 ctx = repo[rev] |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
297 if rev == wdirrev: |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
298 writeworkingdir(repo, ctx, filedata[rev], replacements) |
38988
35bc4b6e132d
fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents:
38987
diff
changeset
|
299 wdirwritten = bool(filedata[rev]) |
38538
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
300 else: |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
301 replacerev(ui, repo, ctx, filedata[rev], replacements) |
a3be09e277e9
fix: add progress bar for number of file revisions processed
Danny Hooper <hooper@google.com>
parents:
38537
diff
changeset
|
302 del filedata[rev] |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
303 |
38988
35bc4b6e132d
fix: correctly set wdirwritten given that the dict item is deleted
Danny Hooper <hooper@google.com>
parents:
38987
diff
changeset
|
304 cleanup(repo, replacements, wdirwritten) |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
305 hookargs = { |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
306 '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
|
307 '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
|
308 '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
|
309 } |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
310 repo.hook('postfix', throw=True, **pycompat.strkwargs(hookargs)) |
38851
64535d43c103
fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents:
38811
diff
changeset
|
311 |
64535d43c103
fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents:
38811
diff
changeset
|
312 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:
38811
diff
changeset
|
313 """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:
38811
diff
changeset
|
314 |
64535d43c103
fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents:
38811
diff
changeset
|
315 "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:
38811
diff
changeset
|
316 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:
38811
diff
changeset
|
317 from cleanupnodes(). |
64535d43c103
fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents:
38811
diff
changeset
|
318 |
64535d43c103
fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents:
38811
diff
changeset
|
319 "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:
38811
diff
changeset
|
320 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:
38811
diff
changeset
|
321 |
64535d43c103
fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents:
38811
diff
changeset
|
322 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:
38811
diff
changeset
|
323 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:
38811
diff
changeset
|
324 """ |
64535d43c103
fix: add a monkey-patchable point after all new revisions have been committed
Danny Hooper <hooper@google.com>
parents:
38811
diff
changeset
|
325 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:
38811
diff
changeset
|
326 scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
327 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
328 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
|
329 """"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
|
330 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
331 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
|
332 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
|
333 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
|
334 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
|
335 or into a replacement revision. |
38537
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
336 |
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
337 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:
38429
diff
changeset
|
338 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:
38429
diff
changeset
|
339 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:
38429
diff
changeset
|
340 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:
38429
diff
changeset
|
341 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:
38429
diff
changeset
|
342 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:
38429
diff
changeset
|
343 the fixes later. |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
344 """ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
345 workqueue = [] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
346 numitems = collections.defaultdict(int) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
347 maxfilesize = ui.configbytes('fix', 'maxfilesize') |
38537
5ffe2041d427
fix: use a worker pool to parallelize running tools
Danny Hooper <hooper@google.com>
parents:
38429
diff
changeset
|
348 for rev in sorted(revstofix): |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
349 fixctx = repo[rev] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
350 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
|
351 for path in sorted(pathstofix( |
8f427f7c1f71
fix: make the order of the work queue deterministic
Danny Hooper <hooper@google.com>
parents:
42008
diff
changeset
|
352 ui, repo, pats, opts, match, basectxs[rev], fixctx)): |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
353 fctx = fixctx[path] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
354 if fctx.islink(): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
355 continue |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
356 if fctx.size() > maxfilesize: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
357 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
|
358 (util.bytecount(maxfilesize), path)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
359 continue |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
360 workqueue.append((rev, path)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
361 numitems[rev] += 1 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
362 return workqueue, numitems |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
363 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
364 def getrevstofix(ui, repo, opts): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
365 """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
|
366 revs = set(scmutil.revrange(repo, opts['rev'])) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
367 for rev in revs: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
368 checkfixablectx(ui, repo, repo[rev]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
369 if revs: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
370 cmdutil.checkunfinished(repo) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
371 checknodescendants(repo, revs) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
372 if opts.get('working_dir'): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
373 revs.add(wdirrev) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
374 if list(merge.mergestate.read(repo).unresolved()): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
375 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
|
376 if not revs: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
377 raise error.Abort( |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
378 '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
|
379 return revs |
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 checknodescendants(repo, revs): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
382 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
|
383 repo.revs('(%ld::) - (%ld)', revs, revs)): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
384 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
|
385 'with all its descendants')) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
386 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
387 def checkfixablectx(ui, repo, ctx): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
388 """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
|
389 if not ctx.mutable(): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
390 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
|
391 (scmutil.formatchangeid(ctx),)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
392 if ctx.obsolete(): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
393 # 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
|
394 allowdivergence = ui.configbool('experimental', |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
395 'evolution.allowdivergence') |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
396 if not allowdivergence: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
397 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
|
398 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
399 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
|
400 """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
|
401 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
402 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
|
403 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
|
404 ancestors of the context being fixed. |
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 files = set() |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
407 for basectx in basectxs: |
38811
260c17eaf3f7
fix: use ctx1.status(ctx2) instead of repo.status(ctx1, ctx2)
Martin von Zweigbergk <martinvonz@google.com>
parents:
38591
diff
changeset
|
408 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:
38591
diff
changeset
|
409 listunknown=bool(pats)) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
410 files.update( |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
411 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
|
412 stat.unknown))) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
413 return files |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
414 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
415 def lineranges(opts, path, basectxs, fixctx, content2): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
416 """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
|
417 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
418 Of the form [(10, 20), (30, 40)]. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
419 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
420 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
|
421 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
|
422 renamed versus any of them. |
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 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
|
425 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
|
426 """ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
427 if opts.get('whole'): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
428 # 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
|
429 # 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
|
430 return difflineranges('', content2) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
431 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
432 rangeslist = [] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
433 for basectx in basectxs: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
434 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
|
435 if basepath in basectx: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
436 content1 = basectx[basepath].data() |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
437 else: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
438 content1 = '' |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
439 rangeslist.extend(difflineranges(content1, content2)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
440 return unionranges(rangeslist) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
441 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
442 def unionranges(rangeslist): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
443 """Return the union of some closed intervals |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
444 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
445 >>> unionranges([]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
446 [] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
447 >>> unionranges([(1, 100)]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
448 [(1, 100)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
449 >>> unionranges([(1, 100), (1, 100)]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
450 [(1, 100)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
451 >>> unionranges([(1, 100), (2, 100)]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
452 [(1, 100)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
453 >>> unionranges([(1, 99), (1, 100)]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
454 [(1, 100)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
455 >>> unionranges([(1, 100), (40, 60)]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
456 [(1, 100)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
457 >>> unionranges([(1, 49), (50, 100)]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
458 [(1, 100)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
459 >>> unionranges([(1, 48), (50, 100)]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
460 [(1, 48), (50, 100)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
461 >>> unionranges([(1, 2), (3, 4), (5, 6)]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
462 [(1, 6)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
463 """ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
464 rangeslist = sorted(set(rangeslist)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
465 unioned = [] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
466 if rangeslist: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
467 unioned, rangeslist = [rangeslist[0]], rangeslist[1:] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
468 for a, b in rangeslist: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
469 c, d = unioned[-1] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
470 if a > d + 1: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
471 unioned.append((a, b)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
472 else: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
473 unioned[-1] = (c, max(b, d)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
474 return unioned |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
475 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
476 def difflineranges(content1, content2): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
477 """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
|
478 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
479 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
|
480 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
|
481 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
|
482 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
|
483 the string. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
484 |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
485 >>> from mercurial import pycompat |
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
486 >>> lines = lambda s: b'\\n'.join([c for c in pycompat.iterbytestr(s)]) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
487 >>> difflineranges2 = lambda a, b: difflineranges(lines(a), lines(b)) |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
488 >>> difflineranges2(b'', b'') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
489 [] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
490 >>> difflineranges2(b'a', b'') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
491 [] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
492 >>> difflineranges2(b'', b'A') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
493 [(1, 1)] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
494 >>> difflineranges2(b'a', b'a') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
495 [] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
496 >>> difflineranges2(b'a', b'A') |
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
497 [(1, 1)] |
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
498 >>> difflineranges2(b'ab', b'') |
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
499 [] |
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
500 >>> difflineranges2(b'', b'AB') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
501 [(1, 2)] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
502 >>> difflineranges2(b'abc', b'ac') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
503 [] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
504 >>> difflineranges2(b'ab', b'aCb') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
505 [(2, 2)] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
506 >>> difflineranges2(b'abc', b'aBc') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
507 [(2, 2)] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
508 >>> difflineranges2(b'ab', b'AB') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
509 [(1, 2)] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
510 >>> difflineranges2(b'abcde', b'aBcDe') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
511 [(2, 2), (4, 4)] |
37215
893ff8c3bc57
py3: fix fix doctests to be bytes-safe
Yuya Nishihara <yuya@tcha.org>
parents:
37209
diff
changeset
|
512 >>> difflineranges2(b'abcde', b'aBCDe') |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
513 [(2, 4)] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
514 """ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
515 ranges = [] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
516 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
|
517 firstline, lastline = lines[2:4] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
518 if kind == '!' and firstline != lastline: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
519 ranges.append((firstline + 1, lastline)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
520 return ranges |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
521 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
522 def getbasectxs(repo, opts, revstofix): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
523 """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
|
524 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
525 The base contexts determine which lines are considered modified when we |
38591
f068495a1c28
fix: add test case that shows why --whole with --base is useful
Danny Hooper <hooper@google.com>
parents:
38538
diff
changeset
|
526 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:
38538
diff
changeset
|
527 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:
38538
diff
changeset
|
528 --whole is used. |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
529 """ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
530 # 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
|
531 # 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
|
532 if opts.get('base'): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
533 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
|
534 if not baserevs: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
535 baserevs = {nullrev} |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
536 basectxs = {repo[rev] for rev in baserevs} |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
537 return {rev: basectxs for rev in revstofix} |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
538 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
539 # 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
|
540 # 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
|
541 basectxs = collections.defaultdict(set) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
542 for rev in sorted(revstofix): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
543 ctx = repo[rev] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
544 for pctx in ctx.parents(): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
545 if pctx.rev() in basectxs: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
546 basectxs[rev].update(basectxs[pctx.rev()]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
547 else: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
548 basectxs[rev].add(pctx) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
549 return basectxs |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
550 |
42700
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
551 def fixfile(ui, repo, opts, fixers, fixctx, path, basectxs): |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
552 """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
|
553 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
554 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
|
555 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
|
556 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
|
557 (i.e. they will only avoid lines that are common to all basectxs). |
39005
a009589cd32a
fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents:
38988
diff
changeset
|
558 |
a009589cd32a
fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents:
38988
diff
changeset
|
559 A fixer tool's stdout will become the file's new content if and only if it |
42700
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
560 exits with code zero. The fixer tool's working directory is the repository's |
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
561 root. |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
562 """ |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
563 metadata = {} |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
564 newdata = fixctx[path].data() |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
565 for fixername, fixer in fixers.iteritems(): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
566 if fixer.affects(opts, fixctx, path): |
42774
e9f503074044
fix: pass line ranges as value instead of callback
Danny Hooper <hooper@google.com>
parents:
42773
diff
changeset
|
567 ranges = lineranges(opts, path, basectxs, fixctx, newdata) |
e9f503074044
fix: pass line ranges as value instead of callback
Danny Hooper <hooper@google.com>
parents:
42773
diff
changeset
|
568 command = fixer.command(ui, path, ranges) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
569 if command is None: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
570 continue |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
571 ui.debug('subprocess: %s\n' % (command,)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
572 proc = subprocess.Popen( |
39841
f1d6021453c2
py3: remove a couple of superfluous calls to pycompat.rapply()
Matt Harbison <matt_harbison@yahoo.com>
parents:
39831
diff
changeset
|
573 procutil.tonativestr(command), |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
574 shell=True, |
42700
74b4cd091e0d
fix: run fixer tools in the repo root as cwd so they can use the working copy
Danny Hooper <hooper@google.com>
parents:
42687
diff
changeset
|
575 cwd=repo.root, |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
576 stdin=subprocess.PIPE, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
577 stdout=subprocess.PIPE, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
578 stderr=subprocess.PIPE) |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
579 stdout, stderr = proc.communicate(newdata) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
580 if stderr: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
581 showstderr(ui, fixctx.rev(), fixername, stderr) |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
582 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
|
583 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
|
584 try: |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
585 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
|
586 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
|
587 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
|
588 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
|
589 (fixername,)) |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
590 continue |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
591 else: |
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
592 metadata[fixername] = None |
39005
a009589cd32a
fix: determine fixer tool failure by exit code instead of stderr
Danny Hooper <hooper@google.com>
parents:
38988
diff
changeset
|
593 if proc.returncode == 0: |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
594 newdata = newerdata |
40582
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
595 else: |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
596 if not stderr: |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
597 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:
40417
diff
changeset
|
598 showstderr(ui, fixctx.rev(), fixername, message) |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
599 checktoolfailureaction( |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
600 ui, _('no fixes will be applied'), |
93bab80993f4
fix: add a config to abort when a fixer tool fails
Danny Hooper <hooper@google.com>
parents:
40417
diff
changeset
|
601 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:
40417
diff
changeset
|
602 'successful fixes anyway')) |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
603 return metadata, newdata |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
604 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
605 def showstderr(ui, rev, fixername, stderr): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
606 """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
|
607 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
608 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
|
609 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
|
610 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
|
611 relevant. |
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 line in re.split('[\r\n]+', stderr): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
614 if line: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
615 ui.warn(('[')) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
616 if rev is None: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
617 ui.warn(_('wdir'), label='evolve.rev') |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
618 else: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
619 ui.warn((str(rev)), label='evolve.rev') |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
620 ui.warn(('] %s: %s\n') % (fixername, line)) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
621 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
622 def writeworkingdir(repo, ctx, filedata, replacements): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
623 """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
|
624 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
625 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
|
626 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
|
627 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
|
628 unless the --working-dir flag is given. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
629 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
630 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
|
631 """ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
632 for path, data in filedata.iteritems(): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
633 fctx = ctx[path] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
634 fctx.write(data, fctx.flags()) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
635 if repo.dirstate[path] == 'n': |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
636 repo.dirstate.normallookup(path) |
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 oldparentnodes = repo.dirstate.parents() |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
639 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
|
640 if newparentnodes != oldparentnodes: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
641 repo.setparents(*newparentnodes) |
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 def replacerev(ui, repo, ctx, filedata, replacements): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
644 """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
|
645 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
646 "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
|
647 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
648 "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
|
649 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
|
650 "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
|
651 they will be added. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
652 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
653 "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
|
654 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
|
655 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
|
656 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
657 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
|
658 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
|
659 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
|
660 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
|
661 """ |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
662 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
663 p1rev, p2rev = repo.changelog.parentrevs(ctx.rev()) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
664 p1ctx, p2ctx = repo[p1rev], repo[p2rev] |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
665 newp1node = replacements.get(p1ctx.node(), p1ctx.node()) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
666 newp2node = replacements.get(p2ctx.node(), p2ctx.node()) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
667 |
40617
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
668 # 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:
40613
diff
changeset
|
669 # 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:
40613
diff
changeset
|
670 # 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:
40613
diff
changeset
|
671 # 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:
40613
diff
changeset
|
672 # 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:
40613
diff
changeset
|
673 # regardless of file content changes. |
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
674 if (not filedata and |
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
675 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:
40613
diff
changeset
|
676 p2ctx.node() not in replacements): |
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
677 return |
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
678 |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
679 def filectxfn(repo, memctx, path): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
680 if path not in ctx: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
681 return None |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
682 fctx = ctx[path] |
41994
550a172a603b
memctx: rename constructor argument "copied" to "copysource" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
41786
diff
changeset
|
683 copysource = fctx.copysource() |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
684 return context.memfilectx( |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
685 repo, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
686 memctx, |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
687 path=fctx.path(), |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
688 data=filedata.get(path, fctx.data()), |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
689 islink=fctx.islink(), |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
690 isexec=fctx.isexec(), |
41994
550a172a603b
memctx: rename constructor argument "copied" to "copysource" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents:
41786
diff
changeset
|
691 copysource=copysource) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
692 |
40617
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
693 extra = ctx.extra().copy() |
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
694 extra['fix_source'] = ctx.hex() |
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
695 |
38429
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
696 memctx = context.memctx( |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
697 repo, |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
698 parents=(newp1node, newp2node), |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
699 text=ctx.description(), |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
700 files=set(ctx.files()) | set(filedata.keys()), |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
701 filectxfn=filectxfn, |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
702 user=ctx.user(), |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
703 date=ctx.date(), |
40617
ad71c792a8d8
fix: add extra field to fixed revisions to avoid creating obsolescence cycles
Danny Hooper <hooper@google.com>
parents:
40613
diff
changeset
|
704 extra=extra, |
38429
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
705 branch=ctx.branch(), |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
706 editor=None) |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
707 sucnode = memctx.commit() |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
708 prenode = ctx.node() |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
709 if prenode == sucnode: |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
710 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:
38426
diff
changeset
|
711 else: |
32fba6fe893d
scmutil: make cleanupnodes optionally also fix the phase
Martin von Zweigbergk <martinvonz@google.com>
parents:
38426
diff
changeset
|
712 replacements[ctx.node()] = sucnode |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
713 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
714 def getfixers(ui): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
715 """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
|
716 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
717 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
|
718 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
|
719 """ |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
720 fixers = {} |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
721 for name in fixernames(ui): |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
722 fixers[name] = Fixer() |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
723 attrs = ui.configsuboptions('fix', name)[1] |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
724 for key, default in FIXER_ATTRS.items(): |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
725 setattr(fixers[name], pycompat.sysstr('_' + key), |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
726 attrs.get(key, default)) |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
727 fixers[name]._priority = int(fixers[name]._priority) |
42773
2d70b1118af2
fix: correctly parse the :metadata subconfig
Danny Hooper <hooper@google.com>
parents:
42772
diff
changeset
|
728 fixers[name]._metadata = stringutil.parsebool(fixers[name]._metadata) |
42772
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
729 fixers[name]._skipclean = stringutil.parsebool(fixers[name]._skipclean) |
43058
808a57a08470
fix: add :enabled sub-config for fixer tools
Danny Hooper <hooper@google.com>
parents:
42774
diff
changeset
|
730 fixers[name]._enabled = stringutil.parsebool(fixers[name]._enabled) |
42687
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
731 # Don't use a fixer if it has no pattern configured. It would be |
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
732 # dangerous to let it affect all files. It would be pointless to let it |
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
733 # affect no files. There is no reasonable subset of files to use as the |
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
734 # default. |
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
735 if fixers[name]._pattern is None: |
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
736 ui.warn( |
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
737 _('fixer tool has no pattern configuration: %s\n') % (name,)) |
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
738 del fixers[name] |
43058
808a57a08470
fix: add :enabled sub-config for fixer tools
Danny Hooper <hooper@google.com>
parents:
42774
diff
changeset
|
739 elif not fixers[name]._enabled: |
808a57a08470
fix: add :enabled sub-config for fixer tools
Danny Hooper <hooper@google.com>
parents:
42774
diff
changeset
|
740 ui.debug('ignoring disabled fixer tool: %s\n' % (name,)) |
808a57a08470
fix: add :enabled sub-config for fixer tools
Danny Hooper <hooper@google.com>
parents:
42774
diff
changeset
|
741 del fixers[name] |
40613
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
742 return collections.OrderedDict( |
b9557567cc3f
fix: add suboption for configuring execution order of tools
Danny Hooper <hooper@google.com>
parents:
40583
diff
changeset
|
743 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:
40583
diff
changeset
|
744 reverse=True)) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
745 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
746 def fixernames(ui): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
747 """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
|
748 names = set() |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
749 for k, v in ui.configitems('fix'): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
750 if ':' in k: |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
751 names.add(k.split(':', 1)[0]) |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
752 return names |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
753 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
754 class Fixer(object): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
755 """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
|
756 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
757 def affects(self, opts, fixctx, path): |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
758 """Should this fixer run on the file at the given path and context?""" |
42687
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
759 return (self._pattern is not None and |
2987d015aba4
fix: ignore fixer tool configurations that are missing patterns
Danny Hooper <hooper@google.com>
parents:
42685
diff
changeset
|
760 scmutil.match(fixctx, [self._pattern], opts)(path)) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
761 |
42229
0da689a60163
fix: allow fixer tools to return metadata in addition to the file content
Danny Hooper <hooper@google.com>
parents:
42009
diff
changeset
|
762 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
|
763 """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
|
764 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
|
765 |
42774
e9f503074044
fix: pass line ranges as value instead of callback
Danny Hooper <hooper@google.com>
parents:
42773
diff
changeset
|
766 def command(self, ui, path, ranges): |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
767 """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
|
768 |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
769 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
|
770 parameters. |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
771 """ |
37774
d6970628b95f
fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents:
37618
diff
changeset
|
772 expand = cmdutil.rendercommandtemplate |
d6970628b95f
fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents:
37618
diff
changeset
|
773 parts = [expand(ui, self._command, |
d6970628b95f
fix: use templater to substitute values in command string
Yuya Nishihara <yuya@tcha.org>
parents:
37618
diff
changeset
|
774 {'rootpath': path, 'basename': os.path.basename(path)})] |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
775 if self._linerange: |
42772
ed0da6e0d6ee
fix: allow tools to use :linerange, but also run if a file is unchanged
Danny Hooper <hooper@google.com>
parents:
42700
diff
changeset
|
776 if self._skipclean and not ranges: |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
777 # 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
|
778 return None |
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
779 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
|
780 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
|
781 {'first': first, 'last': last})) |
37185
ded5ea279a93
fix: new extension for automatically modifying file contents
Danny Hooper <hooper@google.com>
parents:
diff
changeset
|
782 return ' '.join(parts) |