D11280: fix: reduce number of tool executions

2021-08-11 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  By grouping together (path, ctx) pairs according to the inputs they would
  provide to fixer tools, we can deduplicate executions of fixer tools to
  significantly reduce the amount of time spent running slow tools.
  
  This change does not handle clean files in the working copy, which could still
  be deduplicated against the files in the checked out commit. It's a little
  harder to do that because the filerev is not available in the workingfilectx
  (and it doesn't exist for added files).
  
  Anecdotally, this change makes some real uses cases at Google 10x faster. I
  think we were originally hesitant to do this because the benefits weren't
  obvious, and implementing it efficiently is kind of tricky. If we simply
  memoized the formatter execution function, we would be keeping tons of file
  content in memory.

REPOSITORY
  rHG Mercurial

BRANCH
  stable

REVISION DETAIL
  https://phab.mercurial-scm.org/D11280

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1758,8 +1758,8 @@
   $ cat $LOGFILE | sort | uniq -c
 4 bar.log
 4 baz.log
-4 foo.log
-4 qux.log
+3 foo.log
+2 qux.log
 
   $ cd ..
 
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -283,20 +283,29 @@
 # There are no data dependencies between the workers fixing each file
 # revision, so we can use all available parallelism.
 def getfixes(items):
-for rev, path in items:
-ctx = repo[rev]
+for srcrev, path, dstrevs in items:
+ctx = repo[srcrev]
 olddata = ctx[path].data()
 metadata, newdata = fixfile(
-ui, repo, opts, fixers, ctx, path, basepaths, basectxs[rev]
+ui,
+repo,
+opts,
+fixers,
+ctx,
+path,
+basepaths,
+basectxs[srcrev],
 )
-# Don't waste memory/time passing unchanged content back, but
-# produce one result per item either way.
-yield (
-rev,
-path,
-metadata,
-newdata if newdata != olddata else None,
-)
+# We ungroup the work items now, because the code that consumes
+# these results has to handle each dstrev separately, and in
+# topological order. Because these are handled in topological
+# order, it's important that we pass around references to
+# "newdata" instead of copying it. Otherwise, we would be
+# keeping more copies of file content in memory at a time than
+# if we hadn't bothered to group/deduplicate the work items.
+data = newdata if newdata != olddata else None
+for dstrev in dstrevs:
+yield (dstrev, path, metadata, data)
 
 results = worker.worker(
 ui, 1.0, getfixes, tuple(), workqueue, threadsafe=False
@@ -392,7 +401,7 @@
 items by ascending revision number to match the order in which we commit
 the fixes later.
 """
-workqueue = []
+dstrevmap = collections.defaultdict(list)
 numitems = collections.defaultdict(int)
 maxfilesize = ui.configbytes(b'fix', b'maxfilesize')
 for rev in sorted(revstofix):
@@ -410,8 +419,13 @@
 % (util.bytecount(maxfilesize), path)
 )
 continue
-workqueue.append((rev, path))
+baserevs = tuple(ctx.rev() for ctx in basectxs[rev])
+dstrevmap[(fctx.filerev(), baserevs, path)].append(rev)
 numitems[rev] += 1
+workqueue = [
+(dstrevs[0], path, dstrevs)
+for (filerev, baserevs, path), dstrevs in dstrevmap.items()
+]
 return workqueue, numitems
 
 
@@ -516,9 +530,9 @@
 return {}
 
 basepaths = {}
-for rev, path in workqueue:
-fixctx = repo[rev]
-for basectx in basectxs[rev]:
+for srcrev, path, dstrevs in workqueue:
+fixctx = repo[srcrev]
+for basectx in basectxs[srcrev]:
 basepath = copies.pathcopies(basectx, fixctx).get(path, path)
 if basepath in basectx:
 basepaths[(basectx.rev(), fixctx.rev(), path)] = basepath
@@ -641,10 +655,10 @@
 toprefetch = set()
 
 # Prefetch the files that will be fixed.
-for rev, path in workqueue:
-if rev == wdirrev:
+for srcrev, path, dstrevs in workqueue:
+if srcrev == wdirrev:
 continue
-toprefetch.add((rev, path))
+ 

D11279: fix: add test to demonstrate how many times tools are executed

2021-08-11 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  The current implementation wastes a lot of effort invoking fixer tools more
  than once on the same file name+content. It is good to track changes in this
  behavior.
  
  Also included is a regression test for a corner case that I broke with my 
first
  attempt at optimizing this code.

REPOSITORY
  rHG Mercurial

BRANCH
  stable

REVISION DETAIL
  https://phab.mercurial-scm.org/D11279

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1713,3 +1713,101 @@
   r0.whole:
   hello
   
+
+We should execute the fixer tools as few times as possible, because they might
+be slow or expensive to execute. The inputs to each execution are effectively
+the file path, file content, and line ranges. So, we should be able to re-use
+results whenever those inputs are repeated. That saves a lot of work when
+fixing chains of commits that all have the same file revision for a path being
+fixed.
+
+  $ hg init numberofinvocations
+  $ cd numberofinvocations
+
+  $ printf "bar1" > bar.log
+  $ printf "baz1" > baz.log
+  $ printf "foo1" > foo.log
+  $ printf "qux1" > qux.log
+  $ hg commit -Aqm "commit1"
+
+  $ printf "bar2" > bar.log
+  $ printf "baz2" > baz.log
+  $ printf "foo2" > foo.log
+  $ hg commit -Aqm "commit2"
+
+  $ printf "bar3" > bar.log
+  $ printf "baz3" > baz.log
+  $ hg commit -Aqm "commit3"
+
+  $ printf "bar4" > bar.log
+
+  $ LOGFILE=$TESTTMP/log
+  $ LOGGER=$TESTTMP/log.py
+  $ cat >> $LOGGER < # Appends the input file's name to the log file.
+  > import sys
+  > with open('$LOGFILE', 'a') as f:
+  > f.write(sys.argv[1] + '\n')
+  > sys.stdout.write(sys.stdin.read())
+  > EOF
+
+  $ hg fix --working-dir -r "all()" \
+  >--config "fix.log:command=\"$PYTHON\" \"$LOGGER\" {rootpath}" \
+  >--config "fix.log:pattern=glob:**.log"
+
+  $ cat $LOGFILE | sort | uniq -c
+4 bar.log
+4 baz.log
+4 foo.log
+4 qux.log
+
+  $ cd ..
+
+For tools that support line ranges, it's wrong to blindly re-use fixed file
+content for the same file revision if it appears twice with different baserevs,
+because the line ranges could be different. Since computing line ranges is
+ambiguous, this isn't a matter of correctness, but it affects the usability of
+this extension. It could maybe be simpler if baserevs were computed on a
+per-file basis to make this situation impossible to construct.
+
+In the following example, we construct two subgraphs with the same file
+revisions, and fix different sub-subgraphs to get different baserevs and
+different changed line ranges. The key precondition is that revisions 1 and 4
+have the same file revision, and the key result is that their successors don't
+have the same file content, because we want to fix different areas of that same
+file revision's content.
+
+  $ hg init differentlineranges
+  $ cd differentlineranges
+
+  $ printf "a\nb\n" > file.changed
+  $ hg commit -Aqm "0 ab"
+  $ printf "a\nx\n" > file.changed
+  $ hg commit -Aqm "1 ax"
+  $ hg remove file.changed
+  $ hg commit -Aqm "2 removed"
+  $ hg revert file.changed -r 0
+  $ hg commit -Aqm "3 ab (reverted)"
+  $ hg revert file.changed -r 1
+  $ hg commit -Aqm "4 ax (reverted)"
+
+  $ hg manifest --debug --template "{hash}\n" -r 0; \
+  > hg manifest --debug --template "{hash}\n" -r 3
+  418f692145676128d2fb518b027ddbac624be76e
+  418f692145676128d2fb518b027ddbac624be76e
+  $ hg manifest --debug --template "{hash}\n" -r 1; \
+  > hg manifest --debug --template "{hash}\n" -r 4
+  09b8b3ce5a507caaa282f7262679e6d04091426c
+  09b8b3ce5a507caaa282f7262679e6d04091426c
+
+  $ hg fix --working-dir -r 1+3+4
+  3 new orphan changesets
+
+  $ hg cat file.changed -r "successors(1)" --hidden
+  a
+  X
+  $ hg cat file.changed -r "successors(4)" --hidden
+  A
+  X
+
+  $ cd ..



To: hooper, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D8287: fix: add a -s option to format a revision and its descendants

2020-03-13 Thread hooper (Danny Hooper)
hooper added a comment.


  D8283 :D8288 
 all looks good to me.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D8287/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D8287

To: martinvonz, #hg-reviewers
Cc: hooper, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D7570: match: resolve filesets against the passed `cwd`, not the current one

2019-12-12 Thread hooper (Danny Hooper)
hooper added inline comments.

INLINE COMMENTS

> martinvonz wrote in test-fix.t:1336-1342
> > `.::` doesn't include fixing wdir()
> 
> Yes, that's how revsets work (as you noted)
> 
> > `.` isn't updated unless `-w` is specified
> 
> Yes, because otherwise the working directory would appear to undo the 
> formatting changes. I don't remember why we don't just always format the 
> working directory when we format the parent of the working directory. I'm 
> sure @hooper remembers the reasoning better.
> 
> > `-w` doesn't alter `wdir()` content unless there are dirty files (makes 
> > sense), but will update `.` if starting with a clean `wdir()`
> 
> Do you mean with *just* `-w`? That shouldn't change any commits, so it seems 
> very weird if it checks out a different commit. If you meant something like 
> `-w -r .`, then that *would* format the working copy too, but it may not seem 
> like it if the working copy was clean before and after the command (but it 
> was formatted to match the parent commit).

Martin and I talked about this, and I think it would make sense to:

1. Update/fix the wdir when the parent is fixed without -w, unless the wdir has 
uncommitted changes. We want to avoid triggering any merges, or clobbering 
uncommitted changes unless asked to. "Eating uncommitted data" is a very easy 
mistake to make when writing a config for hg fix, or when the formatter has a 
bug, etc.
2. Add a --source/-s flag to hg fix, where "-s foo" means "-r (foo)::" or "-r 
(foo):: -w" depending on whether "." is contained in "(foo)::". Similar to 
rebase.
3. Maybe remove the -r flag since it's a bit of a footgun.
4. Alternatively, keep the -r flag and make merges smart enough that "hg 
evolve" can apply formatters when that makes sense as a cleanup for "foo~-1" 
after "hg fix -r foo".

REPOSITORY
  rHG Mercurial

BRANCH
  default

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7570/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7570

To: mharbison72, #hg-reviewers, durin42
Cc: durin42, hooper, yuja, martinvonz, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D7086: fix: remove a never-true check for unset pattern in Fixer.affects()

2019-10-14 Thread hooper (Danny Hooper)
hooper added a comment.


  Looks good.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D7086/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D7086

To: martinvonz, #hg-reviewers
Cc: hooper, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6975: fix: add :enabled sub-config for fixer tools

2019-10-05 Thread hooper (Danny Hooper)
Closed by commit rHG808a57a08470: fix: add :enabled sub-config for fixer tools 
(authored by hooper).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6975?vs=16824=16852

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6975/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6975

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1341,6 +1341,22 @@
 
   $ cd ..
 
+Tools can be disabled. Disabled tools do nothing but print a debug message.
+
+  $ hg init disabled
+  $ cd disabled
+
+  $ printf "foo\n" > foo
+  $ hg add -q
+  $ hg fix --debug --working-dir --config "fix.disabled:command=echo fixed" \
+  >  --config "fix.disabled:pattern=foo" \
+  >  --config "fix.disabled:enabled=false"
+  ignoring disabled fixer tool: disabled
+  $ cat foo
+  foo
+
+  $ cd ..
+
 Test that we can configure a fixer to affect all files regardless of the cwd.
 The way we invoke matching must not prohibit this.
 
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -173,6 +173,7 @@
 'priority': 0,
 'metadata': 'false',
 'skipclean': 'true',
+'enabled': 'true',
 }
 
 for key, default in FIXER_ATTRS.items():
@@ -726,6 +727,7 @@
 fixers[name]._priority = int(fixers[name]._priority)
 fixers[name]._metadata = stringutil.parsebool(fixers[name]._metadata)
 fixers[name]._skipclean = stringutil.parsebool(fixers[name]._skipclean)
+fixers[name]._enabled = stringutil.parsebool(fixers[name]._enabled)
 # Don't use a fixer if it has no pattern configured. It would be
 # dangerous to let it affect all files. It would be pointless to let it
 # affect no files. There is no reasonable subset of files to use as the
@@ -734,6 +736,9 @@
 ui.warn(
 _('fixer tool has no pattern configuration: %s\n') % (name,))
 del fixers[name]
+elif not fixers[name]._enabled:
+ui.debug('ignoring disabled fixer tool: %s\n' % (name,))
+del fixers[name]
 return collections.OrderedDict(
 sorted(fixers.items(), key=lambda item: item[1]._priority,
reverse=True))



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6975: fix: add :enabled sub-config for fixer tools

2019-10-05 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  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.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6975

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1341,6 +1341,22 @@
 
   $ cd ..
 
+Tools can be disabled. Disabled tools do nothing but print a debug message.
+
+  $ hg init disabled
+  $ cd disabled
+
+  $ printf "foo\n" > foo
+  $ hg add -q
+  $ hg fix --debug --working-dir --config "fix.disabled:command=echo fixed" \
+  >  --config "fix.disabled:pattern=foo" \
+  >  --config "fix.disabled:enabled=false"
+  ignoring disabled fixer tool: disabled
+  $ cat foo
+  foo
+
+  $ cd ..
+
 Test that we can configure a fixer to affect all files regardless of the cwd.
 The way we invoke matching must not prohibit this.
 
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -173,6 +173,7 @@
 'priority': 0,
 'metadata': 'false',
 'skipclean': 'true',
+'enabled': 'true',
 }
 
 for key, default in FIXER_ATTRS.items():
@@ -726,6 +727,7 @@
 fixers[name]._priority = int(fixers[name]._priority)
 fixers[name]._metadata = stringutil.parsebool(fixers[name]._metadata)
 fixers[name]._skipclean = stringutil.parsebool(fixers[name]._skipclean)
+fixers[name]._enabled = stringutil.parsebool(fixers[name]._enabled)
 # Don't use a fixer if it has no pattern configured. It would be
 # dangerous to let it affect all files. It would be pointless to let it
 # affect no files. There is no reasonable subset of files to use as the
@@ -734,6 +736,9 @@
 ui.warn(
 _('fixer tool has no pattern configuration: %s\n') % (name,))
 del fixers[name]
+elif not fixers[name]._enabled:
+ui.debug('ignoring disabled fixer tool: %s\n' % (name,))
+del fixers[name]
 return collections.OrderedDict(
 sorted(fixers.items(), key=lambda item: item[1]._priority,
reverse=True))



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6726: fix: correctly parse the :metadata subconfig

2019-08-14 Thread hooper (Danny Hooper)
Closed by commit rHGd82e9f7e7440: fix: correctly parse the :metadata subconfig 
(authored by hooper).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6726?vs=16193=16206

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6726/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6726

AFFECTED FILES
  hgext/fix.py
  tests/test-fix-metadata.t

CHANGE DETAILS

diff --git a/tests/test-fix-metadata.t b/tests/test-fix-metadata.t
--- a/tests/test-fix-metadata.t
+++ b/tests/test-fix-metadata.t
@@ -43,6 +43,9 @@
   > [extensions]
   > fix =
   > [fix]
+  > metadatafalse:command=cat $TESTTMP/missing
+  > metadatafalse:pattern=metadatafalse
+  > metadatafalse:metadata=false
   > missing:command=cat $TESTTMP/missing
   > missing:pattern=missing
   > missing:metadata=true
@@ -65,6 +68,7 @@
   $ hg init repo
   $ cd repo
 
+  $ printf "old content\n" > metadatafalse
   $ printf "old content\n" > invalid
   $ printf "old content\n" > missing
   $ printf "old content\n" > valid
@@ -72,15 +76,20 @@
 
   $ hg fix -w
   ignored invalid output from fixer tool: invalid
+  fixed metadatafalse in revision 2147483647 using metadatafalse
   ignored invalid output from fixer tool: missing
   fixed valid in revision 2147483647 using valid
   saw "key" 1 times
   fixed 1 files with valid
   fixed the working copy
 
-  $ cat missing invalid valid
+  $ cat metadatafalse
+  new content
+  $ cat missing
   old content
+  $ cat invalid
   old content
+  $ cat valid
   new content
 
   $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -171,7 +171,7 @@
 'linerange': None,
 'pattern': None,
 'priority': 0,
-'metadata': False,
+'metadata': 'false',
 'skipclean': 'true',
 }
 
@@ -724,6 +724,7 @@
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))
 fixers[name]._priority = int(fixers[name]._priority)
+fixers[name]._metadata = stringutil.parsebool(fixers[name]._metadata)
 fixers[name]._skipclean = stringutil.parsebool(fixers[name]._skipclean)
 # Don't use a fixer if it has no pattern configured. It would be
 # dangerous to let it affect all files. It would be pointless to let it



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6723: fix: allow tools to use :linerange, but also run if a file is unchanged

2019-08-14 Thread hooper (Danny Hooper)
Closed by commit rHG69b37b7227f2: fix: allow tools to use :linerange, but also 
run if a file is unchanged (authored by hooper).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6723?vs=16181=16205

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6723/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6723

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -147,6 +147,15 @@
 {first}   The 1-based line number of the first line in the modified range
 {last}The 1-based line number of the last line in the modified range
   
+  Deleted sections of a file will be ignored by :linerange, because there is no
+  corresponding line range in the version being fixed.
+  
+  By default, tools that set :linerange will only be executed if there is at
+  least one changed line range. This is meant to prevent accidents like running
+  a code formatter in such a way that it unexpectedly reformats the whole file.
+  If such a tool needs to operate on unchanged files, it should set the
+  :skipclean suboption to false.
+  
   The :pattern suboption determines which files will be passed through each
   configured tool. See 'hg help patterns' for possible values. If there are 
file
   arguments to 'hg fix', the intersection of these patterns is used.
@@ -1356,3 +1365,34 @@
   fixed
 
   $ cd ..
+
+Tools should be able to run on unchanged files, even if they set :linerange.
+This includes a corner case where deleted chunks of a file are not considered
+changes.
+
+  $ hg init skipclean
+  $ cd skipclean
+
+  $ printf "a\nb\nc\n" > foo
+  $ printf "a\nb\nc\n" > bar
+  $ printf "a\nb\nc\n" > baz
+  $ hg commit -Aqm "base"
+
+  $ printf "a\nc\n" > foo
+  $ printf "a\nx\nc\n" > baz
+
+  $ hg fix --working-dir foo bar baz \
+  >--config 'fix.changedlines:command=printf "Line ranges:\n"; ' \
+  >--config 'fix.changedlines:linerange=printf "{first} through 
{last}\n"; ' \
+  >--config 'fix.changedlines:pattern=rootglob:**' \
+  >--config 'fix.changedlines:skipclean=false'
+
+  $ cat foo
+  Line ranges:
+  $ cat bar
+  Line ranges:
+  $ cat baz
+  Line ranges:
+  2 through 2
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -36,6 +36,15 @@
   {first}   The 1-based line number of the first line in the modified range
   {last}The 1-based line number of the last line in the modified range
 
+Deleted sections of a file will be ignored by :linerange, because there is no
+corresponding line range in the version being fixed.
+
+By default, tools that set :linerange will only be executed if there is at 
least
+one changed line range. This is meant to prevent accidents like running a code
+formatter in such a way that it unexpectedly reformats the whole file. If such 
a
+tool needs to operate on unchanged files, it should set the :skipclean 
suboption
+to false.
+
 The :pattern suboption determines which files will be passed through each
 configured tool. See :hg:`help patterns` for possible values. If there are file
 arguments to :hg:`fix`, the intersection of these patterns is used.
@@ -126,6 +135,7 @@
 
 from mercurial.utils import (
 procutil,
+stringutil,
 )
 
 from mercurial import (
@@ -162,6 +172,7 @@
 'pattern': None,
 'priority': 0,
 'metadata': False,
+'skipclean': 'true',
 }
 
 for key, default in FIXER_ATTRS.items():
@@ -713,6 +724,7 @@
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))
 fixers[name]._priority = int(fixers[name]._priority)
+fixers[name]._skipclean = stringutil.parsebool(fixers[name]._skipclean)
 # Don't use a fixer if it has no pattern configured. It would be
 # dangerous to let it affect all files. It would be pointless to let it
 # affect no files. There is no reasonable subset of files to use as the
@@ -756,7 +768,7 @@
 {'rootpath': path, 'basename': 
os.path.basename(path)})]
 if self._linerange:
 ranges = rangesfn()
-if not ranges:
+if self._skipclean and not ranges:
 # No line ranges to fix, so don't run the fixer.
 return None
 for first, last in ranges:



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6727: fix: pass line ranges as value instead of callback

2019-08-14 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The callback no longer takes any arguments from the inner function, so we 
might
  as well call it sooner and pass the value instead. Note the value still needs
  to be recomputed every iteration to account for the previous iteration's
  changes to the file content.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6727

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -563,8 +563,8 @@
 newdata = fixctx[path].data()
 for fixername, fixer in fixers.iteritems():
 if fixer.affects(opts, fixctx, path):
-rangesfn = lambda: lineranges(opts, path, basectxs, fixctx, 
newdata)
-command = fixer.command(ui, path, rangesfn)
+ranges = lineranges(opts, path, basectxs, fixctx, newdata)
+command = fixer.command(ui, path, ranges)
 if command is None:
 continue
 ui.debug('subprocess: %s\n' % (command,))
@@ -758,7 +758,7 @@
 """Should the stdout of this fixer start with JSON and a null byte?"""
 return self._metadata
 
-def command(self, ui, path, rangesfn):
+def command(self, ui, path, ranges):
 """A shell command to use to invoke this fixer on the given file/lines
 
 May return None if there is no appropriate command to run for the given
@@ -768,7 +768,6 @@
 parts = [expand(ui, self._command,
 {'rootpath': path, 'basename': 
os.path.basename(path)})]
 if self._linerange:
-ranges = rangesfn()
 if self._skipclean and not ranges:
 # No line ranges to fix, so don't run the fixer.
 return None



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6726: fix: correctly parse the :metadata subconfig

2019-08-14 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  It's being handled as a string instead of a bool, though the thruthiness of 
the
  string makes the feature still essentially work. Added a regression test.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6726

AFFECTED FILES
  hgext/fix.py
  tests/test-fix-metadata.t

CHANGE DETAILS

diff --git a/tests/test-fix-metadata.t b/tests/test-fix-metadata.t
--- a/tests/test-fix-metadata.t
+++ b/tests/test-fix-metadata.t
@@ -43,6 +43,9 @@
   > [extensions]
   > fix =
   > [fix]
+  > metadatafalse:command=cat $TESTTMP/missing
+  > metadatafalse:pattern=metadatafalse
+  > metadatafalse:metadata=false
   > missing:command=cat $TESTTMP/missing
   > missing:pattern=missing
   > missing:metadata=true
@@ -65,6 +68,7 @@
   $ hg init repo
   $ cd repo
 
+  $ printf "old content\n" > metadatafalse
   $ printf "old content\n" > invalid
   $ printf "old content\n" > missing
   $ printf "old content\n" > valid
@@ -72,15 +76,20 @@
 
   $ hg fix -w
   ignored invalid output from fixer tool: invalid
+  fixed metadatafalse in revision 2147483647 using metadatafalse
   ignored invalid output from fixer tool: missing
   fixed valid in revision 2147483647 using valid
   saw "key" 1 times
   fixed 1 files with valid
   fixed the working copy
 
-  $ cat missing invalid valid
+  $ cat metadatafalse
+  new content
+  $ cat missing
   old content
+  $ cat invalid
   old content
+  $ cat valid
   new content
 
   $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -171,7 +171,7 @@
 'linerange': None,
 'pattern': None,
 'priority': 0,
-'metadata': False,
+'metadata': 'false',
 'skipclean': 'true',
 }
 
@@ -724,6 +724,7 @@
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))
 fixers[name]._priority = int(fixers[name]._priority)
+fixers[name]._metadata = stringutil.parsebool(fixers[name]._metadata)
 fixers[name]._skipclean = stringutil.parsebool(fixers[name]._skipclean)
 # Don't use a fixer if it has no pattern configured. It would be
 # dangerous to let it affect all files. It would be pointless to let it



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6723: fix: allow tools to use :linerange, but also run if a file is unchanged

2019-08-13 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 16181.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6723?vs=16178=16181

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6723/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6723

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -147,6 +147,15 @@
 {first}   The 1-based line number of the first line in the modified range
 {last}The 1-based line number of the last line in the modified range
   
+  Deleted sections of a file will be ignored by :linerange, because there is no
+  corresponding line range in the version being fixed.
+  
+  By default, tools that set :linerange will only be executed if there is at
+  least one changed line range. This is meant to prevent accidents like running
+  a code formatter in such a way that it unexpectedly reformats the whole file.
+  If such a tool needs to operate on unchanged files, it should set the
+  :skipclean suboption to false.
+  
   The :pattern suboption determines which files will be passed through each
   configured tool. See 'hg help patterns' for possible values. If there are 
file
   arguments to 'hg fix', the intersection of these patterns is used.
@@ -1356,3 +1365,34 @@
   fixed
 
   $ cd ..
+
+Tools should be able to run on unchanged files, even if they set :linerange.
+This includes a corner case where deleted chunks of a file are not considered
+changes.
+
+  $ hg init skipclean
+  $ cd skipclean
+
+  $ printf "a\nb\nc\n" > foo
+  $ printf "a\nb\nc\n" > bar
+  $ printf "a\nb\nc\n" > baz
+  $ hg commit -Aqm "base"
+
+  $ printf "a\nc\n" > foo
+  $ printf "a\nx\nc\n" > baz
+
+  $ hg fix --working-dir foo bar baz \
+  >--config 'fix.changedlines:command=printf "Line ranges:\n"; ' \
+  >--config 'fix.changedlines:linerange=printf "{first} through 
{last}\n"; ' \
+  >--config 'fix.changedlines:pattern=rootglob:**' \
+  >--config 'fix.changedlines:skipclean=false'
+
+  $ cat foo
+  Line ranges:
+  $ cat bar
+  Line ranges:
+  $ cat baz
+  Line ranges:
+  2 through 2
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -36,6 +36,15 @@
   {first}   The 1-based line number of the first line in the modified range
   {last}The 1-based line number of the last line in the modified range
 
+Deleted sections of a file will be ignored by :linerange, because there is no
+corresponding line range in the version being fixed.
+
+By default, tools that set :linerange will only be executed if there is at 
least
+one changed line range. This is meant to prevent accidents like running a code
+formatter in such a way that it unexpectedly reformats the whole file. If such 
a
+tool needs to operate on unchanged files, it should set the :skipclean 
suboption
+to false.
+
 The :pattern suboption determines which files will be passed through each
 configured tool. See :hg:`help patterns` for possible values. If there are file
 arguments to :hg:`fix`, the intersection of these patterns is used.
@@ -126,6 +135,7 @@
 
 from mercurial.utils import (
 procutil,
+stringutil,
 )
 
 from mercurial import (
@@ -162,6 +172,7 @@
 'pattern': None,
 'priority': 0,
 'metadata': False,
+'skipclean': 'true',
 }
 
 for key, default in FIXER_ATTRS.items():
@@ -713,6 +724,7 @@
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))
 fixers[name]._priority = int(fixers[name]._priority)
+fixers[name]._skipclean = stringutil.parsebool(fixers[name]._skipclean)
 # Don't use a fixer if it has no pattern configured. It would be
 # dangerous to let it affect all files. It would be pointless to let it
 # affect no files. There is no reasonable subset of files to use as the
@@ -756,7 +768,7 @@
 {'rootpath': path, 'basename': 
os.path.basename(path)})]
 if self._linerange:
 ranges = rangesfn()
-if not ranges:
+if self._skipclean and not ranges:
 # No line ranges to fix, so don't run the fixer.
 return None
 for first, last in ranges:



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6723: fix: allow tools to use :linerange, but also run if a file is unchanged

2019-08-12 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The definition of "unchanged" here is subtle, because pure deletion diff hunks
  are ignored. That means this is different from using the --whole flag. This
  change allows you to configure, for example, a code formatter that:
  
  1. Formats specific line ranges if specified via flags
  2. Does not format the entire file when there are no line ranges provided
  3. Performs some other kind of formatting regardless of provided line ranges
  
  This sounds a little far fetched, but it is meant to address a specific corner
  case encountered in Google's use of the fix extension. The default behavior is
  kept because it exists to prevent mistakes that could erase uncommitted
  changes.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6723

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -147,6 +147,15 @@
 {first}   The 1-based line number of the first line in the modified range
 {last}The 1-based line number of the last line in the modified range
   
+  Deleted sections of a file will be ignored by :linerange, because there is no
+  corresponding line range in the version being fixed.
+  
+  By default, tools that set :linerange will only be executed if there is at
+  least one changed line range. This is meant to prevent accidents like running
+  a code formatter in such a way that it unexpectedly reformats the whole file.
+  If such a tool needs to operate on unchanged files, it should set the
+  :skipclean suboption to false.
+  
   The :pattern suboption determines which files will be passed through each
   configured tool. See 'hg help patterns' for possible values. If there are 
file
   arguments to 'hg fix', the intersection of these patterns is used.
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -36,6 +36,15 @@
   {first}   The 1-based line number of the first line in the modified range
   {last}The 1-based line number of the last line in the modified range
 
+Deleted sections of a file will be ignored by :linerange, because there is no
+corresponding line range in the version being fixed.
+
+By default, tools that set :linerange will only be executed if there is at 
least
+one changed line range. This is meant to prevent accidents like running a code
+formatter in such a way that it unexpectedly reformats the whole file. If such 
a
+tool needs to operate on unchanged files, it should set the :skipclean 
suboption
+to false.
+
 The :pattern suboption determines which files will be passed through each
 configured tool. See :hg:`help patterns` for possible values. If there are file
 arguments to :hg:`fix`, the intersection of these patterns is used.
@@ -162,6 +171,7 @@
 'pattern': None,
 'priority': 0,
 'metadata': False,
+'skipclean': True,
 }
 
 for key, default in FIXER_ATTRS.items():
@@ -756,7 +766,7 @@
 {'rootpath': path, 'basename': 
os.path.basename(path)})]
 if self._linerange:
 ranges = rangesfn()
-if not ranges:
+if self._skipclean and not ranges:
 # No line ranges to fix, so don't run the fixer.
 return None
 for first, last in ranges:



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6440: fix: let fixer tools inherit hg's cwd so they can look at the working copy

2019-08-01 Thread hooper (Danny Hooper)
Closed by commit rHG74b4cd091e0d: fix: run fixer tools in the repo root as cwd 
so they can use the working copy (authored by hooper).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D6440?vs=16083=16104#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6440?vs=16083=16104

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6440/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6440

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -215,6 +215,13 @@
   executions that modified a file. This aggregates the same metadata
   previously passed to the "postfixfile" hook.
   
+  Fixer tools are run the in repository's root directory. This allows them to
+  read configuration files from the working copy, or even write to the working
+  copy. The working copy is not updated to match the revision being fixed. In
+  fact, several revisions may be fixed in parallel. Writes to the working copy
+  are not amended into the revision being fixed; fixer tools should always 
write
+  fixed file content back to stdout as documented above.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
@@ -1269,6 +1276,41 @@
 
   $ cd ..
 
+We run fixer tools in the repo root so they can look for config files or other
+important things in the working directory. This does NOT mean we are
+reconstructing a working copy of every revision being fixed; we're just giving
+the tool knowledge of the repo's location in case it can do something
+reasonable with that.
+
+  $ hg init subprocesscwd
+  $ cd subprocesscwd
+
+  $ cat >> .hg/hgrc < [fix]
+  > printcwd:command = pwd
+  > printcwd:pattern = path:foo/bar
+  > EOF
+
+  $ mkdir foo
+  $ printf "bar\n" > foo/bar
+  $ hg commit -Aqm blah
+
+  $ hg fix -w -r . foo/bar
+  $ hg cat -r tip foo/bar
+  $TESTTMP/subprocesscwd
+  $ cat foo/bar
+  $TESTTMP/subprocesscwd
+
+  $ cd foo
+
+  $ hg fix -w -r . bar
+  $ hg cat -r tip bar
+  $TESTTMP/subprocesscwd
+  $ cat bar
+  $TESTTMP/subprocesscwd
+
+  $ cd ../..
+
 Tools configured without a pattern are ignored. It would be too dangerous to
 run them on all files, because this might happen while testing a configuration
 that also deletes all of the file content. There is no reasonable subset of the
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -102,6 +102,13 @@
 mapping fixer tool names to lists of metadata values returned from
 executions that modified a file. This aggregates the same metadata
 previously passed to the "postfixfile" hook.
+
+Fixer tools are run the in repository's root directory. This allows them to 
read
+configuration files from the working copy, or even write to the working copy.
+The working copy is not updated to match the revision being fixed. In fact,
+several revisions may be fixed in parallel. Writes to the working copy are not
+amended into the revision being fixed; fixer tools should always write fixed
+file content back to stdout as documented above.
 """
 
 from __future__ import absolute_import
@@ -232,7 +239,7 @@
 for rev, path in items:
 ctx = repo[rev]
 olddata = ctx[path].data()
-metadata, newdata = fixfile(ui, opts, fixers, ctx, path,
+metadata, newdata = fixfile(ui, repo, opts, fixers, ctx, path,
 basectxs[rev])
 # Don't waste memory/time passing unchanged content back, but
 # produce one result per item either way.
@@ -529,7 +536,7 @@
 basectxs[rev].add(pctx)
 return basectxs
 
-def fixfile(ui, opts, fixers, fixctx, path, basectxs):
+def fixfile(ui, repo, opts, fixers, fixctx, path, basectxs):
 """Run any configured fixers that should affect the file in this context
 
 Returns the file content that results from applying the fixers in some 
order
@@ -538,7 +545,8 @@
 (i.e. they will only avoid lines that are common to all basectxs).
 
 A fixer tool's stdout will become the file's new content if and only if it
-exits with code zero.
+exits with code zero. The fixer tool's working directory is the 
repository's
+root.
 """
 metadata = {}
 newdata = fixctx[path].data()
@@ -552,7 +560,7 @@
 proc = subprocess.Popen(
 procutil.tonativestr(command),
 shell=True,
-cwd=procutil.tonativestr(b'/'),
+cwd=repo.root,
 stdin=subprocess.PIPE,
 stdout=subprocess.PIPE,
 stderr=subprocess.PIPE)



To: hooper, #hg-reviewers
Cc: martinvonz, durin42, mercurial-devel

D6698: fix: add some new test cases

2019-07-29 Thread hooper (Danny Hooper)
Closed by commit rHG4b04244f2d5f: fix: add some new test cases (authored by 
hooper).
This revision was automatically updated to reflect the committed changes.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6698?vs=16082=16094

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6698/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6698

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -439,6 +439,18 @@
   $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.changed
   $ hg commit -Aqm "foo"
   $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.changed
+
+  $ hg fix --working-dir
+  $ cat foo.changed
+  ZZ
+  a
+  c
+  DD
+  EE
+  FF
+  f
+  GG
+
   $ hg fix --working-dir --whole
   $ cat foo.changed
   ZZ
@@ -526,6 +538,21 @@
 
   $ cd ..
 
+If we try to fix a missing file, we still fix other files.
+
+  $ hg init fixmissingfile
+  $ cd fixmissingfile
+
+  $ printf "fix me!\n" > foo.whole
+  $ hg add
+  adding foo.whole
+  $ hg fix --working-dir foo.whole bar.whole
+  bar.whole: $ENOENT$
+  $ cat *.whole
+  FIX ME!
+
+  $ cd ..
+
 Specifying a directory name should fix all its files and subdirectories.
 
   $ hg init fixdirectory



To: hooper, #hg-reviewers, pulkit
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6440: fix: let fixer tools inherit hg's cwd so they can look at the working copy

2019-07-26 Thread hooper (Danny Hooper)
hooper added a comment.


  In D6440#97422 , @durin42 wrote:
  
  > I still think we should fix the cwd for fixers, but it seems Martin and I 
agree that repo-root is more consistent. Would you be willing to reroll with 
repo-root instead of cwd?
  
  Done.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6440/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6440

To: hooper, #hg-reviewers
Cc: martinvonz, durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6440: fix: let fixer tools inherit hg's cwd so they can look at the working copy

2019-07-26 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 16083.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6440?vs=15244=16083

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6440/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6440

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -215,6 +215,13 @@
   executions that modified a file. This aggregates the same metadata
   previously passed to the "postfixfile" hook.
   
+  Fixer tools are run the in repository's root directory. This allows them to
+  read configuration files from the working copy, or even write to the working
+  copy. The working copy is not updated to match the revision being fixed. In
+  fact, several revisions may be fixed in parallel. Writes to the working copy
+  are not amended into the revision being fixed; fixer tools should always 
write
+  fixed file content back to stdout as documented above.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
@@ -1264,3 +1271,38 @@
 
   $ cd ..
 
+We run fixer tools in the repo root so they can look for config files or other
+important things in the working directory. This does NOT mean we are
+reconstructing a working copy of every revision being fixed; we're just giving
+the tool knowledge of the repo's location in case it can do something
+reasonable with that.
+
+  $ hg init subprocesscwd
+  $ cd subprocesscwd
+
+  $ cat >> .hg/hgrc < [fix]
+  > printcwd:command = pwd
+  > printcwd:pattern = path:foo/bar
+  > EOF
+
+  $ mkdir foo
+  $ printf "bar\n" > foo/bar
+  $ hg commit -Aqm blah
+
+  $ hg fix -w -r . foo/bar
+  $ hg cat -r tip foo/bar
+  $TESTTMP/subprocesscwd
+  $ cat foo/bar
+  $TESTTMP/subprocesscwd
+
+  $ cd foo
+
+  $ hg fix -w -r . bar
+  $ hg cat -r tip bar
+  $TESTTMP/subprocesscwd
+  $ cat bar
+  $TESTTMP/subprocesscwd
+
+  $ cd ../..
+
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -102,6 +102,13 @@
 mapping fixer tool names to lists of metadata values returned from
 executions that modified a file. This aggregates the same metadata
 previously passed to the "postfixfile" hook.
+
+Fixer tools are run the in repository's root directory. This allows them to 
read
+configuration files from the working copy, or even write to the working copy.
+The working copy is not updated to match the revision being fixed. In fact,
+several revisions may be fixed in parallel. Writes to the working copy are not
+amended into the revision being fixed; fixer tools should always write fixed
+file content back to stdout as documented above.
 """
 
 from __future__ import absolute_import
@@ -233,7 +240,7 @@
 for rev, path in items:
 ctx = repo[rev]
 olddata = ctx[path].data()
-metadata, newdata = fixfile(ui, opts, fixers, ctx, path,
+metadata, newdata = fixfile(ui, repo, opts, fixers, ctx, path,
 basectxs[rev])
 # Don't waste memory/time passing unchanged content back, but
 # produce one result per item either way.
@@ -530,7 +537,7 @@
 basectxs[rev].add(pctx)
 return basectxs
 
-def fixfile(ui, opts, fixers, fixctx, path, basectxs):
+def fixfile(ui, repo, opts, fixers, fixctx, path, basectxs):
 """Run any configured fixers that should affect the file in this context
 
 Returns the file content that results from applying the fixers in some 
order
@@ -539,7 +546,8 @@
 (i.e. they will only avoid lines that are common to all basectxs).
 
 A fixer tool's stdout will become the file's new content if and only if it
-exits with code zero.
+exits with code zero. The fixer tool's working directory is the 
repository's
+root.
 """
 metadata = {}
 newdata = fixctx[path].data()
@@ -553,7 +561,7 @@
 proc = subprocess.Popen(
 procutil.tonativestr(command),
 shell=True,
-cwd=procutil.tonativestr(b'/'),
+cwd=repo.root,
 stdin=subprocess.PIPE,
 stdout=subprocess.PIPE,
 stderr=subprocess.PIPE)



To: hooper, #hg-reviewers
Cc: martinvonz, durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6698: fix: add some new test cases

2019-07-26 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  These cover a couple of behaviors we were testing at Google that weren't
  covered here before.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6698

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -439,6 +439,18 @@
   $ printf "a\nb\nc\nd\ne\nf\ng\n" > foo.changed
   $ hg commit -Aqm "foo"
   $ printf "zz\na\nc\ndd\nee\nff\nf\ngg\n" > foo.changed
+
+  $ hg fix --working-dir
+  $ cat foo.changed
+  ZZ
+  a
+  c
+  DD
+  EE
+  FF
+  f
+  GG
+
   $ hg fix --working-dir --whole
   $ cat foo.changed
   ZZ
@@ -526,6 +538,21 @@
 
   $ cd ..
 
+If we try to fix a missing file, we still fix other files.
+
+  $ hg init fixmissingfile
+  $ cd fixmissingfile
+
+  $ printf "fix me!\n" > foo.whole
+  $ hg add
+  adding foo.whole
+  $ hg fix --working-dir foo.whole bar.whole
+  bar.whole: $ENOENT$
+  $ cat *.whole
+  FIX ME!
+
+  $ cd ..
+
 Specifying a directory name should fix all its files and subdirectories.
 
   $ hg init fixdirectory



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6693: fix: ignore fixer tool configurations that are missing patterns

2019-07-26 Thread hooper (Danny Hooper)
Closed by commit rHG2987d015aba4: fix: ignore fixer tool configurations that 
are missing patterns (authored by hooper).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D6693?vs=16062=16081#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6693?vs=16062=16081

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6693/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6693

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1242,6 +1242,26 @@
 
   $ cd ..
 
+Tools configured without a pattern are ignored. It would be too dangerous to
+run them on all files, because this might happen while testing a configuration
+that also deletes all of the file content. There is no reasonable subset of the
+files to use as a default. Users should be explicit about what files are
+affected by a tool. This test also confirms that we don't crash when the
+pattern config is missing, and that we only warn about it once.
+
+  $ hg init nopatternconfigured
+  $ cd nopatternconfigured
+
+  $ printf "foo" > foo
+  $ printf "bar" > bar
+  $ hg add -q
+  $ hg fix --debug --working-dir --config "fix.nopattern:command=echo fixed"
+  fixer tool has no pattern configuration: nopattern
+  $ cat foo bar
+  foobar (no-eol)
+
+  $ cd ..
+
 Test that we can configure a fixer to affect all files regardless of the cwd.
 The way we invoke matching must not prohibit this.
 
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -705,6 +705,14 @@
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))
 fixers[name]._priority = int(fixers[name]._priority)
+# Don't use a fixer if it has no pattern configured. It would be
+# dangerous to let it affect all files. It would be pointless to let it
+# affect no files. There is no reasonable subset of files to use as the
+# default.
+if fixers[name]._pattern is None:
+ui.warn(
+_('fixer tool has no pattern configuration: %s\n') % (name,))
+del fixers[name]
 return collections.OrderedDict(
 sorted(fixers.items(), key=lambda item: item[1]._priority,
reverse=True))
@@ -722,7 +730,8 @@
 
 def affects(self, opts, fixctx, path):
 """Should this fixer run on the file at the given path and context?"""
-return scmutil.match(fixctx, [self._pattern], opts)(path)
+return (self._pattern is not None and
+scmutil.match(fixctx, [self._pattern], opts)(path))
 
 def shouldoutputmetadata(self):
 """Should the stdout of this fixer start with JSON and a null byte?"""



To: hooper, #hg-reviewers
Cc: martinvonz, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6692: fix: add a test case around the effect of cwd on pattern matching

2019-07-26 Thread hooper (Danny Hooper)
Closed by commit rHG22c4bd7d1cbf: fix: add a test case around the effect of cwd 
on pattern matching (authored by hooper).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6692?vs=16061=16080

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6692/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6692

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1242,3 +1242,28 @@
 
   $ cd ..
 
+Test that we can configure a fixer to affect all files regardless of the cwd.
+The way we invoke matching must not prohibit this.
+
+  $ hg init affectallfiles
+  $ cd affectallfiles
+
+  $ mkdir foo bar
+  $ printf "foo" > foo/file
+  $ printf "bar" > bar/file
+  $ printf "baz" > baz_file
+  $ hg add -q
+
+  $ cd bar
+  $ hg fix --working-dir --config "fix.cooltool:command=echo fixed" \
+  >  --config "fix.cooltool:pattern=rootglob:**"
+  $ cd ..
+
+  $ cat foo/file
+  fixed
+  $ cat bar/file
+  fixed
+  $ cat baz_file
+  fixed
+
+  $ cd ..



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6691: fix: remove support for :fileset sub-config in favor of :pattern

2019-07-26 Thread hooper (Danny Hooper)
Closed by commit rHG9ed63cd0026c: fix: remove support for :fileset sub-config 
in favor of :pattern (authored by hooper).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6691?vs=16060=16079

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6691/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6691

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1161,28 +1161,6 @@
 
   $ cd ..
 
-The :fileset subconfig was a misnomer, so we renamed it to :pattern. We will
-still accept :fileset by itself as if it were :pattern, but this will issue a
-warning.
-
-  $ hg init filesetispattern
-  $ cd filesetispattern
-
-  $ printf "foo\n" > foo.whole
-  $ printf "first\nsecond\n" > bar.txt
-  $ hg add -q
-  $ hg fix -w --config fix.sometool:fileset=bar.txt \
-  >   --config fix.sometool:command="sort -r"
-  the fix.tool:fileset config name is deprecated; please rename it to 
fix.tool:pattern
-
-  $ cat foo.whole
-  FOO
-  $ cat bar.txt
-  second
-  first
-
-  $ cd ..
-
 The execution order of tools can be controlled. This example doesn't work if
 you sort after truncating, but the config defines the correct order while the
 definitions are out of order (which might imply the incorrect order given the
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -152,7 +152,6 @@
 FIXER_ATTRS = {
 'command': None,
 'linerange': None,
-'fileset': None,
 'pattern': None,
 'priority': 0,
 'metadata': False,
@@ -702,10 +701,6 @@
 for name in fixernames(ui):
 fixers[name] = Fixer()
 attrs = ui.configsuboptions('fix', name)[1]
-if 'fileset' in attrs and 'pattern' not in attrs:
-ui.warn(_('the fix.tool:fileset config name is deprecated; '
-  'please rename it to fix.tool:pattern\n'))
-attrs['pattern'] = attrs['fileset']
 for key, default in FIXER_ATTRS.items():
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6693: fix: ignore fixer tool configurations that are missing patterns

2019-07-25 Thread hooper (Danny Hooper)
hooper added inline comments.

INLINE COMMENTS

> martinvonz wrote in fix.py:738-739
> Is this change needed given the change above?

It makes this function more robust. It might be called by someone who actually 
tries to use a Fixer with no pattern.

> martinvonz wrote in test-fix.t:1280
> nit: The `--debug` seems unnecessary, unless we want to make sure that we 
> *don't* get any output.

Yes, it will show a "subprocess: " line if we go ahead and use the fixer. 
The file also exists to make it possible to observe that kind of regression.

Keep in mind the fix command has no output until you set up hooks or something.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST ACTION
  https://phab.mercurial-scm.org/D6693/new/

REVISION DETAIL
  https://phab.mercurial-scm.org/D6693

To: hooper, #hg-reviewers
Cc: martinvonz, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6693: fix: ignore fixer tool configurations that are missing patterns

2019-07-24 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This is to prevent a crash under the same circumstances.
  
  This is also to avoid data loss due to accidental application of a fixer tool
  to all files, if the matching logic somehow changed to that effect. Affecting
  all files until otherwise configured would be dangerous, and not very useful.
  
  We shouldn't abort because there may be other fixers, and it may still be
  useful to run them without having to adjust configuration. A user might not
  feel confident in changing configs, for example.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6693

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1264,3 +1264,23 @@
 
   $ cd ..
 
+Tools configured without a pattern are ignored. It would be too dangerous to
+run them on all files, because this might happen while testing a configuration
+that also deletes all of the file content. There is no reasonable subset of the
+files to use as a default. Users should be explicit about what files are
+affected by a tool. This test also confirms that we don't crash when the
+pattern config is missing, and that we only warn about it once.
+
+  $ hg init nopatternconfigured
+  $ cd nopatternconfigured
+
+  $ printf "foo" > foo
+  $ printf "bar" > bar
+  $ hg add -q
+  $ hg fix --debug --working-dir --config "fix.nopattern:command=echo fixed"
+  fixer tool has no pattern configuration: nopattern
+  $ cat foo bar
+  foobar (no-eol)
+
+  $ cd ..
+
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -710,6 +710,14 @@
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))
 fixers[name]._priority = int(fixers[name]._priority)
+# Don't use a fixer if it has no pattern configured. It would be
+# dangerous to let it affect all files. It would be pointless to let it
+# affect no files. There is no reasonable subset of files to use as the
+# default.
+if fixers[name]._pattern is None:
+ui.warn(
+_('fixer tool has no pattern configuration: %s\n') % (name,))
+del fixers[name]
 return collections.OrderedDict(
 sorted(fixers.items(), key=lambda item: item[1]._priority,
reverse=True))
@@ -727,7 +735,8 @@
 
 def affects(self, opts, fixctx, path):
 """Should this fixer run on the file at the given path and context?"""
-return scmutil.match(fixctx, [self._pattern], opts)(path)
+return (self._pattern is not None and
+scmutil.match(fixctx, [self._pattern], opts)(path))
 
 def shouldoutputmetadata(self):
 """Should the stdout of this fixer start with JSON and a null byte?"""



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6692: fix: add a test case around the effect of cwd on pattern matching

2019-07-24 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This was not covered by previous tests. It is related to a regression
  encountered at Google due to misconfiguration of [fix].

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6692

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1284,3 +1284,28 @@
 
   $ cd ..
 
+Test that we can configure a fixer to affect all files regardless of the cwd.
+The way we invoke matching must not prohibit this.
+
+  $ hg init affectallfiles
+  $ cd affectallfiles
+
+  $ mkdir foo bar
+  $ printf "foo" > foo/file
+  $ printf "bar" > bar/file
+  $ printf "baz" > baz_file
+  $ hg add -q
+
+  $ cd bar
+  $ hg fix --working-dir --config "fix.cooltool:command=echo fixed" \
+  >  --config "fix.cooltool:pattern=rootglob:**"
+  $ cd ..
+
+  $ cat foo/file
+  fixed
+  $ cat bar/file
+  fixed
+  $ cat baz_file
+  fixed
+
+  $ cd ..



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6691: fix: remove support for :fileset sub-config in favor of :pattern

2019-07-24 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6691

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1161,28 +1161,6 @@
 
   $ cd ..
 
-The :fileset subconfig was a misnomer, so we renamed it to :pattern. We will
-still accept :fileset by itself as if it were :pattern, but this will issue a
-warning.
-
-  $ hg init filesetispattern
-  $ cd filesetispattern
-
-  $ printf "foo\n" > foo.whole
-  $ printf "first\nsecond\n" > bar.txt
-  $ hg add -q
-  $ hg fix -w --config fix.sometool:fileset=bar.txt \
-  >   --config fix.sometool:command="sort -r"
-  the fix.tool:fileset config name is deprecated; please rename it to 
fix.tool:pattern
-
-  $ cat foo.whole
-  FOO
-  $ cat bar.txt
-  second
-  first
-
-  $ cd ..
-
 The execution order of tools can be controlled. This example doesn't work if
 you sort after truncating, but the config defines the correct order while the
 definitions are out of order (which might imply the incorrect order given the
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -152,7 +152,6 @@
 FIXER_ATTRS = {
 'command': None,
 'linerange': None,
-'fileset': None,
 'pattern': None,
 'priority': 0,
 'metadata': False,
@@ -702,10 +701,6 @@
 for name in fixernames(ui):
 fixers[name] = Fixer()
 attrs = ui.configsuboptions('fix', name)[1]
-if 'fileset' in attrs and 'pattern' not in attrs:
-ui.warn(_('the fix.tool:fileset config name is deprecated; '
-  'please rename it to fix.tool:pattern\n'))
-attrs['pattern'] = attrs['fileset']
 for key, default in FIXER_ATTRS.items():
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6440: fix: let fixer tools inherit hg's cwd so they can look at the working copy

2019-05-23 Thread hooper (Danny Hooper)
hooper added inline comments.

INLINE COMMENTS

> durin42 wrote in fix.py:106
> I wonder if it'd be more generally useful to run the fixer in the repo root 
> than the same `pwd` as the command invocation. WDYT?

It depends on whether we want to make it easier for tools that want to examine 
the tree upward from the cwd or tools that want to examine the tree downward 
from the root. I suspect that "upward" will be more important because of the 
way some tools use config files that apply to subtrees. For some tools it's 
weird because reading code to format from stdin is often an afterthought. 
Either way, for completeness, the root and cwd would both need to be available 
in either subprocess cwd or the command template. There may also be some room 
to prefer configs like "cd {root} && mycommand".

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6440

To: hooper, #hg-reviewers
Cc: durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6439: test: add missing 'cd ..' to test case

2019-05-23 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGb02f3aa2fab5: test: add missing cd .. to test 
case (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6439?vs=15243=15245

REVISION DETAIL
  https://phab.mercurial-scm.org/D6439

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -834,6 +834,8 @@
   (use 'hg rebase --continue' or 'hg rebase --abort')
   [255]
 
+  $ cd ..
+
 When fixing a file that was renamed, we should diff against the source of the
 rename for incremental fixing and we should correctly reproduce the rename in
 the replacement revision.



To: hooper, #hg-reviewers, pulkit
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6440: fix: let fixer tools inherit hg's cwd so they can look at the working copy

2019-05-22 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This lets fixer tools do things like find configuration files, with the caveat
  that they'll only see the version of that file in the working copy, regardless
  of what revisions are being fixed.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6440

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1264,3 +1264,37 @@
 
   $ cd ..
 
+We run fixer tools in the cwd so they can look for config files or other
+important things in the working directory. This does NOT mean we are
+reconstructing a working copy of every revision being fixed; we're just giving
+the tool knowledge of the cwd in case it can do something reasonable with that.
+
+  $ hg init subprocesscwd
+  $ cd subprocesscwd
+
+  $ cat >> .hg/hgrc < [fix]
+  > printcwd:command = pwd
+  > printcwd:pattern = path:foo/bar
+  > EOF
+
+  $ mkdir foo
+  $ printf "bar\n" > foo/bar
+  $ hg commit -Aqm blah
+
+  $ hg fix -w -r . foo/bar
+  $ hg cat -r tip foo/bar
+  $TESTTMP/subprocesscwd
+  $ cat foo/bar
+  $TESTTMP/subprocesscwd
+
+  $ cd foo
+
+  $ hg fix -w -r . bar
+  $ hg cat -r tip bar
+  $TESTTMP/subprocesscwd/foo
+  $ cat bar
+  $TESTTMP/subprocesscwd/foo
+
+  $ cd ../..
+
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -102,6 +102,13 @@
 mapping fixer tool names to lists of metadata values returned from
 executions that modified a file. This aggregates the same metadata
 previously passed to the "postfixfile" hook.
+
+Fixer tools are run the in same working directory as the :hg:`fix` command. 
This
+allows them to read configuration files from the working copy, or even write to
+the working copy. The working copy is not updated to match the revision being
+fixed. In fact, several revisions may be fixed in parallel. Writes to the
+working copy are not amended into the revision being fixed; fixer tools should
+always write fixed file content back to stdout as documented above.
 """
 
 from __future__ import absolute_import
@@ -233,7 +240,7 @@
 for rev, path in items:
 ctx = repo[rev]
 olddata = ctx[path].data()
-metadata, newdata = fixfile(ui, opts, fixers, ctx, path,
+metadata, newdata = fixfile(ui, repo, opts, fixers, ctx, path,
 basectxs[rev])
 # Don't waste memory/time passing unchanged content back, but
 # produce one result per item either way.
@@ -530,16 +537,17 @@
 basectxs[rev].add(pctx)
 return basectxs
 
-def fixfile(ui, opts, fixers, fixctx, path, basectxs):
+def fixfile(ui, repo, opts, fixers, fixctx, path, basectxs):
 """Run any configured fixers that should affect the file in this context
 
 Returns the file content that results from applying the fixers in some 
order
 starting with the file's content in the fixctx. Fixers that support line
 ranges will affect lines that have changed relative to any of the basectxs
 (i.e. they will only avoid lines that are common to all basectxs).
 
 A fixer tool's stdout will become the file's new content if and only if it
-exits with code zero.
+exits with code zero. The fixer tool's working directory is inherited from
+this process.
 """
 metadata = {}
 newdata = fixctx[path].data()
@@ -553,7 +561,7 @@
 proc = subprocess.Popen(
 procutil.tonativestr(command),
 shell=True,
-cwd=procutil.tonativestr(b'/'),
+cwd=None,
 stdin=subprocess.PIPE,
 stdout=subprocess.PIPE,
 stderr=subprocess.PIPE)



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6439: test: add missing 'cd ..' to test case

2019-05-22 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6439

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -834,6 +834,8 @@
   (use 'hg rebase --continue' or 'hg rebase --abort')
   [255]
 
+  $ cd ..
+
 When fixing a file that was renamed, we should diff against the source of the
 rename for incremental fixing and we should correctly reproduce the rename in
 the replacement revision.



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6414: narrow: consider empty commits to be "inside the narrow spec" for templates

2019-05-22 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG45c18f7345c1: narrow: consider empty commits to be 
inside the narrow spec for templates (authored by hooper, committed 
by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6414?vs=15206=15221

REVISION DETAIL
  https://phab.mercurial-scm.org/D6414

AFFECTED FILES
  hgext/narrow/narrowtemplates.py
  tests/test-narrow.t

CHANGE DETAILS

diff --git a/tests/test-narrow.t b/tests/test-narrow.t
--- a/tests/test-narrow.t
+++ b/tests/test-narrow.t
@@ -281,6 +281,10 @@
   marked working directory as branch foo
   (branches are permanent and global, did you want a bookmark?)
   $ hg ci -m empty
+  $ hg log -T "{rev}: {desc} {outsidenarrow}\n"
+  2: empty 
+  1: add d5/f outsidenarrow
+  0: add d0/f outsidenarrow
   $ hg pull -q
 Can widen the empty clone
   $ hg tracked --addinclude d0
diff --git a/hgext/narrow/narrowtemplates.py b/hgext/narrow/narrowtemplates.py
--- a/hgext/narrow/narrowtemplates.py
+++ b/hgext/narrow/narrowtemplates.py
@@ -37,7 +37,7 @@
 repo = context.resource(mapping, 'repo')
 ctx = context.resource(mapping, 'ctx')
 m = repo.narrowmatch()
-if not m.always():
+if ctx.files() and not m.always():
 if not any(m(f) for f in ctx.files()):
 return 'outsidenarrow'
 return ''



To: hooper, durin42, martinvonz, #hg-reviewers, pulkit
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6414: narrow: consider empty commits to be "inside the narrow spec" for templates

2019-05-20 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: martinvonz.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  It doesn't seem useful to exclude them, or harmful to include them. Users
  writing log templates using outsidenarrow as a predicate might consider it
  unexpected if their locally created empty drafts are treated as if they
  contained something outside the clone.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6414

AFFECTED FILES
  hgext/narrow/narrowtemplates.py
  tests/test-narrow.t

CHANGE DETAILS

diff --git a/tests/test-narrow.t b/tests/test-narrow.t
--- a/tests/test-narrow.t
+++ b/tests/test-narrow.t
@@ -281,6 +281,10 @@
   marked working directory as branch foo
   (branches are permanent and global, did you want a bookmark?)
   $ hg ci -m empty
+  $ hg log -T "{rev}: {desc} {outsidenarrow}\n"
+  2: empty 
+  1: add d5/f outsidenarrow
+  0: add d0/f outsidenarrow
   $ hg pull -q
 Can widen the empty clone
   $ hg tracked --addinclude d0
diff --git a/hgext/narrow/narrowtemplates.py b/hgext/narrow/narrowtemplates.py
--- a/hgext/narrow/narrowtemplates.py
+++ b/hgext/narrow/narrowtemplates.py
@@ -37,7 +37,7 @@
 repo = context.resource(mapping, 'repo')
 ctx = context.resource(mapping, 'ctx')
 m = repo.narrowmatch()
-if not m.always():
+if ctx.files() and not m.always():
 if not any(m(f) for f in ctx.files()):
 return 'outsidenarrow'
 return ''



To: hooper, durin42, martinvonz, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6313: remotefilelog: add missing argument to hg.verify wrapper

2019-04-27 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGbed4c308fc56: remotefilelog: add missing argument to 
hg.verify wrapper (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6313?vs=14928=14929

REVISION DETAIL
  https://phab.mercurial-scm.org/D6313

AFFECTED FILES
  hgext/remotefilelog/__init__.py

CHANGE DETAILS

diff --git a/hgext/remotefilelog/__init__.py b/hgext/remotefilelog/__init__.py
--- a/hgext/remotefilelog/__init__.py
+++ b/hgext/remotefilelog/__init__.py
@@ -653,7 +653,7 @@
 
 # Prevent verify from processing files
 # a stub for mercurial.hg.verify()
-def _verify(orig, repo):
+def _verify(orig, repo, level=None):
 lock = repo.lock()
 try:
 return shallowverifier.shallowverifier(repo).verify()



To: hooper, #hg-reviewers, pulkit
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6313: remotefilelog: add missing argument to hg.verify wrapper

2019-04-26 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6313

AFFECTED FILES
  hgext/remotefilelog/__init__.py

CHANGE DETAILS

diff --git a/hgext/remotefilelog/__init__.py b/hgext/remotefilelog/__init__.py
--- a/hgext/remotefilelog/__init__.py
+++ b/hgext/remotefilelog/__init__.py
@@ -653,7 +653,7 @@
 
 # Prevent verify from processing files
 # a stub for mercurial.hg.verify()
-def _verify(orig, repo):
+def _verify(orig, repo, level=None):
 lock = repo.lock()
 try:
 return shallowverifier.shallowverifier(repo).verify()



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6167: fix: allow fixer tools to return metadata in addition to the file content

2019-04-23 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG0da689a60163: fix: allow fixer tools to return metadata in 
addition to the file content (authored by hooper, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D6167?vs=14901=14902#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6167?vs=14901=14902

REVISION DETAIL
  https://phab.mercurial-scm.org/D6167

AFFECTED FILES
  hgext/fix.py
  tests/test-fix-metadata.t
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -185,6 +185,36 @@
   tool may see different values for the arguments added by the :linerange
   suboption.
   
+  Each fixer tool is allowed to return some metadata in addition to the fixed
+  file content. The metadata must be placed before the file content on stdout,
+  separated from the file content by a zero byte. The metadata is parsed as a
+  JSON value (so, it should be UTF-8 encoded and contain no zero bytes). A 
fixer
+  tool is expected to produce this metadata encoding if and only if the
+  :metadata suboption is true:
+  
+[fix]
+tool:command = tool --prepend-json-metadata
+tool:metadata = true
+  
+  The metadata values are passed to hooks, which can be used to print summaries
+  or perform other post-fixing work. The supported hooks are:
+  
+"postfixfile"
+  Run once for each file in each revision where any fixer tools made 
changes
+  to the file content. Provides "$HG_REV" and "$HG_PATH" to identify the 
file,
+  and "$HG_METADATA" with a map of fixer names to metadata values from 
fixer
+  tools that affected the file. Fixer tools that didn't affect the file 
have a
+  valueof None. Only fixer tools that executed are present in the metadata.
+  
+"postfix"
+  Run once after all files and revisions have been handled. Provides
+  "$HG_REPLACEMENTS" with information about what revisions were created and
+  made obsolete. Provides a boolean "$HG_WDIRWRITTEN" to indicate whether 
any
+  files in the working copy were updated. Provides a list "$HG_METADATA"
+  mapping fixer tool names to lists of metadata values returned from
+  executions that modified a file. This aggregates the same metadata
+  previously passed to the "postfixfile" hook.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
diff --git a/tests/test-fix-metadata.t b/tests/test-fix-metadata.t
new file mode 100644
--- /dev/null
+++ b/tests/test-fix-metadata.t
@@ -0,0 +1,86 @@
+A python hook for "hg fix" that prints out the number of files and revisions
+that were affected, along with which fixer tools were applied. Also checks how
+many times it sees a specific key generated by one of the fixer tools defined
+below.
+
+  $ cat >> $TESTTMP/postfixhook.py < import collections
+  > def file(ui, repo, rev=None, path='', metadata=None, **kwargs):
+  >   ui.status('fixed %s in revision %d using %s\n' %
+  > (path, rev, ', '.join(metadata.keys(
+  > def summarize(ui, repo, replacements=None, wdirwritten=False,
+  >   metadata=None, **kwargs):
+  > counts = collections.defaultdict(int)
+  > keys = 0
+  > for fixername, metadatalist in metadata.items():
+  > for metadata in metadatalist:
+  > if metadata is None:
+  > continue
+  > counts[fixername] += 1
+  > if 'key' in metadata:
+  > keys += 1
+  > ui.status('saw "key" %d times\n' % (keys,))
+  > for name, count in sorted(counts.items()):
+  > ui.status('fixed %d files with %s\n' % (count, name))
+  > if replacements:
+  > ui.status('fixed %d revisions\n' % (len(replacements),))
+  > if wdirwritten:
+  > ui.status('fixed the working copy\n')
+  > EOF
+
+Some mock output for fixer tools that demonstrate what could go wrong with
+expecting the metadata output format.
+
+  $ printf 'new content\n' > $TESTTMP/missing
+  $ printf 'not valid json\0new content\n' > $TESTTMP/invalid
+  $ printf '{"key": "value"}\0new content\n' > $TESTTMP/valid
+
+Configure some fixer tools based on the output defined above, and enable the
+hooks defined above. Disable parallelism to make output of the parallel file
+processing phase stable.
+
+  $ cat >> $HGRCPATH < [extensions]
+  > fix =
+  > [fix]
+  > missing:command=cat $TESTTMP/missing
+  > missing:pattern=missing
+  > missing:metadata=true
+  > invalid:command=cat $TESTTMP/invalid
+  > invalid:pattern=invalid
+  > invalid:metadata=true
+  > valid:command=cat $TESTTMP/valid
+  > valid:pattern=valid
+  > valid:metadata=true
+  > [hooks]
+  > postfixfile = python:$TESTTMP/postfixhook.py:file
+  > postfix = python:$TESTTMP/postfixhook.py:summarize
+  > [worker]
+  > enabled=false
+  > EOF
+
+See what happens when we execute each of the 

D6167: fix: allow fixer tools to return metadata in addition to the file content

2019-04-23 Thread hooper (Danny Hooper)
hooper added inline comments.

INLINE COMMENTS

> martinvonz wrote in fix.py:559-570
> Would the thing that processes this metadata usually not care to aggregate 
> per fixer? If they did, it seems they would now have to look for a 
> `fixer-applied='my-fixer'` entry and then take the metadata from the 
> preceding entry. Did you consider instead making this function return an 
> entry like `{fixername: metadatajson}` (and leave `metadatajson` as None if 
> `not fixer.shouldoutputmetadata()`)?

I think we had some other possibilities in mind, but after trying it, I think 
your idea is cleaner for expected use cases. I don't think it makes anything 
harder, but it makes some things easier. The diff is pretty small.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6167

To: hooper, #hg-reviewers, durin42
Cc: martinvonz, lothiraldan, durin42, indygreg, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6167: fix: allow fixer tools to return metadata in addition to the file content

2019-04-23 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 14901.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6167?vs=14581=14901

REVISION DETAIL
  https://phab.mercurial-scm.org/D6167

AFFECTED FILES
  hgext/fix.py
  tests/test-fix-metadata.t
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -185,6 +185,36 @@
   tool may see different values for the arguments added by the :linerange
   suboption.
   
+  Each fixer tool is allowed to return some metadata in addition to the fixed
+  file content. The metadata must be placed before the file content on stdout,
+  separated from the file content by a zero byte. The metadata is parsed as a
+  JSON value (so, it should be UTF-8 encoded and contain no zero bytes). A 
fixer
+  tool is expected to produce this metadata encoding if and only if the
+  :metadata suboption is true:
+  
+[fix]
+tool:command = tool --prepend-json-metadata
+tool:metadata = true
+  
+  The metadata values are passed to hooks, which can be used to print summaries
+  or perform other post-fixing work. The supported hooks are:
+  
+  "postfixfile"
+Run once for each file in each revision where any fixer tools made changes
+to the file content. Provides "$HG_REV" and "$HG_PATH" to identify the 
file,
+and "$HG_METADATA" with a map of fixer names to metadata values from fixer
+tools that affected the file. Fixer tools that didn't affect the file have 
a
+value of None. Only fixer tools that executed are present in the metadata.
+  
+  "postfix"
+Run once after all files and revisions have been handled. Provides
+"$HG_REPLACEMENTS" with information about what revisions were created and
+made obsolete. Provides a boolean "$HG_WDIRWRITTEN" to indicate whether any
+files in the working copy were updated. Provides a list "$HG_METADATA"
+mapping fixer tool names to lists of metadata values returned from
+executions that modified a file. This aggregates the same metadata
+previously passed to the "postfixfile" hook.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
diff --git a/tests/test-fix-metadata.t b/tests/test-fix-metadata.t
new file mode 100644
--- /dev/null
+++ b/tests/test-fix-metadata.t
@@ -0,0 +1,86 @@
+A python hook for "hg fix" that prints out the number of files and revisions
+that were affected, along with which fixer tools were applied. Also checks how
+many times it sees a specific key generated by one of the fixer tools defined
+below.
+
+  $ cat >> $TESTTMP/postfixhook.py < import collections
+  > def file(ui, repo, rev=None, path='', metadata=None, **kwargs):
+  >   ui.status('fixed %s in revision %d using %s\n' %
+  > (path, rev, ', '.join(metadata.keys(
+  > def summarize(ui, repo, replacements=None, wdirwritten=False,
+  >   metadata=None, **kwargs):
+  > counts = collections.defaultdict(int)
+  > keys = 0
+  > for fixername, metadatalist in metadata.items():
+  > for metadata in metadatalist:
+  > if metadata is None:
+  > continue
+  > counts[fixername] += 1
+  > if 'key' in metadata:
+  > keys += 1
+  > ui.status('saw "key" %d times\n' % (keys,))
+  > for name, count in sorted(counts.items()):
+  > ui.status('fixed %d files with %s\n' % (count, name))
+  > if replacements:
+  > ui.status('fixed %d revisions\n' % (len(replacements),))
+  > if wdirwritten:
+  > ui.status('fixed the working copy\n')
+  > EOF
+
+Some mock output for fixer tools that demonstrate what could go wrong with
+expecting the metadata output format.
+
+  $ printf 'new content\n' > $TESTTMP/missing
+  $ printf 'not valid json\0new content\n' > $TESTTMP/invalid
+  $ printf '{"key": "value"}\0new content\n' > $TESTTMP/valid
+
+Configure some fixer tools based on the output defined above, and enable the
+hooks defined above. Disable parallelism to make output of the parallel file
+processing phase stable.
+
+  $ cat >> $HGRCPATH < [extensions]
+  > fix =
+  > [fix]
+  > missing:command=cat $TESTTMP/missing
+  > missing:pattern=missing
+  > missing:metadata=true
+  > invalid:command=cat $TESTTMP/invalid
+  > invalid:pattern=invalid
+  > invalid:metadata=true
+  > valid:command=cat $TESTTMP/valid
+  > valid:pattern=valid
+  > valid:metadata=true
+  > [hooks]
+  > postfixfile = python:$TESTTMP/postfixhook.py:file
+  > postfix = python:$TESTTMP/postfixhook.py:summarize
+  > [worker]
+  > enabled=false
+  > EOF
+
+See what happens when we execute each of the fixer tools. Some print warnings,
+some write back to the file.
+
+  $ hg init repo
+  $ cd repo
+
+  $ printf "old content\n" > invalid
+  $ printf "old content\n" > missing
+  $ printf "old content\n" > valid
+  $ hg add -q
+
+  $ hg fix -w
+  ignored invalid output from fixer tool: 

D6165: fix: allow fixing untracked files when given as arguments

2019-03-23 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG7f6b375a8903: fix: allow fixing untracked files when given 
as arguments (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6165?vs=14579=14590

REVISION DETAIL
  https://phab.mercurial-scm.org/D6165

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -354,6 +354,10 @@
 
   $ printf "modified!!!\n" > modified.whole
   $ printf "added\n" > added.whole
+
+Listing the files explicitly causes untracked files to also be fixed, but
+ignored files are still unaffected.
+
   $ hg fix --working-dir *.whole
 
   $ hg status --all
@@ -366,13 +370,12 @@
   I ignored.whole
   C .hgignore
 
-It would be better if this also fixed the unknown file.
   $ cat *.whole
   ADDED
   CLEAN
   ignored
   MODIFIED!!!
-  unknown
+  UNKNOWN
 
   $ cd ..
 
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -282,8 +282,6 @@
 match = scmutil.match(fixctx, pats, opts)
 for path in pathstofix(ui, repo, pats, opts, match, basectxs[rev],
fixctx):
-if path not in fixctx:
-continue
 fctx = fixctx[path]
 if fctx.islink():
 continue



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6166: fix: make the order of the work queue deterministic

2019-03-23 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG8f427f7c1f71: fix: make the order of the work queue 
deterministic (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6166?vs=14580=14591

REVISION DETAIL
  https://phab.mercurial-scm.org/D6166

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -280,8 +280,8 @@
 for rev in sorted(revstofix):
 fixctx = repo[rev]
 match = scmutil.match(fixctx, pats, opts)
-for path in pathstofix(ui, repo, pats, opts, match, basectxs[rev],
-   fixctx):
+for path in sorted(pathstofix(
+ui, repo, pats, opts, match, basectxs[rev], fixctx)):
 fctx = fixctx[path]
 if fctx.islink():
 continue



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5516: fix: add some arguments to facilitate extensions

2019-03-21 Thread hooper (Danny Hooper)
hooper abandoned this revision.
hooper added a comment.


  See https://phab.mercurial-scm.org/D6167 for a newer approach.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5516

To: hooper, #hg-reviewers
Cc: durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6167: fix: allow fixer tools to return metadata in addition to the file content

2019-03-21 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  With this change, fixer tools can be configured to output a JSON object that
  will be parsed and passed to hooks that can be used to print summaries of what
  code was formatted or perform other post-fixing work.
  
  The motivation for this change is to allow parallel executions of a
  "meta-formatter" tool to report back statistics, which are then aggregated and
  processed after all formatting has completed. Providing an extensible 
mechanism
  inside fix.py is far simpler, and more portable, than trying to make a tool
  like this communicate through some other channel.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6167

AFFECTED FILES
  hgext/fix.py
  tests/test-fix-metadata.t
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -185,6 +185,34 @@
   tool may see different values for the arguments added by the :linerange
   suboption.
   
+  Each fixer tool is allowed to return some metadata in addition to the fixed
+  file content. The metadata must be placed before the file content on stdout,
+  separated from the file content by a zero byte. The metadata is parsed as a
+  JSON value (so, it should be UTF-8 encoded and contain no zero bytes). A 
fixer
+  tool is expected to produce this metadata encoding if and only if the
+  :metadata suboption is true:
+  
+[fix]
+tool:command = tool --prepend-json-metadata
+tool:metadata = true
+  
+  The metadata values are passed to hooks, which can be used to print summaries
+  or perform other post-fixing work. The supported hooks are:
+  
+  "postfixfile"
+Run once for each file in each revision where any fixer tools made changes
+to the file content. Provides "$HG_REV" and "$HG_PATH" to identify the 
file,
+and "$HG_METADATA" with a list of metadata values from fixer tools that
+affected the file.
+  
+  "postfix"
+Run once after all files and revisions have been handled. Provides
+"$HG_REPLACEMENTS" with information about what revisions were created and
+made obsolete. Provides a boolean "$HG_WDIRWRITTEN" to indicate whether any
+files in the working copy were updated. Provides a list "$HG_ALLMETADATA"
+containing all metadata values returned from fixer tool executions that
+modified a file.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
diff --git a/tests/test-fix-metadata.t b/tests/test-fix-metadata.t
new file mode 100644
--- /dev/null
+++ b/tests/test-fix-metadata.t
@@ -0,0 +1,83 @@
+A python hook for "hg fix" that prints out the number of files and revisions
+that were affected, along with which fixer tools were applied. Also checks how
+many times it sees a specific key generated by one of the fixer tools defined
+below.
+
+  $ cat >> $TESTTMP/postfixhook.py < import collections
+  > def file(ui, repo, rev=None, path='', metadata=None, **kwargs):
+  >   ui.status('fixed %s in revision %d\n' % (path, rev))
+  > def summarize(ui, repo, replacements=None, wdirwritten=False,
+  >   allmetadata=None, **kwargs):
+  > counts = collections.defaultdict(int)
+  > keys = 0
+  > for metadata in allmetadata:
+  > if 'fixer-applied' in metadata:
+  > counts[metadata['fixer-applied']] += 1
+  > if 'key' in metadata:
+  > keys += 1
+  > ui.status('saw "key" %d times\n' % (keys,))
+  > for name, count in sorted(counts.items()):
+  > ui.status('fixed %d files with %s\n' % (count, name))
+  > if replacements:
+  > ui.status('fixed %d revisions\n' % (len(replacements),))
+  > if wdirwritten:
+  > ui.status('fixed the working copy\n')
+  > EOF
+
+Some mock output for fixer tools that demonstrate what could go wrong with
+expecting the metadata output format.
+
+  $ printf 'new content\n' > $TESTTMP/missing
+  $ printf 'not valid json\0new content\n' > $TESTTMP/invalid
+  $ printf '{"key": "value"}\0new content\n' > $TESTTMP/valid
+
+Configure some fixer tools based on the output defined above, and enable the
+hooks defined above. Disable parallelism to make output of the parallel file
+processing phase stable.
+
+  $ cat >> $HGRCPATH < [extensions]
+  > fix =
+  > [fix]
+  > missing:command=cat $TESTTMP/missing
+  > missing:pattern=missing
+  > missing:metadata=true
+  > invalid:command=cat $TESTTMP/invalid
+  > invalid:pattern=invalid
+  > invalid:metadata=true
+  > valid:command=cat $TESTTMP/valid
+  > valid:pattern=valid
+  > valid:metadata=true
+  > [hooks]
+  > postfixfile = python:$TESTTMP/postfixhook.py:file
+  > postfix = python:$TESTTMP/postfixhook.py:summarize
+  > [worker]
+  > enabled=false
+  > EOF
+
+See what happens when we execute each of the fixer tools. Some print warnings,
+some write back to the file.

D6165: fix: allow fixing untracked files when given as arguments

2019-03-21 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  It's more useful to fix the file than to silently avoid it when the user does
  this:
  
hg fix --working-dir untracked-file
  
  We will still do nothing to ignored files, even if they are specified. This 
may
  be safer, given that such files can unexpectedly slip into the arguments via a
  shell glob or fileset.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6165

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -354,6 +354,10 @@
 
   $ printf "modified!!!\n" > modified.whole
   $ printf "added\n" > added.whole
+
+Listing the files explicitly causes untracked files to also be fixed, but
+ignored files are still unaffected.
+
   $ hg fix --working-dir *.whole
 
   $ hg status --all
@@ -366,13 +370,12 @@
   I ignored.whole
   C .hgignore
 
-It would be better if this also fixed the unknown file.
   $ cat *.whole
   ADDED
   CLEAN
   ignored
   MODIFIED!!!
-  unknown
+  UNKNOWN
 
   $ cd ..
 
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -282,8 +282,6 @@
 match = scmutil.match(fixctx, pats, opts)
 for path in pathstofix(ui, repo, pats, opts, match, basectxs[rev],
fixctx):
-if path not in fixctx:
-continue
 fctx = fixctx[path]
 if fctx.islink():
 continue



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D6166: fix: make the order of the work queue deterministic

2019-03-21 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This makes any output generated during the parallel phase of execution stable
  if parallelism is disabled. This helps write tests like that in the future.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D6166

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -280,8 +280,8 @@
 for rev in sorted(revstofix):
 fixctx = repo[rev]
 match = scmutil.match(fixctx, pats, opts)
-for path in pathstofix(ui, repo, pats, opts, match, basectxs[rev],
-   fixctx):
+for path in sorted(pathstofix(
+ui, repo, pats, opts, match, basectxs[rev], fixctx)):
 fctx = fixctx[path]
 if fctx.islink():
 continue



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5516: fix: add some arguments to facilitate extensions

2019-01-09 Thread hooper (Danny Hooper)
hooper added a comment.


  In https://phab.mercurial-scm.org/D5516#81841, @durin42 wrote:
  
  > In https://phab.mercurial-scm.org/D5516#81683, @hooper wrote:
  >
  > > In https://phab.mercurial-scm.org/D5516#81679, @durin42 wrote:
  > >
  > > > I'm -0 on this: what's special about this functionality that it needs 
to be an extension of an extension instead of something that can be done in 
core?
  > >
  > >
  > > Google's internal use of this extension makes some customizations that I 
doubt would be appealing in core. This patch makes some of it simpler to 
implement. Making all of it possible through configs/templates might be unduly 
complex.
  >
  >
  > What kinds of customizations?
  
  
  One is to aggregate metadata output from multiple fixer tool executions to 
display a summary at the end (so wrapping cleanup() is sensible). Not sure who 
else would use that, or if there's a good way to make a generic interface for 
it.
  
  Another is basically to add a "--nodeid_for_this_file=deadbeef" to a fixer 
tool command line. That's where it would be sufficient to have the ctx 
available. It might be nice to put the ctx into the templater, but that raises 
some questions about implementation that I wanted to punt for now.
  
  >> A better version of this might put "ctx" into the templater inside 
Fixer.command, and maybe add a no-op Fixer.cleanup method to make that part 
more explicit. I think that would be a less trivial super set of this patch.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5516

To: hooper, #hg-reviewers
Cc: durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5517: tests: use more portable flags in test-fix.t

2019-01-07 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGd8f5c615e811: tests: use more portable flags in test-fix.t 
(authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5517?vs=13064=13072

REVISION DETAIL
  https://phab.mercurial-scm.org/D5517

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -173,8 +173,8 @@
   in a text file by ensuring that 'sort' runs before 'head':
   
 [fix]
-sort:command = sort --numeric-sort
-head:command = head --lines=10
+sort:command = sort -n
+head:command = head -n 10
 sort:pattern = numbers.txt
 head:pattern = numbers.txt
 sort:priority = 2
@@ -1159,10 +1159,10 @@
 
   $ cat >> .hg/hgrc < [fix]
-  > head:command = head --lines=5
+  > head:command = head -n 5
   > head:pattern = numbers.txt
   > head:priority = 1
-  > sort:command = sort --numeric-sort
+  > sort:command = sort -n
   > sort:pattern = numbers.txt
   > sort:priority = 2
   > EOF
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -62,8 +62,8 @@
 in a text file by ensuring that 'sort' runs before 'head'::
 
   [fix]
-  sort:command = sort --numeric-sort
-  head:command = head --lines=10
+  sort:command = sort -n
+  head:command = head -n 10
   sort:pattern = numbers.txt
   head:pattern = numbers.txt
   sort:priority = 2



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5517: tests: use more portable flags in test-fix.t

2019-01-07 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  `head --lines N` is known to not exist on OSX.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5517

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -173,8 +173,8 @@
   in a text file by ensuring that 'sort' runs before 'head':
   
 [fix]
-sort:command = sort --numeric-sort
-head:command = head --lines=10
+sort:command = sort -n
+head:command = head -n 10
 sort:pattern = numbers.txt
 head:pattern = numbers.txt
 sort:priority = 2
@@ -1159,10 +1159,10 @@
 
   $ cat >> .hg/hgrc < [fix]
-  > head:command = head --lines=5
+  > head:command = head -n 5
   > head:pattern = numbers.txt
   > head:priority = 1
-  > sort:command = sort --numeric-sort
+  > sort:command = sort -n
   > sort:pattern = numbers.txt
   > sort:priority = 2
   > EOF
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -62,8 +62,8 @@
 in a text file by ensuring that 'sort' runs before 'head'::
 
   [fix]
-  sort:command = sort --numeric-sort
-  head:command = head --lines=10
+  sort:command = sort -n
+  head:command = head -n 10
   sort:pattern = numbers.txt
   head:pattern = numbers.txt
   sort:priority = 2



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5516: fix: add some arguments to facilitate extensions

2019-01-07 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  For example, these additions allow wrapping `hg fix` to do things like:
  
  - Telling fixer tools what commit a file belongs to
  - Cleaning up temporary files created by Fixer objects
  
  There are no intended functional changes.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5516

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -239,9 +239,11 @@
 replacerev(ui, repo, ctx, filedata[rev], replacements)
 del filedata[rev]
 
-cleanup(repo, replacements, wdirwritten)
+cleanup(repo, replacements, wdirwritten, fixers)
 
-def cleanup(repo, replacements, wdirwritten):
+# Do not inline this function or remove unused arguments. They are meant as a
+# wrapping point for further extensions.
+def cleanup(repo, replacements, wdirwritten, fixers):
 """Calls scmutil.cleanupnodes() with the given replacements.
 
 "replacements" is a dict from nodeid to nodeid, with one key and one value
@@ -251,6 +253,10 @@
 "wdirwritten" is a bool which tells whether the working copy was affected 
by
 fixing, since it has no entry in "replacements".
 
+"fixers" is the list of fixer tools that was used, in case we want to clean
+up something they dirtied (though they currently have no side effects 
within
+this extension).
+
 Useful as a hook point for extending "hg fix" with output summarizing the
 effects of the command, though we choose not to output anything here.
 """
@@ -497,7 +503,7 @@
 for fixername, fixer in fixers.iteritems():
 if fixer.affects(opts, fixctx, path):
 rangesfn = lambda: lineranges(opts, path, basectxs, fixctx, 
newdata)
-command = fixer.command(ui, path, rangesfn)
+command = fixer.command(ui, fixctx, path, rangesfn)
 if command is None:
 continue
 ui.debug('subprocess: %s\n' % (command,))
@@ -652,6 +658,7 @@
 setattr(fixers[name], pycompat.sysstr('_' + key),
 attrs.get(key, default))
 fixers[name]._priority = int(fixers[name]._priority)
+fixers[name].name = name
 return collections.OrderedDict(
 sorted(fixers.items(), key=lambda item: item[1]._priority,
reverse=True))
@@ -671,11 +678,13 @@
 """Should this fixer run on the file at the given path and context?"""
 return scmutil.match(fixctx, [self._pattern], opts)(path)
 
-def command(self, ui, path, rangesfn):
+def command(self, ui, ctx, path, rangesfn):
 """A shell command to use to invoke this fixer on the given file/lines
 
 May return None if there is no appropriate command to run for the given
 parameters.
+
+"ctx" is unused, but it is meant for use by further extensions.
 """
 expand = cmdutil.rendercommandtemplate
 parts = [expand(ui, self._command,



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5428: absorb: don't prompt to apply changes when there are none to apply

2018-12-14 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGa08e12149bcb: absorb: dont prompt to apply changes 
when there are none to apply (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5428?vs=12859=12864

REVISION DETAIL
  https://phab.mercurial-scm.org/D5428

AFFECTED FILES
  hgext/absorb.py
  tests/test-absorb.t

CHANGE DETAILS

diff --git a/tests/test-absorb.t b/tests/test-absorb.t
--- a/tests/test-absorb.t
+++ b/tests/test-absorb.t
@@ -129,6 +129,20 @@
   nothing applied
   [1]
 
+The prompt is not given if there are no changes to be applied, even if there
+are some changes that won't be applied:
+
+  $ hg absorb
+  showing changes for a
+  @@ -0,2 +0,1 @@
+  -2b
+  -4d
+  +1
+  
+  0 changesets affected
+  nothing applied
+  [1]
+
 Insertaions:
 
   $ cat > a << EOF
diff --git a/hgext/absorb.py b/hgext/absorb.py
--- a/hgext/absorb.py
+++ b/hgext/absorb.py
@@ -971,9 +971,10 @@
  label='absorb.description')
 fm.end()
 if not opts.get('dry_run'):
-if not opts.get('apply_changes'):
-if ui.promptchoice("apply changes (yn)? $$  $$ ", 
default=1):
-raise error.Abort(_('absorb cancelled\n'))
+if (not opts.get('apply_changes') and
+state.ctxaffected and
+ui.promptchoice("apply changes (yn)? $$  $$ ", default=1)):
+raise error.Abort(_('absorb cancelled\n'))
 
 state.apply()
 if state.commit():



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5428: absorb: don't prompt to apply changes when there are none to apply

2018-12-14 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5428

AFFECTED FILES
  hgext/absorb.py
  tests/test-absorb.t

CHANGE DETAILS

diff --git a/tests/test-absorb.t b/tests/test-absorb.t
--- a/tests/test-absorb.t
+++ b/tests/test-absorb.t
@@ -129,6 +129,20 @@
   nothing applied
   [1]
 
+The prompt is not given if there are no changes to be applied, even if there
+are some changes that won't be applied:
+
+  $ hg absorb
+  showing changes for a
+  @@ -0,2 +0,1 @@
+  -2b
+  -4d
+  +1
+  
+  0 changesets affected
+  nothing applied
+  [1]
+
 Insertaions:
 
   $ cat > a << EOF
diff --git a/hgext/absorb.py b/hgext/absorb.py
--- a/hgext/absorb.py
+++ b/hgext/absorb.py
@@ -971,9 +971,10 @@
  label='absorb.description')
 fm.end()
 if not opts.get('dry_run'):
-if not opts.get('apply_changes'):
-if ui.promptchoice("apply changes (yn)? $$  $$ ", 
default=1):
-raise error.Abort(_('absorb cancelled\n'))
+if (not opts.get('apply_changes') and
+state.ctxaffected and
+ui.promptchoice("apply changes (yn)? $$  $$ ", default=1)):
+raise error.Abort(_('absorb cancelled\n'))
 
 state.apply()
 if state.commit():



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5245: fix: add extra field to fixed revisions to avoid creating obsolescence cycles

2018-11-09 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGad71c792a8d8: fix: add extra field to fixed revisions to 
avoid creating obsolescence cycles (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5245?vs=12481=12484

REVISION DETAIL
  https://phab.mercurial-scm.org/D5245

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1195,3 +1195,37 @@
   8
 
   $ cd ..
+
+It's possible for repeated applications of a fixer tool to create cycles in the
+generated content of a file. For example, two users with different versions of
+a code formatter might fight over the formatting when they run hg fix. In the
+absence of other changes, this means we could produce commits with the same
+hash in subsequent runs of hg fix. This is a problem unless we support
+obsolescence cycles well. We avoid this by adding an extra field to the
+successor which forces it to have a new hash. That's why this test creates
+three revisions instead of two.
+
+  $ hg init cyclictool
+  $ cd cyclictool
+
+  $ cat >> .hg/hgrc < [fix]
+  > swapletters:command = tr ab ba
+  > swapletters:pattern = foo
+  > EOF
+
+  $ echo ab > foo
+  $ hg commit -Aqm foo
+
+  $ hg fix -r 0
+  $ hg fix -r 1
+
+  $ hg cat -r 0 foo --hidden
+  ab
+  $ hg cat -r 1 foo --hidden
+  ba
+  $ hg cat -r 2 foo
+  ab
+
+  $ cd ..
+
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -586,6 +586,17 @@
 newp1node = replacements.get(p1ctx.node(), p1ctx.node())
 newp2node = replacements.get(p2ctx.node(), p2ctx.node())
 
+# We don't want to create a revision that has no changes from the original,
+# but we should if the original revision's parent has been replaced.
+# Otherwise, we would produce an orphan that needs no actual human
+# intervention to evolve. We can't rely on commit() to avoid creating the
+# un-needed revision because the extra field added below produces a new 
hash
+# regardless of file content changes.
+if (not filedata and
+p1ctx.node() not in replacements and
+p2ctx.node() not in replacements):
+return
+
 def filectxfn(repo, memctx, path):
 if path not in ctx:
 return None
@@ -602,15 +613,18 @@
 isexec=fctx.isexec(),
 copied=copied)
 
+extra = ctx.extra().copy()
+extra['fix_source'] = ctx.hex()
+
 memctx = context.memctx(
 repo,
 parents=(newp1node, newp2node),
 text=ctx.description(),
 files=set(ctx.files()) | set(filedata.keys()),
 filectxfn=filectxfn,
 user=ctx.user(),
 date=ctx.date(),
-extra=ctx.extra(),
+extra=extra,
 branch=ctx.branch(),
 editor=None)
 sucnode = memctx.commit()



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5244: cleanup: use revision numbers instead of hashes in test output

2018-11-09 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG19e1c26213f1: cleanup: use revision numbers instead of 
hashes in test output (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5244?vs=12480=12483

REVISION DETAIL
  https://phab.mercurial-scm.org/D5244

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -893,24 +893,24 @@
   $ printf "BAR\n" > bar.whole
   $ hg commit -Aqm "add bar"
 
-  $ hg log --graph --template '{node|shortest} {files}'
-  @  bc05 bar.whole
+  $ hg log --graph --template '{rev} {files}'
+  @  2 bar.whole
   |
-  o  4fd2 foo.whole
+  o  1 foo.whole
   |
-  o  f9ac foo.whole
+  o  0 foo.whole
   
   $ hg fix -r 0:2
-  $ hg log --graph --template '{node|shortest} {files}'
-  o  b4e2 bar.whole
+  $ hg log --graph --template '{rev} {files}'
+  o  4 bar.whole
   |
-  o  59f4
+  o  3
   |
-  | @  bc05 bar.whole
+  | @  2 bar.whole
   | |
-  | x  4fd2 foo.whole
+  | x  1 foo.whole
   |/
-  o  f9ac foo.whole
+  o  0 foo.whole
   
 
   $ cd ..



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5245: fix: add extra field to fixed revisions to avoid creating obsolescence cycles

2018-11-08 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The extra field prevents sequential invocations of fix from producing the same
  hash twice. Previously, this could cause problems because it would create an
  obsolescence cycle instead of the expected new successor.
  
  This change also adds an explicit check for whether a new revision should be
  committed. Until now, the code relied on memctx.commit() to quietly do nothing
  if the node already exists. Because of the new extra field, this no longer
  covers the case where we don't want to replace an unchanged node.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5245

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1195,3 +1195,37 @@
   8
 
   $ cd ..
+
+It's possible for repeated applications of a fixer tool to create cycles in the
+generated content of a file. For example, two users with different versions of
+a code formatter might fight over the formatting when they run hg fix. In the
+absence of other changes, this means we could produce commits with the same
+hash in subsequent runs of hg fix. This is a problem unless we support
+obsolescence cycles well. We avoid this by adding an extra field to the
+successor which forces it to have a new hash. That's why this test creates
+three revisions instead of two.
+
+  $ hg init cyclictool
+  $ cd cyclictool
+
+  $ cat >> .hg/hgrc < [fix]
+  > swapletters:command = tr ab ba
+  > swapletters:pattern = foo
+  > EOF
+
+  $ echo ab > foo
+  $ hg commit -Aqm foo
+
+  $ hg fix -r 0
+  $ hg fix -r 1
+
+  $ hg cat -r 0 foo --hidden
+  ab
+  $ hg cat -r 1 foo --hidden
+  ba
+  $ hg cat -r 2 foo
+  ab
+
+  $ cd ..
+
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -586,6 +586,17 @@
 newp1node = replacements.get(p1ctx.node(), p1ctx.node())
 newp2node = replacements.get(p2ctx.node(), p2ctx.node())
 
+# We don't want to create a revision that has no changes from the original,
+# but we should if the original revision's parent has been replaced.
+# Otherwise, we would produce an orphan that needs no actual human
+# intervention to evolve. We can't rely on commit() to avoid creating the
+# un-needed revision because the extra field added below produces a new 
hash
+# regardless of file content changes.
+if (not filedata and
+p1ctx.node() not in replacements and
+p2ctx.node() not in replacements):
+return
+
 def filectxfn(repo, memctx, path):
 if path not in ctx:
 return None
@@ -602,15 +613,18 @@
 isexec=fctx.isexec(),
 copied=copied)
 
+extra = ctx.extra().copy()
+extra['fix_source'] = ctx.hex()
+
 memctx = context.memctx(
 repo,
 parents=(newp1node, newp2node),
 text=ctx.description(),
 files=set(ctx.files()) | set(filedata.keys()),
 filectxfn=filectxfn,
 user=ctx.user(),
 date=ctx.date(),
-extra=ctx.extra(),
+extra=extra,
 branch=ctx.branch(),
 editor=None)
 sucnode = memctx.commit()



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5244: cleanup: use revision numbers instead of hashes in test output

2018-11-08 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This allows changes to the hashes produced by fix to not needlessly modify 
this
  area of the test.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5244

AFFECTED FILES
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -893,24 +893,24 @@
   $ printf "BAR\n" > bar.whole
   $ hg commit -Aqm "add bar"
 
-  $ hg log --graph --template '{node|shortest} {files}'
-  @  bc05 bar.whole
+  $ hg log --graph --template '{rev} {files}'
+  @  2 bar.whole
   |
-  o  4fd2 foo.whole
+  o  1 foo.whole
   |
-  o  f9ac foo.whole
+  o  0 foo.whole
   
   $ hg fix -r 0:2
-  $ hg log --graph --template '{node|shortest} {files}'
-  o  b4e2 bar.whole
+  $ hg log --graph --template '{rev} {files}'
+  o  4 bar.whole
   |
-  o  59f4
+  o  3
   |
-  | @  bc05 bar.whole
+  | @  2 bar.whole
   | |
-  | x  4fd2 foo.whole
+  | x  1 foo.whole
   |/
-  o  f9ac foo.whole
+  o  0 foo.whole
   
 
   $ cd ..



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5237: fix: add suboption for configuring execution order of tools

2018-11-08 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGb9557567cc3f: fix: add suboption for configuring execution 
order of tools (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5237?vs=12473=12477

REVISION DETAIL
  https://phab.mercurial-scm.org/D5237

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -165,6 +165,26 @@
 [fix]
 failure = abort
   
+  When multiple tools are configured to affect a file, they execute in an order
+  defined by the :priority suboption. The priority suboption has a default 
value
+  of zero for each tool. Tools are executed in order of descending priority. 
The
+  execution order of tools with equal priority is unspecified. For example, you
+  could use the 'sort' and 'head' utilities to keep only the 10 smallest 
numbers
+  in a text file by ensuring that 'sort' runs before 'head':
+  
+[fix]
+sort:command = sort --numeric-sort
+head:command = head --lines=10
+sort:pattern = numbers.txt
+head:pattern = numbers.txt
+sort:priority = 2
+head:priority = 1
+  
+  To account for changes made by each tool, the line numbers used for
+  incremental formatting are recomputed before executing the next tool. So, 
each
+  tool may see different values for the arguments added by the :linerange
+  suboption.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
@@ -1127,3 +1147,51 @@
   first
 
   $ cd ..
+
+The execution order of tools can be controlled. This example doesn't work if
+you sort after truncating, but the config defines the correct order while the
+definitions are out of order (which might imply the incorrect order given the
+implementation of fix). The goal is to use multiple tools to select the lowest
+5 numbers in the file.
+
+  $ hg init priorityexample
+  $ cd priorityexample
+
+  $ cat >> .hg/hgrc < [fix]
+  > head:command = head --lines=5
+  > head:pattern = numbers.txt
+  > head:priority = 1
+  > sort:command = sort --numeric-sort
+  > sort:pattern = numbers.txt
+  > sort:priority = 2
+  > EOF
+
+  $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
+  $ hg add -q
+  $ hg fix -w
+  $ cat numbers.txt
+  0
+  1
+  2
+  3
+  4
+
+And of course we should be able to break this by reversing the execution order.
+Test negative priorities while we're at it.
+
+  $ cat >> .hg/hgrc < [fix]
+  > head:priority = -1
+  > sort:priority = -2
+  > EOF
+  $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
+  $ hg fix -w
+  $ cat numbers.txt
+  2
+  3
+  6
+  7
+  8
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -54,6 +54,24 @@
   [fix]
   failure = abort
 
+When multiple tools are configured to affect a file, they execute in an order
+defined by the :priority suboption. The priority suboption has a default value
+of zero for each tool. Tools are executed in order of descending priority. The
+execution order of tools with equal priority is unspecified. For example, you
+could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
+in a text file by ensuring that 'sort' runs before 'head'::
+
+  [fix]
+  sort:command = sort --numeric-sort
+  head:command = head --lines=10
+  sort:pattern = numbers.txt
+  head:pattern = numbers.txt
+  sort:priority = 2
+  head:priority = 1
+
+To account for changes made by each tool, the line numbers used for incremental
+formatting are recomputed before executing the next tool. So, each tool may see
+different values for the arguments added by the :linerange suboption.
 """
 
 from __future__ import absolute_import
@@ -100,10 +118,16 @@
 configitem = registrar.configitem(configtable)
 
 # Register the suboptions allowed for each configured fixer.
-FIXER_ATTRS = ('command', 'linerange', 'fileset', 'pattern')
+FIXER_ATTRS = {
+'command': None,
+'linerange': None,
+'fileset': None,
+'pattern': None,
+'priority': 0,
+}
 
-for key in FIXER_ATTRS:
-configitem('fix', '.*(:%s)?' % key, default=None, generic=True)
+for key, default in FIXER_ATTRS.items():
+configitem('fix', '.*(:%s)?' % key, default=default, generic=True)
 
 # A good default size allows most source code files to be fixed, but avoids
 # letting fixer tools choke on huge inputs, which could be surprising to the
@@ -602,18 +626,21 @@
 Each value is a Fixer object with methods that implement the behavior of 
the
 fixer's config suboptions. Does not validate the config values.
 """
-result = {}
+fixers = {}
 for name in fixernames(ui):
-result[name] = Fixer()
+fixers[name] = Fixer()
 attrs = ui.configsuboptions('fix', name)[1]
 if 'fileset' in attrs and 'pattern' not in attrs:
 ui.warn(_('the fix.tool:fileset config name 

D5237: fix: add suboption for configuring execution order of tools

2018-11-07 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 12473.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5237?vs=12461=12473

REVISION DETAIL
  https://phab.mercurial-scm.org/D5237

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -165,6 +165,26 @@
 [fix]
 failure = abort
   
+  When multiple tools are configured to affect a file, they execute in an order
+  defined by the :priority suboption. The priority suboption has a default 
value
+  of zero for each tool. Tools are executed in order of descending priority. 
The
+  execution order of tools with equal priority is unspecified. For example, you
+  could use the 'sort' and 'head' utilities to keep only the 10 smallest 
numbers
+  in a text file by ensuring that 'sort' runs before 'head':
+  
+[fix]
+sort:command = sort --numeric-sort
+head:command = head --lines=10
+sort:pattern = numbers.txt
+head:pattern = numbers.txt
+sort:priority = 2
+head:priority = 1
+  
+  To account for changes made by each tool, the line numbers used for
+  incremental formatting are recomputed before executing the next tool. So, 
each
+  tool may see different values for the arguments added by the :linerange
+  suboption.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
@@ -1127,3 +1147,51 @@
   first
 
   $ cd ..
+
+The execution order of tools can be controlled. This example doesn't work if
+you sort after truncating, but the config defines the correct order while the
+definitions are out of order (which might imply the incorrect order given the
+implementation of fix). The goal is to use multiple tools to select the lowest
+5 numbers in the file.
+
+  $ hg init priorityexample
+  $ cd priorityexample
+
+  $ cat >> .hg/hgrc < [fix]
+  > head:command = head --lines=5
+  > head:pattern = numbers.txt
+  > head:priority = 1
+  > sort:command = sort --numeric-sort
+  > sort:pattern = numbers.txt
+  > sort:priority = 2
+  > EOF
+
+  $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
+  $ hg add -q
+  $ hg fix -w
+  $ cat numbers.txt
+  0
+  1
+  2
+  3
+  4
+
+And of course we should be able to break this by reversing the execution order.
+Test negative priorities while we're at it.
+
+  $ cat >> .hg/hgrc < [fix]
+  > head:priority = -1
+  > sort:priority = -2
+  > EOF
+  $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
+  $ hg fix -w
+  $ cat numbers.txt
+  2
+  3
+  6
+  7
+  8
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -54,6 +54,24 @@
   [fix]
   failure = abort
 
+When multiple tools are configured to affect a file, they execute in an order
+defined by the :priority suboption. The priority suboption has a default value
+of zero for each tool. Tools are executed in order of descending priority. The
+execution order of tools with equal priority is unspecified. For example, you
+could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
+in a text file by ensuring that 'sort' runs before 'head'::
+
+  [fix]
+  sort:command = sort --numeric-sort
+  head:command = head --lines=10
+  sort:pattern = numbers.txt
+  head:pattern = numbers.txt
+  sort:priority = 2
+  head:priority = 1
+
+To account for changes made by each tool, the line numbers used for incremental
+formatting are recomputed before executing the next tool. So, each tool may see
+different values for the arguments added by the :linerange suboption.
 """
 
 from __future__ import absolute_import
@@ -100,10 +118,16 @@
 configitem = registrar.configitem(configtable)
 
 # Register the suboptions allowed for each configured fixer.
-FIXER_ATTRS = ('command', 'linerange', 'fileset', 'pattern')
+FIXER_ATTRS = {
+'command': None,
+'linerange': None,
+'fileset': None,
+'pattern': None,
+'priority': 0,
+}
 
-for key in FIXER_ATTRS:
-configitem('fix', '.*(:%s)?' % key, default=None, generic=True)
+for key, default in FIXER_ATTRS.items():
+configitem('fix', '.*(:%s)?' % key, default=default, generic=True)
 
 # A good default size allows most source code files to be fixed, but avoids
 # letting fixer tools choke on huge inputs, which could be surprising to the
@@ -602,18 +626,21 @@
 Each value is a Fixer object with methods that implement the behavior of 
the
 fixer's config suboptions. Does not validate the config values.
 """
-result = {}
+fixers = {}
 for name in fixernames(ui):
-result[name] = Fixer()
+fixers[name] = Fixer()
 attrs = ui.configsuboptions('fix', name)[1]
 if 'fileset' in attrs and 'pattern' not in attrs:
 ui.warn(_('the fix.tool:fileset config name is deprecated; '
   'please rename it to fix.tool:pattern\n'))
 attrs['pattern'] = attrs['fileset']
-for key in 

D5237: fix: add suboption for configuring execution order of tools

2018-11-06 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 12461.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5237?vs=12460=12461

REVISION DETAIL
  https://phab.mercurial-scm.org/D5237

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -165,6 +165,26 @@
 [fix]
 failure = abort
   
+  When multiple tools are configured to affect a file, they execute in an order
+  defined by the :priority suboption. The priority suboption has a default 
value
+  of zero for each tool. Tools are executed in order of ascending priority. The
+  execution order of tools with equal priority is unspecified. For example, you
+  could use the 'sort' and 'head' utilities to keep only the 10 smallest 
numbers
+  in a text file by ensuring that 'sort' runs before 'head':
+  
+[fix]
+sort:command = sort --numeric-sort
+head:command = head --lines=10
+sort:pattern = numbers.txt
+head:pattern = numbers.txt
+sort:priority = 1
+head:priority = 2
+  
+  To account for changes made by each tool, the line numbers used for
+  incremental formatting are recomputed before executing the next tool. So, 
each
+  tool may see different values for the arguments added by the :linerange
+  suboption.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
@@ -1127,3 +1147,51 @@
   first
 
   $ cd ..
+
+The execution order of tools can be controlled. This example doesn't work if
+you sort after truncating, but the config defines the correct order while the
+definitions are out of order (which might imply the incorrect order given the
+implementation of fix). The goal is to use multiple tools to select the lowest
+5 numbers in the file.
+
+  $ hg init priorityexample
+  $ cd priorityexample
+
+  $ cat >> .hg/hgrc < [fix]
+  > head:command = head --lines=5
+  > head:pattern = numbers.txt
+  > head:priority = 2
+  > sort:command = sort --numeric-sort
+  > sort:pattern = numbers.txt
+  > sort:priority = 1
+  > EOF
+
+  $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
+  $ hg add -q
+  $ hg fix -w
+  $ cat numbers.txt
+  0
+  1
+  2
+  3
+  4
+
+And of course we should be able to break this by reversing the execution order.
+Test negative priorities while we're at it.
+
+  $ cat >> .hg/hgrc < [fix]
+  > head:priority = -2
+  > sort:priority = -1
+  > EOF
+  $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
+  $ hg fix -w
+  $ cat numbers.txt
+  2
+  3
+  6
+  7
+  8
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -54,6 +54,24 @@
   [fix]
   failure = abort
 
+When multiple tools are configured to affect a file, they execute in an order
+defined by the :priority suboption. The priority suboption has a default value
+of zero for each tool. Tools are executed in order of ascending priority. The
+execution order of tools with equal priority is unspecified. For example, you
+could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
+in a text file by ensuring that 'sort' runs before 'head'::
+
+  [fix]
+  sort:command = sort --numeric-sort
+  head:command = head --lines=10
+  sort:pattern = numbers.txt
+  head:pattern = numbers.txt
+  sort:priority = 1
+  head:priority = 2
+
+To account for changes made by each tool, the line numbers used for incremental
+formatting are recomputed before executing the next tool. So, each tool may see
+different values for the arguments added by the :linerange suboption.
 """
 
 from __future__ import absolute_import
@@ -100,10 +118,16 @@
 configitem = registrar.configitem(configtable)
 
 # Register the suboptions allowed for each configured fixer.
-FIXER_ATTRS = ('command', 'linerange', 'fileset', 'pattern')
+FIXER_ATTRS = {
+'command': None,
+'linerange': None,
+'fileset': None,
+'pattern': None,
+'priority': 0,
+}
 
-for key in FIXER_ATTRS:
-configitem('fix', '.*(:%s)?' % key, default=None, generic=True)
+for key, default in FIXER_ATTRS.items():
+configitem('fix', '.*(:%s)?' % key, default=default, generic=True)
 
 # A good default size allows most source code files to be fixed, but avoids
 # letting fixer tools choke on huge inputs, which could be surprising to the
@@ -602,18 +626,20 @@
 Each value is a Fixer object with methods that implement the behavior of 
the
 fixer's config suboptions. Does not validate the config values.
 """
-result = {}
+fixers = {}
 for name in fixernames(ui):
-result[name] = Fixer()
+fixers[name] = Fixer()
 attrs = ui.configsuboptions('fix', name)[1]
 if 'fileset' in attrs and 'pattern' not in attrs:
 ui.warn(_('the fix.tool:fileset config name is deprecated; '
   'please rename it to fix.tool:pattern\n'))
 attrs['pattern'] = attrs['fileset']
-for key in FIXER_ATTRS:
- 

D5237: fix: add suboption for configuring execution order of tools

2018-11-06 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This could be accomplished by using wrapper scripts, but that would diminish
  the usefulness of the incremental formatting logic. Configuring execution 
order
  along with other things in the hgrc is probably more convenient anyway.
  
  This change highlights some awkwardness with suboptions and default values,
  which should be addressed separately.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5237

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -165,6 +165,26 @@
 [fix]
 failure = abort
   
+  When multiple tools are configured to affect a file, they execute in an order
+  defined by the :priority suboption. The priority suboption has a default 
value
+  of zero for each tool. Tools are executed in order of ascending priority. The
+  execution order of tools with equal priority is unspecified. For example, you
+  could use the 'sort' and 'head' utilities to keep only the 10 smallest 
numbers
+  in a text file by ensuring that 'sort' runs before 'head':
+  
+[fix]
+sort:command = sort --numeric-sort
+head:command = head --lines=10
+sort:pattern = numbers.txt
+head:pattern = numbers.txt
+sort:priority = 1
+head:priority = 2
+  
+  To account for changes made by each tool, the line numbers used for
+  incremental formatting are recomputed before executing the next tool. So, 
each
+  tool may see different values for the arguments added by the :linerange
+  suboption.
+  
   list of commands:
   
fix   rewrite file content in changesets or working directory
@@ -1127,3 +1147,52 @@
   first
 
   $ cd ..
+
+The execution order of tools can be controlled. This example doesn't work if
+you sort after truncating, but the config defines the correct order while the
+definitions are out of order (which might imply the incorrect order given the
+implementation of fix). The goal is to use multiple tools to select the lowest
+5 numbers in the file.
+
+  $ hg init priorityexample
+  $ cd priorityexample
+
+  $ cat >> .hg/hgrc < [fix]
+  > head:command = head --lines=5
+  > head:pattern = numbers.txt
+  > head:priority = 2
+  > sort:command = sort --numeric-sort
+  > sort:pattern = numbers.txt
+  > sort:priority = 1
+  > EOF
+
+  $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
+  $ hg add -q
+  $ hg fix -w
+  $ cat numbers.txt
+  0
+  1
+  2
+  3
+  4
+
+And of course we should be able to break this by reversing the execution order.
+Test negative priorities while we're at it.
+
+  $ cat >> .hg/hgrc < [fix]
+  > head:priority = -2
+  > sort:priority = -1
+  > EOF
+  $ printf "8\n2\n3\n6\n7\n4\n9\n5\n1\n0\n" > numbers.txt
+  $ hg fix -w
+  $ cat numbers.txt
+  2
+  3
+  6
+  7
+  8
+
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -54,6 +54,24 @@
   [fix]
   failure = abort
 
+When multiple tools are configured to affect a file, they execute in an order
+defined by the :priority suboption. The priority suboption has a default value
+of zero for each tool. Tools are executed in order of ascending priority. The
+execution order of tools with equal priority is unspecified. For example, you
+could use the 'sort' and 'head' utilities to keep only the 10 smallest numbers
+in a text file by ensuring that 'sort' runs before 'head'::
+
+  [fix]
+  sort:command = sort --numeric-sort
+  head:command = head --lines=10
+  sort:pattern = numbers.txt
+  head:pattern = numbers.txt
+  sort:priority = 1
+  head:priority = 2
+
+To account for changes made by each tool, the line numbers used for incremental
+formatting are recomputed before executing the next tool. So, each tool may see
+different values for the arguments added by the :linerange suboption.
 """
 
 from __future__ import absolute_import
@@ -100,10 +118,16 @@
 configitem = registrar.configitem(configtable)
 
 # Register the suboptions allowed for each configured fixer.
-FIXER_ATTRS = ('command', 'linerange', 'fileset', 'pattern')
+FIXER_ATTRS = {
+'command': None,
+'linerange': None,
+'fileset': None,
+'pattern': None,
+'priority': 0,
+}
 
-for key in FIXER_ATTRS:
-configitem('fix', '.*(:%s)?' % key, default=None, generic=True)
+for key, default in FIXER_ATTRS.items():
+configitem('fix', '.*(:%s)?' % key, default=default, generic=True)
 
 # A good default size allows most source code files to be fixed, but avoids
 # letting fixer tools choke on huge inputs, which could be surprising to the
@@ -602,18 +626,20 @@
 Each value is a Fixer object with methods that implement the behavior of 
the
 fixer's config suboptions. Does not validate the config values.
 """
-result = {}
+fixers = {}
 for name in fixernames(ui):
-result[name] = Fixer()
+  

D5226: fix: rename :fileset subconfig to :pattern

2018-11-06 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG2ecf5c24d0cd: fix: rename :fileset subconfig to :pattern 
(authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5226?vs=12437=12446

REVISION DETAIL
  https://phab.mercurial-scm.org/D5226

AFFECTED FILES
  hgext/fix.py
  tests/test-fix-clang-format.t
  tests/test-fix-topology.t
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -66,10 +66,10 @@
   > evolution.allowunstable=True
   > [fix]
   > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY all
-  > uppercase-whole-file:fileset=set:**.whole
+  > uppercase-whole-file:pattern=set:**.whole
   > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY
   > uppercase-changed-lines:linerange={first}-{last}
-  > uppercase-changed-lines:fileset=set:**.changed
+  > uppercase-changed-lines:pattern=set:**.changed
   > EOF
 
 Help text for fix.
@@ -126,7 +126,7 @@
 [fix]
 clang-format:command=clang-format --assume-filename={rootpath}
 clang-format:linerange=--lines={first}:{last}
-clang-format:fileset=set:**.cpp or **.hpp
+clang-format:pattern=set:**.cpp or **.hpp
   
   The :command suboption forms the first part of the shell command that will be
   used to fix a file. The content of the file is passed on standard input, and
@@ -147,9 +147,9 @@
 {first}   The 1-based line number of the first line in the modified range
 {last}The 1-based line number of the last line in the modified range
   
-  The :fileset suboption determines which files will be passed through each
-  configured tool. See 'hg help fileset' for possible values. If there are file
-  arguments to 'hg fix', the intersection of these filesets is used.
+  The :pattern suboption determines which files will be passed through each
+  configured tool. See 'hg help patterns' for possible values. If there are 
file
+  arguments to 'hg fix', the intersection of these patterns is used.
   
   There is also a configurable limit for the maximum size of file that will be
   processed by 'hg fix':
@@ -371,7 +371,7 @@
 
   $ hg --config "fix.fail:command=echo" \
   >--config "fix.fail:linerange={first}:{last}" \
-  >--config "fix.fail:fileset=foo.txt" \
+  >--config "fix.fail:pattern=foo.txt" \
   >fix --working-dir
   $ cat foo.txt
   1:1 4:6 8:8
@@ -534,7 +534,7 @@
   > exit 0 # success despite the stderr output
   > EOF
   $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \
-  >--config "fix.work:fileset=hello.txt" \
+  >--config "fix.work:pattern=hello.txt" \
   >fix --working-dir
   [wdir] work: hello.txt: some
   [wdir] work: error that didn't stop the tool
@@ -551,7 +551,7 @@
   > exit 42 # success despite the stdout output
   > EOF
   $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >--config "fix.failure=abort" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
@@ -565,7 +565,7 @@
   foo
 
   $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
   [wdir] fail: error that did stop the tool
@@ -575,7 +575,7 @@
   FOO
 
   $ hg --config "fix.fail:command=exit 42" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >fix --working-dir
   [wdir] fail: exited with status 42
 
@@ -1027,7 +1027,7 @@
   adding foo/bar
   $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \
   >--config "fix.fail:linerange='{first}' '{last}'" \
-  >--config "fix.fail:fileset=foo/bar" \
+  >--config "fix.fail:pattern=foo/bar" \
   >fix --working-dir
   $ cat foo/bar
   foo/bar
@@ -1105,3 +1105,25 @@
   FOO2
 
   $ cd ..
+
+The :fileset subconfig was a misnomer, so we renamed it to :pattern. We will
+still accept :fileset by itself as if it were :pattern, but this will issue a
+warning.
+
+  $ hg init filesetispattern
+  $ cd filesetispattern
+
+  $ printf "foo\n" > foo.whole
+  $ printf "first\nsecond\n" > bar.txt
+  $ hg add -q
+  $ hg fix -w --config fix.sometool:fileset=bar.txt \
+  >   --config fix.sometool:command=tac
+  the fix.tool:fileset config name is deprecated; please rename it to 
fix.tool:pattern
+
+  $ cat foo.whole
+  FOO
+  $ cat bar.txt
+  second
+  first
+
+  $ cd ..
diff --git a/tests/test-fix-topology.t b/tests/test-fix-topology.t
--- a/tests/test-fix-topology.t
+++ b/tests/test-fix-topology.t
@@ -23,7 +23,7 @@
   > fix =
   > [fix]
   > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY
-  > uppercase-whole-file:fileset=set:**
+  > uppercase-whole-file:pattern=set:**
   > EOF
 
 This tests the only behavior 

D5200: fix: add a config to abort when a fixer tool fails

2018-11-06 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG93bab80993f4: fix: add a config to abort when a fixer tool 
fails (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5200?vs=12435=12445

REVISION DETAIL
  https://phab.mercurial-scm.org/D5200

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -130,9 +130,11 @@
   
   The :command suboption forms the first part of the shell command that will be
   used to fix a file. The content of the file is passed on standard input, and
-  the fixed file content is expected on standard output. If there is any output
-  on standard error, the file will not be affected. Some values may be
-  substituted into the command:
+  the fixed file content is expected on standard output. Any output on standard
+  error will be displayed as a warning. If the exit status is not zero, the 
file
+  will not be affected. A placeholder warning is displayed if there is a non-
+  zero exit status but no standard error output. Some values may be substituted
+  into the command:
   
 {rootpath}  The path of the file being fixed, relative to the repo root
 {basename}  The name of the file being fixed, without the directory path
@@ -153,7 +155,15 @@
   processed by 'hg fix':
   
 [fix]
-maxfilesize=2MB
+maxfilesize = 2MB
+  
+  Normally, execution of configured tools will continue after a failure
+  (indicated by a non-zero exit status). It can also be configured to abort
+  after the first such failure, so that no files will be affected if any tool
+  fails. This abort will also cause 'hg fix' to exit with a non-zero status:
+  
+[fix]
+failure = abort
   
   list of commands:
   
@@ -508,40 +518,61 @@
 on stderr and nothing on stdout, which would cause us the clear the file,
 except that they also exit with a non-zero code. We show the user which fixer
 emitted the stderr, and which revision, but we assume that the fixer will print
-the filename if it is relevant (since the issue may be non-specific).
+the filename if it is relevant (since the issue may be non-specific). There is
+also a config to abort (without affecting any files whatsoever) if we see any
+tool with a non-zero exit status.
 
   $ hg init showstderr
   $ cd showstderr
 
   $ printf "hello\n" > hello.txt
   $ hg add
   adding hello.txt
-  $ cat > $TESTTMP/fail.sh <<'EOF'
+  $ cat > $TESTTMP/work.sh <<'EOF'
   > printf 'HELLO\n'
-  > printf "$@: some\nerror" >&2
+  > printf "$@: some\nerror that didn't stop the tool" >&2
   > exit 0 # success despite the stderr output
   > EOF
+  $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \
+  >--config "fix.work:fileset=hello.txt" \
+  >fix --working-dir
+  [wdir] work: hello.txt: some
+  [wdir] work: error that didn't stop the tool
+  $ cat hello.txt
+  HELLO
+
+  $ printf "goodbye\n" > hello.txt
+  $ printf "foo\n" > foo.whole
+  $ hg add
+  adding foo.whole
+  $ cat > $TESTTMP/fail.sh <<'EOF'
+  > printf 'GOODBYE\n'
+  > printf "$@: some\nerror that did stop the tool\n" >&2
+  > exit 42 # success despite the stdout output
+  > EOF
+  $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
+  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.failure=abort" \
+  >fix --working-dir
+  [wdir] fail: hello.txt: some
+  [wdir] fail: error that did stop the tool
+  abort: no fixes will be applied
+  (use --config fix.failure=continue to apply any successful fixes anyway)
+  [255]
+  $ cat hello.txt
+  goodbye
+  $ cat foo.whole
+  foo
+
   $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
   >--config "fix.fail:fileset=hello.txt" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
-  [wdir] fail: error
-  $ cat hello.txt
-  HELLO
-
-  $ printf "goodbye\n" > hello.txt
-  $ cat > $TESTTMP/work.sh <<'EOF'
-  > printf 'GOODBYE\n'
-  > printf "$@: some\nerror\n" >&2
-  > exit 42 # success despite the stdout output
-  > EOF
-  $ hg --config "fix.fail:command=sh $TESTTMP/work.sh {rootpath}" \
-  >--config "fix.fail:fileset=hello.txt" \
-  >fix --working-dir
-  [wdir] fail: hello.txt: some
-  [wdir] fail: error
+  [wdir] fail: error that did stop the tool
   $ cat hello.txt
   goodbye
+  $ cat foo.whole
+  FOO
 
   $ hg --config "fix.fail:command=exit 42" \
   >--config "fix.fail:fileset=hello.txt" \
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -19,9 +19,11 @@
 
 The :command suboption forms the first part of the shell command that will be
 used to fix a file. The content of the file is passed on standard input, and 
the
-fixed file content is expected on standard output. If there is any output on
-standard error, the file will not be affected. Some values may be substituted
-into the command::
+fixed file content 

D5226: fix: rename :fileset subconfig to :pattern

2018-11-05 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 12437.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5226?vs=12436=12437

REVISION DETAIL
  https://phab.mercurial-scm.org/D5226

AFFECTED FILES
  hgext/fix.py
  tests/test-fix-clang-format.t
  tests/test-fix-topology.t
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -66,10 +66,10 @@
   > evolution.allowunstable=True
   > [fix]
   > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY all
-  > uppercase-whole-file:fileset=set:**.whole
+  > uppercase-whole-file:pattern=set:**.whole
   > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY
   > uppercase-changed-lines:linerange={first}-{last}
-  > uppercase-changed-lines:fileset=set:**.changed
+  > uppercase-changed-lines:pattern=set:**.changed
   > EOF
 
 Help text for fix.
@@ -126,7 +126,7 @@
 [fix]
 clang-format:command=clang-format --assume-filename={rootpath}
 clang-format:linerange=--lines={first}:{last}
-clang-format:fileset=set:**.cpp or **.hpp
+clang-format:pattern=set:**.cpp or **.hpp
   
   The :command suboption forms the first part of the shell command that will be
   used to fix a file. The content of the file is passed on standard input, and
@@ -147,9 +147,9 @@
 {first}   The 1-based line number of the first line in the modified range
 {last}The 1-based line number of the last line in the modified range
   
-  The :fileset suboption determines which files will be passed through each
-  configured tool. See 'hg help fileset' for possible values. If there are file
-  arguments to 'hg fix', the intersection of these filesets is used.
+  The :pattern suboption determines which files will be passed through each
+  configured tool. See 'hg help patterns' for possible values. If there are 
file
+  arguments to 'hg fix', the intersection of these patterns is used.
   
   There is also a configurable limit for the maximum size of file that will be
   processed by 'hg fix':
@@ -371,7 +371,7 @@
 
   $ hg --config "fix.fail:command=echo" \
   >--config "fix.fail:linerange={first}:{last}" \
-  >--config "fix.fail:fileset=foo.txt" \
+  >--config "fix.fail:pattern=foo.txt" \
   >fix --working-dir
   $ cat foo.txt
   1:1 4:6 8:8
@@ -534,7 +534,7 @@
   > exit 0 # success despite the stderr output
   > EOF
   $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \
-  >--config "fix.work:fileset=hello.txt" \
+  >--config "fix.work:pattern=hello.txt" \
   >fix --working-dir
   [wdir] work: hello.txt: some
   [wdir] work: error that didn't stop the tool
@@ -551,7 +551,7 @@
   > exit 42 # success despite the stdout output
   > EOF
   $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >--config "fix.failure=abort" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
@@ -565,7 +565,7 @@
   foo
 
   $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
   [wdir] fail: error that did stop the tool
@@ -575,7 +575,7 @@
   FOO
 
   $ hg --config "fix.fail:command=exit 42" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >fix --working-dir
   [wdir] fail: exited with status 42
 
@@ -1027,7 +1027,7 @@
   adding foo/bar
   $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \
   >--config "fix.fail:linerange='{first}' '{last}'" \
-  >--config "fix.fail:fileset=foo/bar" \
+  >--config "fix.fail:pattern=foo/bar" \
   >fix --working-dir
   $ cat foo/bar
   foo/bar
@@ -1105,3 +1105,25 @@
   FOO2
 
   $ cd ..
+
+The :fileset subconfig was a misnomer, so we renamed it to :pattern. We will
+still accept :fileset by itself as if it were :pattern, but this will issue a
+warning.
+
+  $ hg init filesetispattern
+  $ cd filesetispattern
+
+  $ printf "foo\n" > foo.whole
+  $ printf "first\nsecond\n" > bar.txt
+  $ hg add -q
+  $ hg fix -w --config fix.sometool:fileset=bar.txt \
+  >   --config fix.sometool:command=tac
+  the fix.tool:fileset config name is deprecated; please rename it to 
fix.tool:pattern
+
+  $ cat foo.whole
+  FOO
+  $ cat bar.txt
+  second
+  first
+
+  $ cd ..
diff --git a/tests/test-fix-topology.t b/tests/test-fix-topology.t
--- a/tests/test-fix-topology.t
+++ b/tests/test-fix-topology.t
@@ -23,7 +23,7 @@
   > fix =
   > [fix]
   > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY
-  > uppercase-whole-file:fileset=set:**
+  > uppercase-whole-file:pattern=set:**
   > EOF
 
 This tests the only behavior that should really be affected by obsolescence, so
diff --git a/tests/test-fix-clang-format.t b/tests/test-fix-clang-format.t
--- 

D5226: fix: rename :fileset subconfig to :pattern

2018-11-05 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This name was always inaccurate, since the config accepts any pattern.
  Hopefully so few people use this right now that it won't matter, but there 
will
  now be a warning if the old config name is used.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5226

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -66,10 +66,10 @@
   > evolution.allowunstable=True
   > [fix]
   > uppercase-whole-file:command="$PYTHON" $UPPERCASEPY all
-  > uppercase-whole-file:fileset=set:**.whole
+  > uppercase-whole-file:pattern=set:**.whole
   > uppercase-changed-lines:command="$PYTHON" $UPPERCASEPY
   > uppercase-changed-lines:linerange={first}-{last}
-  > uppercase-changed-lines:fileset=set:**.changed
+  > uppercase-changed-lines:pattern=set:**.changed
   > EOF
 
 Help text for fix.
@@ -126,7 +126,7 @@
 [fix]
 clang-format:command=clang-format --assume-filename={rootpath}
 clang-format:linerange=--lines={first}:{last}
-clang-format:fileset=set:**.cpp or **.hpp
+clang-format:pattern=set:**.cpp or **.hpp
   
   The :command suboption forms the first part of the shell command that will be
   used to fix a file. The content of the file is passed on standard input, and
@@ -147,9 +147,9 @@
 {first}   The 1-based line number of the first line in the modified range
 {last}The 1-based line number of the last line in the modified range
   
-  The :fileset suboption determines which files will be passed through each
-  configured tool. See 'hg help fileset' for possible values. If there are file
-  arguments to 'hg fix', the intersection of these filesets is used.
+  The :pattern suboption determines which files will be passed through each
+  configured tool. See 'hg help patterns' for possible values. If there are 
file
+  arguments to 'hg fix', the intersection of these patterns is used.
   
   There is also a configurable limit for the maximum size of file that will be
   processed by 'hg fix':
@@ -371,7 +371,7 @@
 
   $ hg --config "fix.fail:command=echo" \
   >--config "fix.fail:linerange={first}:{last}" \
-  >--config "fix.fail:fileset=foo.txt" \
+  >--config "fix.fail:pattern=foo.txt" \
   >fix --working-dir
   $ cat foo.txt
   1:1 4:6 8:8
@@ -534,7 +534,7 @@
   > exit 0 # success despite the stderr output
   > EOF
   $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \
-  >--config "fix.work:fileset=hello.txt" \
+  >--config "fix.work:pattern=hello.txt" \
   >fix --working-dir
   [wdir] work: hello.txt: some
   [wdir] work: error that didn't stop the tool
@@ -551,7 +551,7 @@
   > exit 42 # success despite the stdout output
   > EOF
   $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >--config "fix.failure=abort" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
@@ -565,7 +565,7 @@
   foo
 
   $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
   [wdir] fail: error that did stop the tool
@@ -575,7 +575,7 @@
   FOO
 
   $ hg --config "fix.fail:command=exit 42" \
-  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.fail:pattern=hello.txt" \
   >fix --working-dir
   [wdir] fail: exited with status 42
 
@@ -1027,7 +1027,7 @@
   adding foo/bar
   $ hg --config "fix.fail:command=printf '%s\n' '{rootpath}' '{basename}'" \
   >--config "fix.fail:linerange='{first}' '{last}'" \
-  >--config "fix.fail:fileset=foo/bar" \
+  >--config "fix.fail:pattern=foo/bar" \
   >fix --working-dir
   $ cat foo/bar
   foo/bar
@@ -1105,3 +1105,25 @@
   FOO2
 
   $ cd ..
+
+The :fileset subconfig was a misnomer, so we renamed it to :pattern. We will
+still accept :fileset by itself as if it were :pattern, but this will issue a
+warning.
+
+  $ hg init filesetispattern
+  $ cd filesetispattern
+
+  $ printf "foo\n" > foo.whole
+  $ printf "first\nsecond\n" > bar.txt
+  $ hg add -q
+  $ hg fix -w --config fix.sometool:fileset=bar.txt \
+  >   --config fix.sometool:command=tac
+  the fix.fileset config name is deprecated; please rename it to fix.pattern
+
+  $ cat foo.whole
+  FOO
+  $ cat bar.txt
+  second
+  first
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -15,7 +15,7 @@
   [fix]
   clang-format:command=clang-format --assume-filename={rootpath}
   clang-format:linerange=--lines={first}:{last}
-  clang-format:fileset=set:**.cpp or **.hpp
+  clang-format:pattern=set:**.cpp or **.hpp
 
 The :command suboption forms the first 

D5200: fix: add a config to abort when a fixer tool fails

2018-11-05 Thread hooper (Danny Hooper)
hooper added a comment.


  In https://phab.mercurial-scm.org/D5200#77865, @yuja wrote:
  
  > Looks good, but test-check-config.t failed probably because the doc couldn't
  >  be found by the checker.
  
  
  Looks like it's picky about whitespace.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5200

To: hooper, #hg-reviewers
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5200: fix: add a config to abort when a fixer tool fails

2018-11-05 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 12435.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5200?vs=12355=12435

REVISION DETAIL
  https://phab.mercurial-scm.org/D5200

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -130,9 +130,11 @@
   
   The :command suboption forms the first part of the shell command that will be
   used to fix a file. The content of the file is passed on standard input, and
-  the fixed file content is expected on standard output. If there is any output
-  on standard error, the file will not be affected. Some values may be
-  substituted into the command:
+  the fixed file content is expected on standard output. Any output on standard
+  error will be displayed as a warning. If the exit status is not zero, the 
file
+  will not be affected. A placeholder warning is displayed if there is a non-
+  zero exit status but no standard error output. Some values may be substituted
+  into the command:
   
 {rootpath}  The path of the file being fixed, relative to the repo root
 {basename}  The name of the file being fixed, without the directory path
@@ -153,7 +155,15 @@
   processed by 'hg fix':
   
 [fix]
-maxfilesize=2MB
+maxfilesize = 2MB
+  
+  Normally, execution of configured tools will continue after a failure
+  (indicated by a non-zero exit status). It can also be configured to abort
+  after the first such failure, so that no files will be affected if any tool
+  fails. This abort will also cause 'hg fix' to exit with a non-zero status:
+  
+[fix]
+failure = abort
   
   list of commands:
   
@@ -508,40 +518,61 @@
 on stderr and nothing on stdout, which would cause us the clear the file,
 except that they also exit with a non-zero code. We show the user which fixer
 emitted the stderr, and which revision, but we assume that the fixer will print
-the filename if it is relevant (since the issue may be non-specific).
+the filename if it is relevant (since the issue may be non-specific). There is
+also a config to abort (without affecting any files whatsoever) if we see any
+tool with a non-zero exit status.
 
   $ hg init showstderr
   $ cd showstderr
 
   $ printf "hello\n" > hello.txt
   $ hg add
   adding hello.txt
-  $ cat > $TESTTMP/fail.sh <<'EOF'
+  $ cat > $TESTTMP/work.sh <<'EOF'
   > printf 'HELLO\n'
-  > printf "$@: some\nerror" >&2
+  > printf "$@: some\nerror that didn't stop the tool" >&2
   > exit 0 # success despite the stderr output
   > EOF
+  $ hg --config "fix.work:command=sh $TESTTMP/work.sh {rootpath}" \
+  >--config "fix.work:fileset=hello.txt" \
+  >fix --working-dir
+  [wdir] work: hello.txt: some
+  [wdir] work: error that didn't stop the tool
+  $ cat hello.txt
+  HELLO
+
+  $ printf "goodbye\n" > hello.txt
+  $ printf "foo\n" > foo.whole
+  $ hg add
+  adding foo.whole
+  $ cat > $TESTTMP/fail.sh <<'EOF'
+  > printf 'GOODBYE\n'
+  > printf "$@: some\nerror that did stop the tool\n" >&2
+  > exit 42 # success despite the stdout output
+  > EOF
+  $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
+  >--config "fix.fail:fileset=hello.txt" \
+  >--config "fix.failure=abort" \
+  >fix --working-dir
+  [wdir] fail: hello.txt: some
+  [wdir] fail: error that did stop the tool
+  abort: no fixes will be applied
+  (use --config fix.failure=continue to apply any successful fixes anyway)
+  [255]
+  $ cat hello.txt
+  goodbye
+  $ cat foo.whole
+  foo
+
   $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
   >--config "fix.fail:fileset=hello.txt" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
-  [wdir] fail: error
-  $ cat hello.txt
-  HELLO
-
-  $ printf "goodbye\n" > hello.txt
-  $ cat > $TESTTMP/work.sh <<'EOF'
-  > printf 'GOODBYE\n'
-  > printf "$@: some\nerror\n" >&2
-  > exit 42 # success despite the stdout output
-  > EOF
-  $ hg --config "fix.fail:command=sh $TESTTMP/work.sh {rootpath}" \
-  >--config "fix.fail:fileset=hello.txt" \
-  >fix --working-dir
-  [wdir] fail: hello.txt: some
-  [wdir] fail: error
+  [wdir] fail: error that did stop the tool
   $ cat hello.txt
   goodbye
+  $ cat foo.whole
+  FOO
 
   $ hg --config "fix.fail:command=exit 42" \
   >--config "fix.fail:fileset=hello.txt" \
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -19,9 +19,11 @@
 
 The :command suboption forms the first part of the shell command that will be
 used to fix a file. The content of the file is passed on standard input, and 
the
-fixed file content is expected on standard output. If there is any output on
-standard error, the file will not be affected. Some values may be substituted
-into the command::
+fixed file content is expected on standard output. Any output on standard error
+will be displayed as a warning. If the exit status is not zero, the file will
+not be 

D5103: beautifygraph: don't substitute anything for 'X' in rendered graphs

2018-10-31 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGc2a0bc6412db: beautifygraph: dont substitute anything 
for X in rendered graphs (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5103?vs=12131=12352

REVISION DETAIL
  https://phab.mercurial-scm.org/D5103

AFFECTED FILES
  hgext/beautifygraph.py

CHANGE DETAILS

diff --git a/hgext/beautifygraph.py b/hgext/beautifygraph.py
--- a/hgext/beautifygraph.py
+++ b/hgext/beautifygraph.py
@@ -31,8 +31,6 @@
 def prettyedge(before, edge, after):
 if edge == '~':
 return '\xE2\x95\xA7' # U+2567 ╧
-if edge == 'X':
-return '\xE2\x95\xB3' # U+2573 ╳
 if edge == '/':
 return '\xE2\x95\xB1' # U+2571 ╱
 if edge == '-':



To: hooper, #hg-reviewers, martinvonz
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5102: beautifygraph: add configs for customizing the characters

2018-10-30 Thread hooper (Danny Hooper)
hooper added a comment.


  I'll elaborate a bit. I think the idea of using unicode to make the graph 
good looking is flawed. There are no characters that properly serve common 
cases like this:
  
o
|
 \
  o
  
  That's part of why there was some disagreement in early discussion of this 
extension.
  
  I think it's a bad user experience, because if the graph looks 95% like a 
connected drawing, these broken areas are going to look like malfunctions 
(whereas we started with a stylized ascii drawing where the limitations are 
obvious to the user).
  
  Additionally, the existing graphlog output is lossy. The two pipes in this 
example do not have the same meaning:
  
o
|
|
 \
   o
  
  Even if we had the unicode characters/custom font needed to make this work, 
we would need at least 5 configurable variants of what is currently just a 
pipe. You would need hundreds of distinct characters to support all 
combinations of the 8 horizontal and diagonal edges in each character/cell of 
the graph rendering. More than double that to support dashed lines. Maybe 
exclude some unused characters. It's hard to imagine making that easy to 
configure.
  
  You can also imagine having the graphlog output optionally use only 
horizontal/vertical edges so this can be done properly with box drawing 
characters. This is would complicate graphlog itself considerably, regardless 
of configuration.
  
  Meanwhile, this patch would be useful to some of our users, and it keeps the 
problems contained within the extension.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5102

To: hooper, #hg-reviewers
Cc: spectral, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5102: beautifygraph: add configs for customizing the characters

2018-10-14 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 12138.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5102?vs=12130=12138

REVISION DETAIL
  https://phab.mercurial-scm.org/D5102

AFFECTED FILES
  hgext/beautifygraph.py
  tests/test-glog-beautifygraph.t

CHANGE DETAILS

diff --git a/tests/test-glog-beautifygraph.t b/tests/test-glog-beautifygraph.t
--- a/tests/test-glog-beautifygraph.t
+++ b/tests/test-glog-beautifygraph.t
@@ -1,3 +1,29 @@
+  $ hg help beautifygraph
+  beautifygraph extension - beautify log -G output by using Unicode characters
+  (EXPERIMENTAL)
+  
+ A terminal with UTF-8 support and monospace narrow text are required.
+  
+ The character substitutions used in the graph can be customized with
+ variables in the [beautifygraph] section:
+  
+/   ``beautifygraph.edge.diagonal1``
+\   ``beautifygraph.edge.diagonal2``
+-   ``beautifygraph.edge.horizontal``
+|   ``beautifygraph.edge.vertical``
+:   ``beautifygraph.edge.verticaldotted``
+   -+-  ``beautifygraph.edge.cross``
+   -+   ``beautifygraph.edge.verticalleft``
++-  ``beautifygraph.edge.verticalright``
+~   ``beautifygraph.edge.verticalstop``
+_   ``beautifygraph.node.closesbranch``
+@   ``beautifygraph.node.current``
+x   ``beautifygraph.node.obsolete``
+o   ``beautifygraph.node.other``
+*   ``beautifygraph.node.unstable``
+  
+  (use 'hg help extensions' for information on enabling extensions)
+
 @  (34) head
 |
 | o  (33) head
@@ -3112,3 +3138,84 @@
   
 
   $ cd ..
+
+Construct a magical repo whose ascii graph log contains all the possible 
symbols.
+
+  $ hg init configuration
+  $ cd configuration
+
+  $ touch file0
+  $ hg commit -Aqm revision0
+  $ touch file1
+  $ hg commit -Aqm revision1
+  $ touch file2
+  $ hg commit -Aqm revision2
+  $ touch file3
+  $ hg commit -Aqm revision3
+  $ hg update -q null
+  $ touch file4
+  $ hg commit -Aqm revision4
+  $ hg update -q 3
+  $ hg merge -q 4
+  $ touch file5
+  $ hg commit -Aqm revision5
+  $ hg update -q null
+  $ touch file6
+  $ hg branch -q foo
+  $ hg commit -Aqm revision6
+  $ hg merge -q 3
+  $ touch file7
+  $ hg commit -Aqm revision7 --close-branch
+  $ hg update -q 4
+  $ hg merge -q 3
+  $ touch file8
+  $ hg commit -Aqm revision8
+  $ hg update -q 6
+  $ hg merge -q 5
+  $ touch file9
+  $ hg commit -Aqm revision9
+  $ touch file10
+  $ hg commit -Aqm revision10
+  $ hg debugobsolete `hg log -r 9 -T '{node}'`
+  obsoleted 1 changesets
+  1 new orphan changesets
+  $ hg update -q 8
+
+All symbols should be configurable.
+
+  $ hg log -G -q -r '(1:)-2' \
+  > --config beautifygraph.edge.diagonal1=a \
+  > --config beautifygraph.edge.diagonal2=b \
+  > --config beautifygraph.edge.cross=c \
+  > --config beautifygraph.edge.horizontal=d \
+  > --config beautifygraph.edge.vertical=e \
+  > --config beautifygraph.edge.verticaldotted=f \
+  > --config beautifygraph.edge.verticalleft=g \
+  > --config beautifygraph.edge.verticalright=h \
+  > --config beautifygraph.edge.verticalstop=i \
+  > --config beautifygraph.node.closesbranch=j \
+  > --config beautifygraph.node.current=ï“Ž \
+  > --config beautifygraph.node.obsolete=l \
+  > --config beautifygraph.node.other=m \
+  > --config beautifygraph.node.unstable=n
+  n  10:3bf4adf1e513
+  e
+  l9:a4d281932d8a
+  eb
+  e e ï“Ž  8:b9029cea3597 (esc)
+  e e eb
+  e hdcdddj  7:12cd82bb4409
+  e e e e
+  e m e e  6:11bb041c7deb
+  e  a a
+  mdddg  5:0b61ae539b30
+  ea a
+  e m  4:f2e786cf2f3d
+  e
+  m  3:561d8244024e
+  f
+  m  1:388ecb15405b
+  e
+  i
+
+  $ cd ..
diff --git a/hgext/beautifygraph.py b/hgext/beautifygraph.py
--- a/hgext/beautifygraph.py
+++ b/hgext/beautifygraph.py
@@ -9,6 +9,24 @@
 '''beautify log -G output by using Unicode characters (EXPERIMENTAL)
 
A terminal with UTF-8 support and monospace narrow text are required.
+
+   The character substitutions used in the graph can be customized with
+   variables in the [beautifygraph] section::
+
+/   ``beautifygraph.edge.diagonal1``
+\   ``beautifygraph.edge.diagonal2``
+-   ``beautifygraph.edge.horizontal``
+|   ``beautifygraph.edge.vertical``
+:   ``beautifygraph.edge.verticaldotted``
+   -+-  ``beautifygraph.edge.cross``
+   -+   ``beautifygraph.edge.verticalleft``
++-  ``beautifygraph.edge.verticalright``
+~   ``beautifygraph.edge.verticalstop``
+_   ``beautifygraph.node.closesbranch``
+@   ``beautifygraph.node.current``
+x   ``beautifygraph.node.obsolete``
+o   ``beautifygraph.node.other``
+*   ``beautifygraph.node.unstable``
 '''
 
 from __future__ import absolute_import
@@ -19,6 +37,7 @@
 extensions,
 graphmod,
 pycompat,
+registrar,
 templatekw,
 )
 
@@ -28,53 +47,69 @@
 # leave the attribute unspecified.
 testedwith = 'ships-with-hg-core'
 
-def prettyedge(before, edge, after):
-if edge == 

D5102: beautifygraph: add configs for customizing the characters

2018-10-14 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  I figure we should keep this out of graphmod.py and templatekw.py for now.
  Moving the extension functionality out of hgext is a separate issue.
  
  Calling ui.config() inside getgraphnode seems like it might slow things down,
  but it needs to happen there because of the template keyword. We probably want
  to honor config overrides, so we can't cache glyphs at this level.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5102

AFFECTED FILES
  hgext/beautifygraph.py
  tests/test-glog-beautifygraph.t

CHANGE DETAILS

diff --git a/tests/test-glog-beautifygraph.t b/tests/test-glog-beautifygraph.t
--- a/tests/test-glog-beautifygraph.t
+++ b/tests/test-glog-beautifygraph.t
@@ -1,3 +1,29 @@
+  $ hg help beautifygraph
+  beautifygraph extension - beautify log -G output by using Unicode characters
+  (EXPERIMENTAL)
+  
+ A terminal with UTF-8 support and monospace narrow text are required.
+  
+ The character substitutions used in the graph can be customized with
+ variables in the [beautifygraph] section:
+  
+/   ``beautifygraph.edge.diagonal1``
+\   ``beautifygraph.edge.diagonal2``
+-   ``beautifygraph.edge.horizontal``
+|   ``beautifygraph.edge.vertical``
+:   ``beautifygraph.edge.verticaldotted``
+   -+-  ``beautifygraph.edge.cross``
+   -+   ``beautifygraph.edge.verticalleft``
++-  ``beautifygraph.edge.verticalright``
+~   ``beautifygraph.edge.verticalstop``
+_   ``beautifygraph.node.closesbranch``
+@   ``beautifygraph.node.current``
+x   ``beautifygraph.node.obsolete``
+o   ``beautifygraph.node.other``
+*   ``beautifygraph.node.unstable``
+  
+  (use 'hg help extensions' for information on enabling extensions)
+
 @  (34) head
 |
 | o  (33) head
@@ -3112,3 +3138,84 @@
   
 
   $ cd ..
+
+Construct a magical repo whose ascii graph log contains all the possible 
symbols.
+
+  $ hg init configuration
+  $ cd configuration
+
+  $ touch file0
+  $ hg commit -Aqm revision0
+  $ touch file1
+  $ hg commit -Aqm revision1
+  $ touch file2
+  $ hg commit -Aqm revision2
+  $ touch file3
+  $ hg commit -Aqm revision3
+  $ hg update -q null
+  $ touch file4
+  $ hg commit -Aqm revision4
+  $ hg update -q 3
+  $ hg merge -q 4
+  $ touch file5
+  $ hg commit -Aqm revision5
+  $ hg update -q null
+  $ touch file6
+  $ hg branch -q foo
+  $ hg commit -Aqm revision6
+  $ hg merge -q 3
+  $ touch file7
+  $ hg commit -Aqm revision7 --close-branch
+  $ hg update -q 4
+  $ hg merge -q 3
+  $ touch file8
+  $ hg commit -Aqm revision8
+  $ hg update -q 6
+  $ hg merge -q 5
+  $ touch file9
+  $ hg commit -Aqm revision9
+  $ touch file10
+  $ hg commit -Aqm revision10
+  $ hg debugobsolete $(hg log -r 9 -T '{node}')
+  obsoleted 1 changesets
+  1 new orphan changesets
+  $ hg update -q 8
+
+All symbols should be configurable.
+
+  $ hg log -G -q -r '(1:)-2' \
+  > --config beautifygraph.edge.diagonal1=a \
+  > --config beautifygraph.edge.diagonal2=b \
+  > --config beautifygraph.edge.cross=c \
+  > --config beautifygraph.edge.horizontal=d \
+  > --config beautifygraph.edge.vertical=e \
+  > --config beautifygraph.edge.verticaldotted=f \
+  > --config beautifygraph.edge.verticalleft=g \
+  > --config beautifygraph.edge.verticalright=h \
+  > --config beautifygraph.edge.verticalstop=i \
+  > --config beautifygraph.node.closesbranch=j \
+  > --config beautifygraph.node.current=ï“Ž \
+  > --config beautifygraph.node.obsolete=l \
+  > --config beautifygraph.node.other=m \
+  > --config beautifygraph.node.unstable=n
+  n  10:3bf4adf1e513
+  e
+  l9:a4d281932d8a
+  eb
+  e e ï“Ž  8:b9029cea3597 (esc)
+  e e eb
+  e hdcdddj  7:12cd82bb4409
+  e e e e
+  e m e e  6:11bb041c7deb
+  e  a a
+  mdddg  5:0b61ae539b30
+  ea a
+  e m  4:f2e786cf2f3d
+  e
+  m  3:561d8244024e
+  f
+  m  1:388ecb15405b
+  e
+  i
+
+  $ cd ..
diff --git a/hgext/beautifygraph.py b/hgext/beautifygraph.py
--- a/hgext/beautifygraph.py
+++ b/hgext/beautifygraph.py
@@ -9,6 +9,24 @@
 '''beautify log -G output by using Unicode characters (EXPERIMENTAL)
 
A terminal with UTF-8 support and monospace narrow text are required.
+
+   The character substitutions used in the graph can be customized with
+   variables in the [beautifygraph] section::
+
+/   ``beautifygraph.edge.diagonal1``
+\   ``beautifygraph.edge.diagonal2``
+-   ``beautifygraph.edge.horizontal``
+|   ``beautifygraph.edge.vertical``
+:   ``beautifygraph.edge.verticaldotted``
+   -+-  ``beautifygraph.edge.cross``
+   -+   ``beautifygraph.edge.verticalleft``
++-  ``beautifygraph.edge.verticalright``
+~   ``beautifygraph.edge.verticalstop``
+_   ``beautifygraph.node.closesbranch``
+@   ``beautifygraph.node.current``
+x   

D5103: beautifygraph: don't substitute anything for 'X' in rendered graphs

2018-10-14 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  It looks like we never actually render graphs this way, although there's an
  example in a comment next to the code that prevents it from being needed (see
  graphmod.ascii()).

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D5103

AFFECTED FILES
  hgext/beautifygraph.py

CHANGE DETAILS

diff --git a/hgext/beautifygraph.py b/hgext/beautifygraph.py
--- a/hgext/beautifygraph.py
+++ b/hgext/beautifygraph.py
@@ -31,8 +31,6 @@
 def prettyedge(before, edge, after):
 if edge == '~':
 return '\xE2\x95\xA7' # U+2567 ╧
-if edge == 'X':
-return '\xE2\x95\xB3' # U+2573 ╳
 if edge == '/':
 return '\xE2\x95\xB1' # U+2571 ╱
 if edge == '-':



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4158: fix: determine fixer tool failure by exit code instead of stderr

2018-08-09 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGa009589cd32a: fix: determine fixer tool failure by exit 
code instead of stderr (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4158?vs=10078=10130

REVISION DETAIL
  https://phab.mercurial-scm.org/D4158

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -502,30 +502,51 @@
 
   $ cd ..
 
-When a fixer prints to stderr, we assume that it has failed. We should show the
-error messages to the user, and we should not let the failing fixer affect the
-file it was fixing (many code formatters might emit error messages on stderr
-and nothing on stdout, which would cause us the clear the file). We show the
-user which fixer failed and which revision, but we assume that the fixer will
-print the filename if it is relevant.
+When a fixer prints to stderr, we don't assume that it has failed. We show the
+error messages to the user, and we still let the fixer affect the file it was
+fixing if its exit code is zero. Some code formatters might emit error messages
+on stderr and nothing on stdout, which would cause us the clear the file,
+except that they also exit with a non-zero code. We show the user which fixer
+emitted the stderr, and which revision, but we assume that the fixer will print
+the filename if it is relevant (since the issue may be non-specific).
 
   $ hg init showstderr
   $ cd showstderr
 
   $ printf "hello\n" > hello.txt
   $ hg add
   adding hello.txt
-  $ cat >> $TESTTMP/cmd.sh <<'EOF'
+  $ cat > $TESTTMP/fail.sh <<'EOF'
   > printf 'HELLO\n'
   > printf "$@: some\nerror" >&2
+  > exit 0 # success despite the stderr output
   > EOF
-  $ hg --config "fix.fail:command=sh $TESTTMP/cmd.sh {rootpath}" \
+  $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
   >--config "fix.fail:fileset=hello.txt" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
   [wdir] fail: error
   $ cat hello.txt
-  hello
+  HELLO
+
+  $ printf "goodbye\n" > hello.txt
+  $ cat > $TESTTMP/work.sh <<'EOF'
+  > printf 'GOODBYE\n'
+  > printf "$@: some\nerror\n" >&2
+  > exit 42 # success despite the stdout output
+  > EOF
+  $ hg --config "fix.fail:command=sh $TESTTMP/work.sh {rootpath}" \
+  >--config "fix.fail:fileset=hello.txt" \
+  >fix --working-dir
+  [wdir] fail: hello.txt: some
+  [wdir] fail: error
+  $ cat hello.txt
+  goodbye
+
+  $ hg --config "fix.fail:command=exit 42" \
+  >--config "fix.fail:fileset=hello.txt" \
+  >fix --working-dir
+  [wdir] fail: exited with status 42
 
   $ cd ..
 
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -435,6 +435,9 @@
 starting with the file's content in the fixctx. Fixers that support line
 ranges will affect lines that have changed relative to any of the basectxs
 (i.e. they will only avoid lines that are common to all basectxs).
+
+A fixer tool's stdout will become the file's new content if and only if it
+exits with code zero.
 """
 newdata = fixctx[path].data()
 for fixername, fixer in fixers.iteritems():
@@ -454,8 +457,11 @@
 newerdata, stderr = proc.communicate(newdata)
 if stderr:
 showstderr(ui, fixctx.rev(), fixername, stderr)
-else:
+if proc.returncode == 0:
 newdata = newerdata
+elif not stderr:
+showstderr(ui, fixctx.rev(), fixername,
+   _('exited with status %d\n') % (proc.returncode,))
 return newdata
 
 def showstderr(ui, rev, fixername, stderr):



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4158: fix: determine fixer tool failure by exit code instead of stderr

2018-08-08 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This seems like the more natural thing, and it probably should have been this
  way to beign with. It is more flexible because it allows tools to emit
  diagnostic information while also modifying a file. An example would be an
  automatic code formatter that also prints any remaining lint issues.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D4158

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -502,30 +502,51 @@
 
   $ cd ..
 
-When a fixer prints to stderr, we assume that it has failed. We should show the
-error messages to the user, and we should not let the failing fixer affect the
-file it was fixing (many code formatters might emit error messages on stderr
-and nothing on stdout, which would cause us the clear the file). We show the
-user which fixer failed and which revision, but we assume that the fixer will
-print the filename if it is relevant.
+When a fixer prints to stderr, we don't assume that it has failed. We show the
+error messages to the user, and we still let the fixer affect the file it was
+fixing if its exit code is zero. Some code formatters might emit error messages
+on stderr and nothing on stdout, which would cause us the clear the file,
+except that they also exit with a non-zero code. We show the user which fixer
+emitted the stderr, and which revision, but we assume that the fixer will print
+the filename if it is relevant (since the issue may be non-specific).
 
   $ hg init showstderr
   $ cd showstderr
 
   $ printf "hello\n" > hello.txt
   $ hg add
   adding hello.txt
-  $ cat >> $TESTTMP/cmd.sh <<'EOF'
+  $ cat > $TESTTMP/fail.sh <<'EOF'
   > printf 'HELLO\n'
   > printf "$@: some\nerror" >&2
+  > exit 0 # success despite the stderr output
   > EOF
-  $ hg --config "fix.fail:command=sh $TESTTMP/cmd.sh {rootpath}" \
+  $ hg --config "fix.fail:command=sh $TESTTMP/fail.sh {rootpath}" \
   >--config "fix.fail:fileset=hello.txt" \
   >fix --working-dir
   [wdir] fail: hello.txt: some
   [wdir] fail: error
   $ cat hello.txt
-  hello
+  HELLO
+
+  $ printf "goodbye\n" > hello.txt
+  $ cat > $TESTTMP/work.sh <<'EOF'
+  > printf 'GOODBYE\n'
+  > printf "$@: some\nerror\n" >&2
+  > exit 42 # success despite the stdout output
+  > EOF
+  $ hg --config "fix.fail:command=sh $TESTTMP/work.sh {rootpath}" \
+  >--config "fix.fail:fileset=hello.txt" \
+  >fix --working-dir
+  [wdir] fail: hello.txt: some
+  [wdir] fail: error
+  $ cat hello.txt
+  goodbye
+
+  $ hg --config "fix.fail:command=exit 42" \
+  >--config "fix.fail:fileset=hello.txt" \
+  >fix --working-dir
+  [wdir] fail: exited with status 42
 
   $ cd ..
 
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -435,6 +435,9 @@
 starting with the file's content in the fixctx. Fixers that support line
 ranges will affect lines that have changed relative to any of the basectxs
 (i.e. they will only avoid lines that are common to all basectxs).
+
+A fixer tool's stdout will become the file's new content if and only if it
+exits with code zero.
 """
 newdata = fixctx[path].data()
 for fixername, fixer in fixers.iteritems():
@@ -454,8 +457,11 @@
 newerdata, stderr = proc.communicate(newdata)
 if stderr:
 showstderr(ui, fixctx.rev(), fixername, stderr)
-else:
+if proc.returncode == 0:
 newdata = newerdata
+elif not stderr:
+showstderr(ui, fixctx.rev(), fixername,
+   _('exited with status %d\n') % (proc.returncode,))
 return newdata
 
 def showstderr(ui, rev, fixername, stderr):



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4146: fix: correctly set wdirwritten given that the dict item is deleted

2018-08-08 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG35bc4b6e132d: fix: correctly set wdirwritten given that the 
dict item is deleted (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4146?vs=10021=10071

REVISION DETAIL
  https://phab.mercurial-scm.org/D4146

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -162,6 +162,7 @@
 # it makes the results more easily reproducible.
 filedata = collections.defaultdict(dict)
 replacements = {}
+wdirwritten = False
 commitorder = sorted(revstofix, reverse=True)
 with ui.makeprogress(topic=_('fixing'), unit=_('files'),
  total=sum(numitems.values())) as progress:
@@ -179,11 +180,12 @@
 ctx = repo[rev]
 if rev == wdirrev:
 writeworkingdir(repo, ctx, filedata[rev], replacements)
+wdirwritten = bool(filedata[rev])
 else:
 replacerev(ui, repo, ctx, filedata[rev], replacements)
 del filedata[rev]
 
-cleanup(repo, replacements, bool(filedata[wdirrev]))
+cleanup(repo, replacements, wdirwritten)
 
 def cleanup(repo, replacements, wdirwritten):
 """Calls scmutil.cleanupnodes() with the given replacements.



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4145: fix: pull out flag definitions to make them re-usable from extensions

2018-08-08 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGb0c591950e51: fix: pull out flag definitions to make them 
re-usable from extensions (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4145?vs=10020=10069

REVISION DETAIL
  https://phab.mercurial-scm.org/D4145

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -96,15 +96,16 @@
 # user.
 configitem('fix', 'maxfilesize', default='2MB')
 
-@command('fix',
-[('', 'all', False, _('fix all non-public non-obsolete revisions')),
- ('', 'base', [], _('revisions to diff against (overrides automatic '
-'selection, and applies to every revision being '
-'fixed)'), _('REV')),
- ('r', 'rev', [], _('revisions to fix'), _('REV')),
- ('w', 'working-dir', False, _('fix the working directory')),
- ('', 'whole', False, _('always fix every line of a file'))],
-_('[OPTION]... [FILE]...'))
+allopt = ('', 'all', False, _('fix all non-public non-obsolete revisions'))
+baseopt = ('', 'base', [], _('revisions to diff against (overrides automatic '
+ 'selection, and applies to every revision being '
+ 'fixed)'), _('REV'))
+revopt = ('r', 'rev', [], _('revisions to fix'), _('REV'))
+wdiropt = ('w', 'working-dir', False, _('fix the working directory'))
+wholeopt = ('', 'whole', False, _('always fix every line of a file'))
+usage = _('[OPTION]... [FILE]...')
+
+@command('fix', [allopt, baseopt, revopt, wdiropt, wholeopt], usage)
 def fix(ui, repo, *pats, **opts):
 """rewrite file content in changesets or working directory
 



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4146: fix: correctly set wdirwritten given that the dict item is deleted

2018-08-06 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D4146

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -162,6 +162,7 @@
 # it makes the results more easily reproducible.
 filedata = collections.defaultdict(dict)
 replacements = {}
+wdirwritten = False
 commitorder = sorted(revstofix, reverse=True)
 with ui.makeprogress(topic=_('fixing'), unit=_('files'),
  total=sum(numitems.values())) as progress:
@@ -179,11 +180,12 @@
 ctx = repo[rev]
 if rev == wdirrev:
 writeworkingdir(repo, ctx, filedata[rev], replacements)
+wdirwritten = bool(filedata[rev])
 else:
 replacerev(ui, repo, ctx, filedata[rev], replacements)
 del filedata[rev]
 
-cleanup(repo, replacements, bool(filedata[wdirrev]))
+cleanup(repo, replacements, wdirwritten)
 
 def cleanup(repo, replacements, wdirwritten):
 """Calls scmutil.cleanupnodes() with the given replacements.



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4145: fix: pull out flag definitions to make them re-usable from extensions

2018-08-06 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This makes it cleaner to implement fix-related commands with additional
  functionality while sharing some flags with the core implementation.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D4145

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -96,15 +96,16 @@
 # user.
 configitem('fix', 'maxfilesize', default='2MB')
 
-@command('fix',
-[('', 'all', False, _('fix all non-public non-obsolete revisions')),
- ('', 'base', [], _('revisions to diff against (overrides automatic '
-'selection, and applies to every revision being '
-'fixed)'), _('REV')),
- ('r', 'rev', [], _('revisions to fix'), _('REV')),
- ('w', 'working-dir', False, _('fix the working directory')),
- ('', 'whole', False, _('always fix every line of a file'))],
-_('[OPTION]... [FILE]...'))
+allopt = ('', 'all', False, _('fix all non-public non-obsolete revisions'))
+baseopt = ('', 'base', [], _('revisions to diff against (overrides automatic '
+ 'selection, and applies to every revision being '
+ 'fixed)'), _('REV'))
+revopt = ('r', 'rev', [], _('revisions to fix'), _('REV'))
+wdiropt = ('w', 'working-dir', False, _('fix the working directory'))
+wholeopt = ('', 'whole', False, _('always fix every line of a file'))
+usage = _('[OPTION]... [FILE]...')
+
+@command('fix', [allopt, baseopt, revopt, wdiropt, wholeopt], usage)
 def fix(ui, repo, *pats, **opts):
 """rewrite file content in changesets or working directory
 



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4100: fix: compute changed lines lazily to make whole-file fixer tools faster

2018-08-04 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG257c9846b532: fix: compute changed lines lazily to make 
whole-file fixer tools faster (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4100?vs=9867=9904

REVISION DETAIL
  https://phab.mercurial-scm.org/D4100

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -436,8 +436,8 @@
 newdata = fixctx[path].data()
 for fixername, fixer in fixers.iteritems():
 if fixer.affects(opts, fixctx, path):
-ranges = lineranges(opts, path, basectxs, fixctx, newdata)
-command = fixer.command(ui, path, ranges)
+rangesfn = lambda: lineranges(opts, path, basectxs, fixctx, 
newdata)
+command = fixer.command(ui, path, rangesfn)
 if command is None:
 continue
 ui.debug('subprocess: %s\n' % (command,))
@@ -582,7 +582,7 @@
 """Should this fixer run on the file at the given path and context?"""
 return scmutil.match(fixctx, [self._fileset], opts)(path)
 
-def command(self, ui, path, ranges):
+def command(self, ui, path, rangesfn):
 """A shell command to use to invoke this fixer on the given file/lines
 
 May return None if there is no appropriate command to run for the given
@@ -592,6 +592,7 @@
 parts = [expand(ui, self._command,
 {'rootpath': path, 'basename': 
os.path.basename(path)})]
 if self._linerange:
+ranges = rangesfn()
 if not ranges:
 # No line ranges to fix, so don't run the fixer.
 return None



To: hooper, #hg-reviewers, pulkit
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4100: fix: compute changed lines lazily to make whole-file fixer tools faster

2018-08-03 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D4100

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -436,8 +436,8 @@
 newdata = fixctx[path].data()
 for fixername, fixer in fixers.iteritems():
 if fixer.affects(opts, fixctx, path):
-ranges = lineranges(opts, path, basectxs, fixctx, newdata)
-command = fixer.command(ui, path, ranges)
+rangesfn = lambda: lineranges(opts, path, basectxs, fixctx, 
newdata)
+command = fixer.command(ui, path, rangesfn)
 if command is None:
 continue
 ui.debug('subprocess: %s\n' % (command,))
@@ -582,7 +582,7 @@
 """Should this fixer run on the file at the given path and context?"""
 return scmutil.match(fixctx, [self._fileset], opts)(path)
 
-def command(self, ui, path, ranges):
+def command(self, ui, path, rangesfn):
 """A shell command to use to invoke this fixer on the given file/lines
 
 May return None if there is no appropriate command to run for the given
@@ -592,6 +592,7 @@
 parts = [expand(ui, self._command,
 {'rootpath': path, 'basename': 
os.path.basename(path)})]
 if self._linerange:
+ranges = rangesfn()
 if not ranges:
 # No line ranges to fix, so don't run the fixer.
 return None



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4048: fix: add a monkey-patchable point after all new revisions have been committed

2018-08-03 Thread hooper (Danny Hooper)
hooper added inline comments.

INLINE COMMENTS

> pulkit wrote in fix.py:197
> If the output is not Google specific, we can have that here also under `hg 
> fix -v` or a config option.

Unfortunately, some of it is, though that might just mean we should template 
it. I think there's also some difficulty around verbosity levels if you don't 
want to see other modules' verbose output? At the very least I think "hg fix 
-q" should have no output if it succeeds.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D4048

To: hooper, #hg-reviewers, pulkit
Cc: pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4048: fix: add a monkey-patchable point after all new revisions have been committed

2018-08-02 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG64535d43c103: fix: add a monkey-patchable point after all 
new revisions have been committed (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4048?vs=9769=9813

REVISION DETAIL
  https://phab.mercurial-scm.org/D4048

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -182,8 +182,23 @@
 replacerev(ui, repo, ctx, filedata[rev], replacements)
 del filedata[rev]
 
-replacements = {prec: [succ] for prec, succ in 
replacements.iteritems()}
-scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
+cleanup(repo, replacements, bool(filedata[wdirrev]))
+
+def cleanup(repo, replacements, wdirwritten):
+"""Calls scmutil.cleanupnodes() with the given replacements.
+
+"replacements" is a dict from nodeid to nodeid, with one key and one value
+for every revision that was affected by fixing. This is slightly different
+from cleanupnodes().
+
+"wdirwritten" is a bool which tells whether the working copy was affected 
by
+fixing, since it has no entry in "replacements".
+
+Useful as a hook point for extending "hg fix" with output summarizing the
+effects of the command, though we choose not to output anything here.
+"""
+replacements = {prec: [succ] for prec, succ in replacements.iteritems()}
+scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
 
 def getworkqueue(ui, repo, pats, opts, revstofix, basectxs):
 Constructs the list of files to be fixed at specific revisions



To: hooper, #hg-reviewers, pulkit
Cc: pulkit, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4048: fix: add a monkey-patchable point after all new revisions have been committed

2018-08-01 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 9769.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D4048?vs=9768=9769

REVISION DETAIL
  https://phab.mercurial-scm.org/D4048

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -182,8 +182,23 @@
 replacerev(ui, repo, ctx, filedata[rev], replacements)
 del filedata[rev]
 
-replacements = {prec: [succ] for prec, succ in 
replacements.iteritems()}
-scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
+cleanup(repo, replacements, bool(filedata[wdirrev]))
+
+def cleanup(repo, replacements, wdirwritten):
+"""Calls scmutil.cleanupnodes() with the given replacements.
+
+"replacements" is a dict from nodeid to nodeid, with one key and one value
+for every revision that was affected by fixing. This is slightly different
+from cleanupnodes().
+
+"wdirwritten" is a bool which tells whether the working copy was affected 
by
+fixing, since it has no entry in "replacements".
+
+Useful as a hook point for extending "hg fix" with output summarizing the
+effects of the command, though we choose not to output anything here.
+"""
+replacements = {prec: [succ] for prec, succ in replacements.iteritems()}
+scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
 
 def getworkqueue(ui, repo, pats, opts, revstofix, basectxs):
 Constructs the list of files to be fixed at specific revisions



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D4048: fix: add a monkey-patchable point after all new revisions have been committed

2018-08-01 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D4048

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -182,8 +182,20 @@
 replacerev(ui, repo, ctx, filedata[rev], replacements)
 del filedata[rev]
 
-replacements = {prec: [succ] for prec, succ in 
replacements.iteritems()}
-scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
+cleanup(repo, replacements)
+
+def cleanup(repo, replacements):
+"""Calls scmutil.cleanupnodes() with the given replacements.
+
+"replacements" is a dict from nodeid to nodeid, with one key and one value
+for every revision that was affected by fixing. This is slightly different
+from cleanupnodes().
+
+Useful as a hook point for extending "hg fix" with output summarizing the
+effects of the command, though we choose not to output anything here.
+"""
+replacements = {prec: [succ] for prec, succ in replacements.iteritems()}
+scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)
 
 def getworkqueue(ui, repo, pats, opts, revstofix, basectxs):
 Constructs the list of files to be fixed at specific revisions



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3960: worker: use one pipe per posix worker and select() in parent process

2018-07-19 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG9e6afe7fca31: worker: use one pipe per posix worker and 
select() in parent process (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3960?vs=9626=9628

REVISION DETAIL
  https://phab.mercurial-scm.org/D3960

AFFECTED FILES
  mercurial/worker.py

CHANGE DETAILS

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -14,6 +14,12 @@
 import threading
 import time
 
+try:
+import selectors
+selectors.BaseSelector
+except ImportError:
+from .thirdparty import selectors2 as selectors
+
 from .i18n import _
 from . import (
 encoding,
@@ -89,7 +95,6 @@
 return func(*staticargs + (args,))
 
 def _posixworker(ui, func, staticargs, args):
-rfd, wfd = os.pipe()
 workers = _numworkers(ui)
 oldhandler = signal.getsignal(signal.SIGINT)
 signal.signal(signal.SIGINT, signal.SIG_IGN)
@@ -138,7 +143,15 @@
 oldchldhandler = signal.signal(signal.SIGCHLD, sigchldhandler)
 ui.flush()
 parentpid = os.getpid()
+pipes = []
 for pargs in partition(args, workers):
+# Every worker gets its own pipe to send results on, so we don't have 
to
+# implement atomic writes larger than PIPE_BUF. Each forked process has
+# its own pipe's descriptors in the local variables, and the parent
+# process has the full list of pipe descriptors (and it doesn't really
+# care what order they're in).
+rfd, wfd = os.pipe()
+pipes.append((rfd, wfd))
 # make sure we use os._exit in all worker code paths. otherwise the
 # worker may do some clean-ups which could cause surprises like
 # deadlock. see sshpeer.cleanup for example.
@@ -154,6 +167,9 @@
 signal.signal(signal.SIGCHLD, oldchldhandler)
 
 def workerfunc():
+for r, w in pipes[:-1]:
+os.close(r)
+os.close(w)
 os.close(rfd)
 for result in func(*(staticargs + (pargs,))):
 os.write(wfd, util.pickle.dumps(result))
@@ -175,8 +191,10 @@
 finally:
 os._exit(ret & 255)
 pids.add(pid)
-os.close(wfd)
-fp = os.fdopen(rfd, r'rb', 0)
+selector = selectors.DefaultSelector()
+for rfd, wfd in pipes:
+os.close(wfd)
+selector.register(os.fdopen(rfd, r'rb', 0), selectors.EVENT_READ)
 def cleanup():
 signal.signal(signal.SIGINT, oldhandler)
 waitforworkers()
@@ -187,15 +205,19 @@
 os.kill(os.getpid(), -status)
 sys.exit(status)
 try:
-while True:
-try:
-yield util.pickle.load(fp)
-except EOFError:
-break
-except IOError as e:
-if e.errno == errno.EINTR:
-continue
-raise
+openpipes = len(pipes)
+while openpipes > 0:
+for key, events in selector.select():
+try:
+yield util.pickle.load(key.fileobj)
+except EOFError:
+selector.unregister(key.fileobj)
+key.fileobj.close()
+openpipes -= 1
+except IOError as e:
+if e.errno == errno.EINTR:
+continue
+raise
 except: # re-raises
 killworkers()
 cleanup()



To: hooper, #hg-reviewers
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3960: worker: use one pipe per posix worker and select() in parent process

2018-07-18 Thread hooper (Danny Hooper)
hooper added a comment.


  Do you want to move the selector import stuff to pycompat?

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3960

To: hooper, #hg-reviewers
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3960: worker: use one pipe per posix worker and select() in parent process

2018-07-18 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 9626.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3960?vs=9618=9626

REVISION DETAIL
  https://phab.mercurial-scm.org/D3960

AFFECTED FILES
  mercurial/worker.py

CHANGE DETAILS

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -14,6 +14,12 @@
 import threading
 import time
 
+try:
+import selectors
+selectors.BaseSelector
+except ImportError:
+from .thirdparty import selectors2 as selectors
+
 from .i18n import _
 from . import (
 encoding,
@@ -89,7 +95,6 @@
 return func(*staticargs + (args,))
 
 def _posixworker(ui, func, staticargs, args):
-rfd, wfd = os.pipe()
 workers = _numworkers(ui)
 oldhandler = signal.getsignal(signal.SIGINT)
 signal.signal(signal.SIGINT, signal.SIG_IGN)
@@ -138,7 +143,15 @@
 oldchldhandler = signal.signal(signal.SIGCHLD, sigchldhandler)
 ui.flush()
 parentpid = os.getpid()
+pipes = []
 for pargs in partition(args, workers):
+# Every worker gets its own pipe to send results on, so we don't have 
to
+# implement atomic writes larger than PIPE_BUF. Each forked process has
+# its own pipe's descriptors in the local variables, and the parent
+# process has the full list of pipe descriptors (and it doesn't really
+# care what order they're in).
+rfd, wfd = os.pipe()
+pipes.append((rfd, wfd))
 # make sure we use os._exit in all worker code paths. otherwise the
 # worker may do some clean-ups which could cause surprises like
 # deadlock. see sshpeer.cleanup for example.
@@ -154,6 +167,9 @@
 signal.signal(signal.SIGCHLD, oldchldhandler)
 
 def workerfunc():
+for r, w in pipes[:-1]:
+os.close(r)
+os.close(w)
 os.close(rfd)
 for result in func(*(staticargs + (pargs,))):
 os.write(wfd, util.pickle.dumps(result))
@@ -175,8 +191,10 @@
 finally:
 os._exit(ret & 255)
 pids.add(pid)
-os.close(wfd)
-fp = os.fdopen(rfd, r'rb', 0)
+selector = selectors.DefaultSelector()
+for rfd, wfd in pipes:
+os.close(wfd)
+selector.register(os.fdopen(rfd, r'rb', 0), selectors.EVENT_READ)
 def cleanup():
 signal.signal(signal.SIGINT, oldhandler)
 waitforworkers()
@@ -187,15 +205,19 @@
 os.kill(os.getpid(), -status)
 sys.exit(status)
 try:
-while True:
-try:
-yield util.pickle.load(fp)
-except EOFError:
-break
-except IOError as e:
-if e.errno == errno.EINTR:
-continue
-raise
+openpipes = len(pipes)
+while openpipes > 0:
+for key, events in selector.select():
+try:
+yield util.pickle.load(key.fileobj)
+except EOFError:
+selector.unregister(key.fileobj)
+key.fileobj.close()
+openpipes -= 1
+except IOError as e:
+if e.errno == errno.EINTR:
+continue
+raise
 except: # re-raises
 killworkers()
 cleanup()



To: hooper, #hg-reviewers
Cc: yuja, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3960: worker: use one pipe per posix worker and select() in parent process

2018-07-17 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This allows us to pass results larger than PIPE_BUF through the pipes without
  interleaving them. This is necessary now because "hg fix" sends file contents
  as the result from workers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3960

AFFECTED FILES
  mercurial/worker.py

CHANGE DETAILS

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -9,6 +9,7 @@
 
 import errno
 import os
+import select
 import signal
 import sys
 import threading
@@ -89,7 +90,6 @@
 return func(*staticargs + (args,))
 
 def _posixworker(ui, func, staticargs, args):
-rfd, wfd = os.pipe()
 workers = _numworkers(ui)
 oldhandler = signal.getsignal(signal.SIGINT)
 signal.signal(signal.SIGINT, signal.SIG_IGN)
@@ -138,7 +138,15 @@
 oldchldhandler = signal.signal(signal.SIGCHLD, sigchldhandler)
 ui.flush()
 parentpid = os.getpid()
+pipes = []
 for pargs in partition(args, workers):
+# Every worker gets its own pipe to send results on, so we don't have 
to
+# implement atomic writes larger than PIPE_BUF. Each forked process has
+# its own pipe's descriptors in the local variables, and the parent
+# process has the full list of pipe descriptors (and it doesn't really
+# care what order they're in).
+rfd, wfd = os.pipe()
+pipes.append((rfd, wfd))
 # make sure we use os._exit in all worker code paths. otherwise the
 # worker may do some clean-ups which could cause surprises like
 # deadlock. see sshpeer.cleanup for example.
@@ -175,8 +183,10 @@
 finally:
 os._exit(ret & 255)
 pids.add(pid)
-os.close(wfd)
-fp = os.fdopen(rfd, r'rb', 0)
+fps = []
+for rfd, wfd in pipes:
+os.close(wfd)
+fps.append(os.fdopen(rfd, r'rb', 0))
 def cleanup():
 signal.signal(signal.SIGINT, oldhandler)
 waitforworkers()
@@ -187,15 +197,23 @@
 os.kill(os.getpid(), -status)
 sys.exit(status)
 try:
-while True:
+while fps:
 try:
-yield util.pickle.load(fp)
-except EOFError:
-break
-except IOError as e:
-if e.errno == errno.EINTR:
+rlist, wlist, xlist = select.select(fps, [], fps)
+except select.error as e:
+if e[0] == errno.EINTR:
 continue
 raise
+for fp in rlist + xlist:
+try:
+yield util.pickle.load(fp)
+except EOFError:
+fp.close()
+except IOError as e:
+if e.errno == errno.EINTR:
+continue
+raise
+fps = [fp for fp in fps if not fp.closed]
 except: # re-raises
 killworkers()
 cleanup()



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3949: shelve: improve help text for --patch and --stat

2018-07-16 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGabcf500d527c: shelve: improve help text for --patch and 
--stat (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3949?vs=9602=9604

REVISION DETAIL
  https://phab.mercurial-scm.org/D3949

AFFECTED FILES
  hgext/shelve.py
  tests/test-shelve.t

CHANGE DETAILS

diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -68,9 +68,12 @@
-l --listlist current shelves
-m --message TEXTuse text as shelve message
-n --name NAME   use the given name for the shelved commit
-   -p --patch   show patch
+   -p --patch   output patches for changes (provide the names of 
the
+shelved changes as positional arguments)
-i --interactive interactive mode, only works while creating a 
shelve
-  --statoutput diffstat-style summary of changes
+  --statoutput diffstat-style summary of changes (provide
+the names of the shelved changes as positional
+arguments)
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
   --mq  operate on patch repository
diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -1011,11 +1011,14 @@
   ('n', 'name', '',
_('use the given name for the shelved commit'), _('NAME')),
   ('p', 'patch', None,
-   _('show patch')),
+   _('output patches for changes (provide the names of the shelved '
+ 'changes as positional arguments)')),
   ('i', 'interactive', None,
_('interactive mode, only works while creating a shelve')),
   ('', 'stat', None,
-   _('output diffstat-style summary of changes'))] + cmdutil.walkopts,
+   _('output diffstat-style summary of changes (provide the names of '
+ 'the shelved changes as positional arguments)')
+   )] + cmdutil.walkopts,
  _('hg shelve [OPTION]... [FILE]...'))
 def shelvecmd(ui, repo, *pats, **opts):
 '''save and set aside changes from the working directory



To: hooper, #hg-reviewers, pulkit
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3950: shelve: pick the most recent shelve if none specified for --patch/--stat

2018-07-16 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG905b66681004: shelve: pick the most recent shelve if none 
specified for --patch/--stat (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3950?vs=9603=9605

REVISION DETAIL
  https://phab.mercurial-scm.org/D3950

AFFECTED FILES
  hgext/shelve.py
  tests/test-shelve.t

CHANGE DETAILS

diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -1057,8 +1057,33 @@
   $ hg shelve --patch default nonexistentshelf
   abort: cannot find shelf nonexistentshelf
   [255]
+
+when the user asks for a patch, we assume they want the most recent shelve if
+they don't provide a shelve name
+
   $ hg shelve --patch
-  abort: --patch expects at least one shelf
+  default-01  (*)* changes to: create conflict (glob)
+  
+  diff --git a/shelf-patch-b b/shelf-patch-b
+  new file mode 100644
+  --- /dev/null
+  +++ b/shelf-patch-b
+  @@ -0,0 +1,1 @@
+  +patch b
+
+  $ cd ..
+
+you shouldn't be able to ask for the patch/stats of the most recent shelve if
+there are no shelves
+
+  $ hg init noshelves
+  $ cd noshelves
+
+  $ hg shelve --patch
+  abort: there are no shelves to show
+  [255]
+  $ hg shelve --stat
+  abort: there are no shelves to show
   [255]
 
   $ cd ..
diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -594,10 +594,15 @@
 for chunk, label in patch.diffstatui(difflines, width=width):
 ui.write(chunk, label=label)
 
-def patchcmds(ui, repo, pats, opts, subcommand):
+def patchcmds(ui, repo, pats, opts):
 """subcommand that displays shelves"""
 if len(pats) == 0:
-raise error.Abort(_("--%s expects at least one shelf") % subcommand)
+shelves = listshelves(repo)
+if not shelves:
+raise error.Abort(_("there are no shelves to show"))
+mtime, name = shelves[0]
+sname = util.split(name)[1]
+pats = [sname]
 
 for shelfname in pats:
 if not shelvedfile(repo, shelfname, patchextension).exists():
@@ -1082,10 +1087,8 @@
 return deletecmd(ui, repo, pats)
 elif checkopt('list'):
 return listcmd(ui, repo, pats, opts)
-elif checkopt('patch'):
-return patchcmds(ui, repo, pats, opts, subcommand='patch')
-elif checkopt('stat'):
-return patchcmds(ui, repo, pats, opts, subcommand='stat')
+elif checkopt('patch') or checkopt('stat'):
+return patchcmds(ui, repo, pats, opts)
 else:
 return createcmd(ui, repo, pats, opts)
 



To: hooper, #hg-reviewers, pulkit
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3949: shelve: improve help text for --patch and --stat

2018-07-16 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  It's not currently obvious why "hg shelve -p" fails, since -p doesn't take an 
argument.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3949

AFFECTED FILES
  hgext/shelve.py
  tests/test-shelve.t

CHANGE DETAILS

diff --git a/tests/test-shelve.t b/tests/test-shelve.t
--- a/tests/test-shelve.t
+++ b/tests/test-shelve.t
@@ -68,9 +68,12 @@
-l --listlist current shelves
-m --message TEXTuse text as shelve message
-n --name NAME   use the given name for the shelved commit
-   -p --patch   show patch
+   -p --patch   output patches for changes (provide the names of 
the
+shelved changes as positional arguments)
-i --interactive interactive mode, only works while creating a 
shelve
-  --statoutput diffstat-style summary of changes
+  --statoutput diffstat-style summary of changes (provide
+the names of the shelved changes as positional
+arguments)
-I --include PATTERN [+] include names matching the given patterns
-X --exclude PATTERN [+] exclude names matching the given patterns
   --mq  operate on patch repository
diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -1011,11 +1011,14 @@
   ('n', 'name', '',
_('use the given name for the shelved commit'), _('NAME')),
   ('p', 'patch', None,
-   _('show patch')),
+   _('output patches for changes (provide the names of the shelved '
+ 'changes as positional arguments)')),
   ('i', 'interactive', None,
_('interactive mode, only works while creating a shelve')),
   ('', 'stat', None,
-   _('output diffstat-style summary of changes'))] + cmdutil.walkopts,
+   _('output diffstat-style summary of changes (provide the names of '
+ 'the shelved changes as positional arguments)')
+   )] + cmdutil.walkopts,
  _('hg shelve [OPTION]... [FILE]...'))
 def shelvecmd(ui, repo, *pats, **opts):
 '''save and set aside changes from the working directory



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3897: tests: prevent conflict markers in test case from triggering warnings

2018-07-11 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG02850baddadd: tests: prevent conflict markers in test case 
from triggering warnings (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3897?vs=9485=9530

REVISION DETAIL
  https://phab.mercurial-scm.org/D3897

AFFECTED FILES
  tests/test-simplemerge.py

CHANGE DETAILS

diff --git a/tests/test-simplemerge.py b/tests/test-simplemerge.py
--- a/tests/test-simplemerge.py
+++ b/tests/test-simplemerge.py
@@ -109,13 +109,13 @@
so we may see their result.
  The two are the same,
  But after they are produced,
-   they have different names.
-<<< LAO
-===
+   they have different names.\
+\n<<< LAO\
+\n===
 
-- The Way of Lao-Tzu, tr. Wing-tsit Chan
-
->>> TAO
+\
+\n>>> TAO
 """)
 
 class TestMerge3(TestCase):



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3897: tests: prevent conflict markers in test case from triggering warnings

2018-07-09 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Broadly, having lines that begin with several '<' tends to trigger tools that
  try to warn you about unresolved conflicts. It will save some headaches to
  tweak this string literal to avoid that.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3897

AFFECTED FILES
  tests/test-simplemerge.py

CHANGE DETAILS

diff --git a/tests/test-simplemerge.py b/tests/test-simplemerge.py
--- a/tests/test-simplemerge.py
+++ b/tests/test-simplemerge.py
@@ -109,13 +109,13 @@
so we may see their result.
  The two are the same,
  But after they are produced,
-   they have different names.
-<<< LAO
-===
+   they have different names.\
+\n<<< LAO\
+\n===
 
-- The Way of Lao-Tzu, tr. Wing-tsit Chan
-
->>> TAO
+\
+\n>>> TAO
 """)
 
 class TestMerge3(TestCase):



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3894: fix: add test case that shows why --whole with --base is useful

2018-07-06 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGf068495a1c28: fix: add test case that shows why --whole 
with --base is useful (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3894?vs=9465=9468

REVISION DETAIL
  https://phab.mercurial-scm.org/D3894

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1027,3 +1027,29 @@
 
   $ cd ..
 
+The --base flag affects the set of files being fixed. So while the --whole flag
+makes the base irrelevant for changed line ranges, it still changes the
+meaning and effect of the command. In this example, no files or lines are fixed
+until we specify the base, but then we do fix unchanged lines.
+
+  $ hg init basewhole
+  $ cd basewhole
+  $ printf "foo1\n" > foo.changed
+  $ hg commit -Aqm "first"
+  $ printf "foo2\n" >> foo.changed
+  $ printf "bar\n" > bar.changed
+  $ hg commit -Aqm "second"
+
+  $ hg fix --working-dir --whole
+  $ cat *.changed
+  bar
+  foo1
+  foo2
+
+  $ hg fix --working-dir --base 0 --whole
+  $ cat *.changed
+  BAR
+  FOO1
+  FOO2
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -385,7 +385,9 @@
 """Returns a map of the base contexts for each revision
 
 The base contexts determine which lines are considered modified when we
-attempt to fix just the modified lines in a file.
+attempt to fix just the modified lines in a file. It also determines which
+files we attempt to fix, so it is important to compute this even when
+--whole is used.
 """
 # The --base flag overrides the usual logic, and we give every revision
 # exactly the set of baserevs that the user specified.



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3894: fix: add test case that shows why --whole with --base is useful

2018-07-06 Thread hooper (Danny Hooper)
hooper created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3894

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -1027,3 +1027,29 @@
 
   $ cd ..
 
+The --base flag affects the set of files being fixed. So while the --whole flag
+makes the base irrelevant for changed line ranges, it still changes the
+meaning and effect of the command. In this example, no files or lines are fixed
+until we specify the base, but then we do fix unchanged lines.
+
+  $ hg init basewhole
+  $ cd basewhole
+  $ printf "foo1\n" > foo.changed
+  $ hg commit -Aqm "first"
+  $ printf "foo2\n" >> foo.changed
+  $ printf "bar\n" > bar.changed
+  $ hg commit -Aqm "second"
+
+  $ hg fix --working-dir --whole
+  $ cat *.changed
+  bar
+  foo1
+  foo2
+
+  $ hg fix --working-dir --base 0 --whole
+  $ cat *.changed
+  BAR
+  FOO1
+  FOO2
+
+  $ cd ..
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -385,7 +385,9 @@
 """Returns a map of the base contexts for each revision
 
 The base contexts determine which lines are considered modified when we
-attempt to fix just the modified lines in a file.
+attempt to fix just the modified lines in a file. It also determines which
+files we attempt to fix, so it is important to compute this even when
+--whole is used.
 """
 # The --base flag overrides the usual logic, and we give every revision
 # exactly the set of baserevs that the user specified.



To: hooper, #hg-reviewers
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3848: fix: add progress bar for number of file revisions processed

2018-07-04 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGc8961e9b2f5e: fix: add progress bar for number of file 
revisions processed (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3848?vs=9368=9432

REVISION DETAIL
  https://phab.mercurial-scm.org/D3848

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -162,22 +162,25 @@
 filedata = collections.defaultdict(dict)
 replacements = {}
 commitorder = sorted(revstofix, reverse=True)
-for rev, path, newdata in results:
-if newdata is not None:
-filedata[rev][path] = newdata
-numitems[rev] -= 1
-# Apply the fixes for this and any other revisions that are ready
-# and sitting at the front of the queue. Using a loop here prevents
-# the queue from being blocked by the first revision to be ready 
out
-# of order.
-while commitorder and not numitems[commitorder[-1]]:
-rev = commitorder.pop()
-ctx = repo[rev]
-if rev == wdirrev:
-writeworkingdir(repo, ctx, filedata[rev], replacements)
-else:
-replacerev(ui, repo, ctx, filedata[rev], replacements)
-del filedata[rev]
+with ui.makeprogress(topic=_('fixing'), unit=_('files'),
+ total=sum(numitems.values())) as progress:
+for rev, path, newdata in results:
+progress.increment(item=path)
+if newdata is not None:
+filedata[rev][path] = newdata
+numitems[rev] -= 1
+# Apply the fixes for this and any other revisions that are
+# ready and sitting at the front of the queue. Using a loop 
here
+# prevents the queue from being blocked by the first revision 
to
+# be ready out of order.
+while commitorder and not numitems[commitorder[-1]]:
+rev = commitorder.pop()
+ctx = repo[rev]
+if rev == wdirrev:
+writeworkingdir(repo, ctx, filedata[rev], replacements)
+else:
+replacerev(ui, repo, ctx, filedata[rev], replacements)
+del filedata[rev]
 
 replacements = {prec: [succ] for prec, succ in 
replacements.iteritems()}
 scmutil.cleanupnodes(repo, replacements, 'fix', fixphase=True)



To: hooper, #hg-reviewers, durin42
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3845: worker: support more return types in posix worker

2018-07-04 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG8c38d2948217: worker: support more return types in posix 
worker (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3845?vs=9418=9429

REVISION DETAIL
  https://phab.mercurial-scm.org/D3845

AFFECTED FILES
  mercurial/worker.py

CHANGE DETAILS

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -155,8 +155,8 @@
 
 def workerfunc():
 os.close(rfd)
-for i, item in func(*(staticargs + (pargs,))):
-os.write(wfd, '%d %s\n' % (i, item))
+for result in func(*(staticargs + (pargs,))):
+os.write(wfd, util.pickle.dumps(result))
 return 0
 
 ret = scmutil.callcatch(ui, workerfunc)
@@ -187,9 +187,15 @@
 os.kill(os.getpid(), -status)
 sys.exit(status)
 try:
-for line in util.iterfile(fp):
-l = line.split(' ', 1)
-yield int(l[0]), l[1][:-1]
+while True:
+try:
+yield util.pickle.load(fp)
+except EOFError:
+break
+except IOError as e:
+if e.errno == errno.EINTR:
+continue
+raise
 except: # re-raises
 killworkers()
 cleanup()



To: hooper, #hg-reviewers
Cc: yuja, durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3846: fix: use a worker pool to parallelize running tools

2018-07-04 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG5ffe2041d427: fix: use a worker pool to parallelize running 
tools (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3846?vs=9365=9430

REVISION DETAIL
  https://phab.mercurial-scm.org/D3846

AFFECTED FILES
  hgext/fix.py

CHANGE DETAILS

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -70,6 +70,7 @@
 registrar,
 scmutil,
 util,
+worker,
 )
 
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' 
for
@@ -138,19 +139,40 @@
 basectxs = getbasectxs(repo, opts, revstofix)
 workqueue, numitems = getworkqueue(ui, repo, pats, opts, revstofix,
basectxs)
+fixers = getfixers(ui)
+
+# There are no data dependencies between the workers fixing each file
+# revision, so we can use all available parallelism.
+def getfixes(items):
+for rev, path in items:
+ctx = repo[rev]
+olddata = ctx[path].data()
+newdata = fixfile(ui, opts, fixers, ctx, path, basectxs[rev])
+# Don't waste memory/time passing unchanged content back, but
+# produce one result per item either way.
+yield (rev, path, newdata if newdata != olddata else None)
+results = worker.worker(ui, 1.0, getfixes, tuple(), workqueue)
+
+# We have to hold on to the data for each successor revision in memory
+# until all its parents are committed. We ensure this by committing and
+# freeing memory for the revisions in some topological order. This
+# leaves a little bit of memory efficiency on the table, but also makes
+# the tests deterministic. It might also be considered a feature since
+# it makes the results more easily reproducible.
 filedata = collections.defaultdict(dict)
 replacements = {}
-fixers = getfixers(ui)
-# Some day this loop can become a worker pool, but for now it's easier
-# to fix everything serially in topological order.
-for rev, path in sorted(workqueue):
-ctx = repo[rev]
-olddata = ctx[path].data()
-newdata = fixfile(ui, opts, fixers, ctx, path, basectxs[rev])
-if newdata != olddata:
+commitorder = sorted(revstofix, reverse=True)
+for rev, path, newdata in results:
+if newdata is not None:
 filedata[rev][path] = newdata
 numitems[rev] -= 1
-if not numitems[rev]:
+# Apply the fixes for this and any other revisions that are ready
+# and sitting at the front of the queue. Using a loop here prevents
+# the queue from being blocked by the first revision to be ready 
out
+# of order.
+while commitorder and not numitems[commitorder[-1]]:
+rev = commitorder.pop()
+ctx = repo[rev]
 if rev == wdirrev:
 writeworkingdir(repo, ctx, filedata[rev], replacements)
 else:
@@ -168,11 +190,19 @@
 topological order. Each work item represents a file in the working copy or
 in some revision that should be fixed and written back to the working copy
 or into a replacement revision.
+
+Work items for the same revision are grouped together, so that a worker
+pool starting with the first N items in parallel is likely to finish the
+first revision's work before other revisions. This can allow us to write
+the result to disk and reduce memory footprint. At time of writing, the
+partition strategy in worker.py seems favorable to this. We also sort the
+items by ascending revision number to match the order in which we commit
+the fixes later.
 """
 workqueue = []
 numitems = collections.defaultdict(int)
 maxfilesize = ui.configbytes('fix', 'maxfilesize')
-for rev in revstofix:
+for rev in sorted(revstofix):
 fixctx = repo[rev]
 match = scmutil.match(fixctx, pats, opts)
 for path in pathstofix(ui, repo, pats, opts, match, basectxs[rev],



To: hooper, #hg-reviewers, durin42
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3847: fix: disallow 'hg fix --base --whole'

2018-07-04 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG3a2c57dfea60: fix: disallow hg fix --base rev 
--whole (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3847?vs=9366=9431

REVISION DETAIL
  https://phab.mercurial-scm.org/D3847

AFFECTED FILES
  hgext/fix.py
  tests/test-fix.t

CHANGE DETAILS

diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -178,6 +178,9 @@
   abort: no changesets specified
   (use --rev or --working-dir)
   [255]
+  $ hg fix --base 0 --whole --working-dir
+  abort: --base has no meaning in addition to --whole
+  [255]
 
 Fixing a public revision isn't allowed. It should abort early enough that
 nothing happens, even to the working directory.
diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -387,6 +387,8 @@
 # The --base flag overrides the usual logic, and we give every revision
 # exactly the set of baserevs that the user specified.
 if opts.get('base'):
+if opts.get('whole'):
+raise error.Abort('--base has no meaning in addition to --whole')
 baserevs = set(scmutil.revrange(repo, opts.get('base')))
 if not baserevs:
 baserevs = {nullrev}



To: hooper, #hg-reviewers, durin42
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3847: fix: disallow 'hg fix --base --whole'

2018-07-03 Thread hooper (Danny Hooper)
hooper added a comment.


  Let's not commit this one if possible. I have another patch with a test case 
that shows the combination is useful.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3847

To: hooper, #hg-reviewers, durin42
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3845: worker: support more return types in posix worker

2018-07-03 Thread hooper (Danny Hooper)
hooper added a comment.


  Yuya, it had passed tests for me with cbor, so is that a portability issue?
  
  One of the benefits of pickle/marshal is that we don't lose information, like 
when tuples become lists. That would be an insidious problem for callers.
  
  Also, in case it wasn't obvious, we'll need another patch to add some 
handling of len(dumps(result)) > PIPE_BUF (which was an existing issue).

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D3845

To: hooper, #hg-reviewers
Cc: yuja, durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3845: worker: support more return types in posix worker

2018-07-03 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 9418.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3845?vs=9401=9418

REVISION DETAIL
  https://phab.mercurial-scm.org/D3845

AFFECTED FILES
  mercurial/worker.py

CHANGE DETAILS

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -155,8 +155,8 @@
 
 def workerfunc():
 os.close(rfd)
-for i, item in func(*(staticargs + (pargs,))):
-os.write(wfd, '%d %s\n' % (i, item))
+for result in func(*(staticargs + (pargs,))):
+os.write(wfd, util.pickle.dumps(result))
 return 0
 
 ret = scmutil.callcatch(ui, workerfunc)
@@ -187,9 +187,15 @@
 os.kill(os.getpid(), -status)
 sys.exit(status)
 try:
-for line in util.iterfile(fp):
-l = line.split(' ', 1)
-yield int(l[0]), l[1][:-1]
+while True:
+try:
+yield util.pickle.load(fp)
+except EOFError:
+break
+except IOError as e:
+if e.errno == errno.EINTR:
+continue
+raise
 except: # re-raises
 killworkers()
 cleanup()



To: hooper, #hg-reviewers
Cc: yuja, durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3845: worker: support more return types in posix worker

2018-07-01 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 9401.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3845?vs=9364=9401

REVISION DETAIL
  https://phab.mercurial-scm.org/D3845

AFFECTED FILES
  mercurial/worker.py

CHANGE DETAILS

diff --git a/mercurial/worker.py b/mercurial/worker.py
--- a/mercurial/worker.py
+++ b/mercurial/worker.py
@@ -15,6 +15,9 @@
 import time
 
 from .i18n import _
+from .thirdparty import (
+cbor,
+)
 from . import (
 encoding,
 error,
@@ -155,8 +158,8 @@
 
 def workerfunc():
 os.close(rfd)
-for i, item in func(*(staticargs + (pargs,))):
-os.write(wfd, '%d %s\n' % (i, item))
+for result in func(*(staticargs + (pargs,))):
+os.write(wfd, cbor.dumps(result))
 return 0
 
 ret = scmutil.callcatch(ui, workerfunc)
@@ -187,9 +190,15 @@
 os.kill(os.getpid(), -status)
 sys.exit(status)
 try:
-for line in util.iterfile(fp):
-l = line.split(' ', 1)
-yield int(l[0]), l[1][:-1]
+while True:
+try:
+yield cbor.load(fp)
+except EOFError:
+break
+except IOError as e:
+if e.errno == errno.EINTR:
+continue
+raise
 except: # re-raises
 killworkers()
 cleanup()



To: hooper, #hg-reviewers
Cc: yuja, durin42, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3861: scmutil: fix __enter__ in progress context manager

2018-07-01 Thread hooper (Danny Hooper)
hooper updated this revision to Diff 9402.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3861?vs=9380=9402

REVISION DETAIL
  https://phab.mercurial-scm.org/D3861

AFFECTED FILES
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -1328,7 +1328,7 @@
 self.total = total
 
 def __enter__(self):
-pass
+return self
 
 def __exit__(self, exc_type, exc_value, exc_tb):
 self.complete()



To: hooper, #hg-reviewers, durin42
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3861: scmutil: fix __enter__ in progress context manager

2018-06-30 Thread hooper (Danny Hooper)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG077301ac69dc: scmutil: fix __enter__ in progress context 
manager (authored by hooper, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3861?vs=9367=9380

REVISION DETAIL
  https://phab.mercurial-scm.org/D3861

AFFECTED FILES
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -1328,7 +1328,7 @@
 self.total = total
 
 def __enter__(self):
-pass
+return self
 
 def __exit__(self, exc_type, exc_value, exc_tb):
 self.complete()



To: hooper, #hg-reviewers, durin42
Cc: mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


  1   2   >