D5514: test: change test's diff generation to use mdiff for nicer output

2019-02-13 Thread sangeet259 (Sangeet Kumar Mishra)
sangeet259 added a comment.


  ping @durin42

REPOSITORY
  rHG Mercurial

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

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


D5959: templates: adding a config() function for template customization.

2019-02-13 Thread rdamazio (Rodrigo Damazio Bovendorp)
rdamazio created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This allows templates to be written such that users can customize them easily,
  or that they can be customized based on other configuration of the system.  
For
  enterprise deployments, we often have complex template aliases, and right now
  the only way individual users can customize those is by replacing the whole
  template alias (which means they won't get company-wide updates to it anymore,
  plus most users don't want to have to get a complex template right).
  With this change, they can just set a config option which feeds into our
  templates for common changes (e.g. whether to limit commit descriptions to the
  width of their terminal or not).
  
  To work around the issue of having to register the config options, I declared
  a dedicated section [templateconfig] for these options to be dynamically
  declared. They can still reference any other config option that's registered
  elsewhere.
  
  I only did string, bool and int at this time - list and date would add other
  complications with parsing the default so I'll leave that as an exercise to
  the reader :)

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/configitems.py
  mercurial/templatefuncs.py
  tests/test-template-functions.t

CHANGE DETAILS

diff --git a/tests/test-template-functions.t b/tests/test-template-functions.t
--- a/tests/test-template-functions.t
+++ b/tests/test-template-functions.t
@@ -1549,4 +1549,31 @@
   $ HGENCODING=utf-8 hg debugtemplate "{pad('`cat utf-8`', 2, '-')}\n"
   \xc3\xa9- (esc)
 
+read config options:
+
+  $ hg log -T "{config('templateconfig', 'knob', 'foo')}\n"
+  foo
+  $ hg log -T "{config('templateconfig', 'knob', 'foo')}\n" \
+  > --config templateconfig.knob=bar
+  bar
+  $ hg log -T "{configbool('templateconfig', 'knob', True)}\n"
+  True
+  $ hg log -T "{configbool('templateconfig', 'knob', True)}\n" \
+  > --config templateconfig.knob=0
+  False
+  $ hg log -T "{configint('templateconfig', 'knob', 123)}\n"
+  123
+  $ hg log -T "{configint('templateconfig', 'knob', 123)}\n" \
+  > --config templateconfig.knob=456
+  456
+  $ hg log -T "{config('templateconfig', 'knob')}\n"
+  devel-warn: config item requires an explicit default value: 
'templateconfig.knob' at: * (glob)
+  
+  $ hg log -T "{configbool('ui', 'interactive')}\n"
+  False
+  $ hg log -T "{configbool('ui', 'interactive')}\n" --config ui.interactive=1
+  True
+  $ hg log -T "{config('templateconfig', 'knob', if(true, 'foo', 'bar'))}\n"
+  foo
+
   $ cd ..
diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -295,6 +295,39 @@
 hint = _("get() expects a dict as first argument")
 raise error.ParseError(bytes(err), hint=hint)
 
+@templatefunc('config(section, name[, default])', requires={'ui'})
+def config(context, mapping, args):
+"""Returns the requested hgrc config option as a string."""
+fn = context.resource(mapping, 'ui').config
+return _config(context, mapping, args, fn, evalstring)
+
+@templatefunc('configbool(section, name[, default])', requires={'ui'})
+def configbool(context, mapping, args):
+"""Returns the requested hgrc config option as a boolean."""
+fn = context.resource(mapping, 'ui').configbool
+return _config(context, mapping, args, fn, evalboolean)
+
+@templatefunc('configint(section, name[, default])', requires={'ui'})
+def configint(context, mapping, args):
+"""Returns the requested hgrc config option as an integer."""
+fn = context.resource(mapping, 'ui').configint
+return _config(context, mapping, args, fn, evalinteger)
+
+def _config(context, mapping, args, configfn, defaultfn):
+if not (2 <= len(args) <= 3):
+raise error.ParseError(_("config expects two or three arguments"))
+
+# The config option can come from any section, though we specifically
+# reserve the [templateconfig] section for dynamically defining options
+# for this function without also requiring an extension.
+section = evalstringliteral(context, mapping, args[0])
+name = evalstringliteral(context, mapping, args[1])
+if len(args) == 3:
+default = defaultfn(context, mapping, args[2])
+return configfn(section, name, default)
+else:
+return configfn(section, name)
+
 @templatefunc('if(expr, then[, else])')
 def if_(context, mapping, args):
 """Conditionally execute based on the result of
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -1081,6 +1081,10 @@
 default=None,
 generic=True,
 )
+coreconfigitem('templateconfig', '.*',
+default=dynamicdefault,
+generic=True,
+)
 coreconfigitem('trusted', 'groups',
 default=list,
 )



To: rdamazio, #hg-reviewers
Cc: 

D5958: remotefilelog: remove strkwargs()

2019-02-13 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The previous commit activated previously unused code paths on
  Python 3 and revealed that we were calling strkwargs() on a dict
  that already had str keys. The only caller of _forceprefetch()
  is _adjustlinknode() a few lines up and the static commonlogkwargs
  dict features str keys.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/remotefilelog/remotefilectx.py

CHANGE DETAILS

diff --git a/hgext/remotefilelog/remotefilectx.py 
b/hgext/remotefilelog/remotefilectx.py
--- a/hgext/remotefilelog/remotefilectx.py
+++ b/hgext/remotefilelog/remotefilectx.py
@@ -316,7 +316,7 @@
 finally:
 elapsed = time.time() - start
 repo.ui.log('linkrevfixup', logmsg + '\n', elapsed=elapsed * 1000,
-**pycompat.strkwargs(commonlogkwargs))
+**commonlogkwargs)
 
 def _verifylinknode(self, revs, linknode):
 """



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


D5957: remotefilelog: use raw strings when looking for variable names

2019-02-13 Thread indygreg (Gregory Szorc)
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Keys in self.__dict__ and vars() are always str. So we need to use
  raw strings to ensure lookups work on Python 3.
  
  1. skip-blame just r'' prefixes

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/remotefilelog/remotefilectx.py

CHANGE DETAILS

diff --git a/hgext/remotefilelog/remotefilectx.py 
b/hgext/remotefilelog/remotefilectx.py
--- a/hgext/remotefilelog/remotefilectx.py
+++ b/hgext/remotefilelog/remotefilectx.py
@@ -39,11 +39,11 @@
 
 @propertycache
 def _changeid(self):
-if '_changeid' in self.__dict__:
+if r'_changeid' in self.__dict__:
 return self._changeid
-elif '_changectx' in self.__dict__:
+elif r'_changectx' in self.__dict__:
 return self._changectx.rev()
-elif '_descendantrev' in self.__dict__:
+elif r'_descendantrev' in self.__dict__:
 # this file context was created from a revision with a known
 # descendant, we can (lazily) correct for linkrev aliases
 linknode = self._adjustlinknode(self._path, self._filelog,
@@ -102,7 +102,7 @@
 """
 lkr = self.linkrev()
 attrs = vars(self)
-noctx = not ('_changeid' in attrs or '_changectx' in attrs)
+noctx = not (r'_changeid' in attrs or r'_changectx' in attrs)
 if noctx or self.rev() == lkr:
 return lkr
 linknode = self._adjustlinknode(self._path, self._filelog,



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


[PATCH V2] fix: change the default fix pattern (issue6077)

2019-02-13 Thread Jordi Gutiérrez Hermoso
# HG changeset patch
# User Jordi Gutiérrez Hermoso 
# Date 1550096863 18000
#  Wed Feb 13 17:27:43 2019 -0500
# Node ID d8ba3b6466b220a5e04d07a5eccd3c1d45a2f501
# Parent  5d383d9636d0b81b416398913b32b8c715e98db5
fix: change the default fix pattern (issue6077)

The matchutils functions don't know what to do with an empty pattern.
When a fixer doesn't have a pattern at all, a default of None will
make match functions unhappy and stack trace.

Change this default instead to a pattern that matches everything.

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -38,7 +38,8 @@ substituted into the command::
 
 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.
+arguments to :hg:`fix`, the intersection of these patterns is used. If no 
patterns
+are specified, the default is to apply the tool to all files.
 
 There is also a configurable limit for the maximum size of file that will be
 processed by :hg:`fix`::
@@ -122,7 +123,7 @@ FIXER_ATTRS = {
 'command': None,
 'linerange': None,
 'fileset': None,
-'pattern': None,
+'pattern': '.',
 'priority': 0,
 }
 
diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -288,17 +288,28 @@ we ignore a file that doesn't match any 
 
   $ cd ..
 
+A config file missing a :pattern suboption to match issue6077
+
+  $ REMOVE_WS=$TESTTMP/remove-trailing-whitespace.hgrc
+  $ cat >> $REMOVE_WS < [extensions]
+  > fix =
+  > [fix]
+  > trailing-whitespace:command = sed
+  > trailing-whitespace:linerange = -e '{first},{last}s/\s\+$//'
+  > EOF
+
 Fixing the working directory should still work if there are no revisions.
 
   $ hg init norevisions
   $ cd norevisions
 
-  $ printf "something\n" > something.whole
+  $ printf "something   \n" > something.whole
   $ hg add
   adding something.whole
-  $ hg fix --working-dir
+  $ HGRCPATH=$REMOVE_WS hg fix --working-dir
   $ cat something.whole
-  SOMETHING
+  something
 
   $ cd ..
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] fix: change the default fix pattern (issue6077)

2019-02-13 Thread Jordi Gutiérrez Hermoso
# HG changeset patch
# User Jordi Gutiérrez Hermoso 
# Date 1550096863 18000
#  Wed Feb 13 17:27:43 2019 -0500
# Node ID c56534966c1641a50994a02c746e5b17cb00aa0e
# Parent  5d383d9636d0b81b416398913b32b8c715e98db5
fix: change the default fix pattern (issue6077)

The matchutils functions don't know what to do with an empty pattern.
When a fixer doesn't have a pattern at all, a default of None will
make match functions unhappy and stack trace.

Change this default instead to a pattern that matches everything.

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -122,7 +122,7 @@ FIXER_ATTRS = {
 'command': None,
 'linerange': None,
 'fileset': None,
-'pattern': None,
+'pattern': '.',
 'priority': 0,
 }
 
diff --git a/tests/test-fix.t b/tests/test-fix.t
--- a/tests/test-fix.t
+++ b/tests/test-fix.t
@@ -288,17 +288,28 @@ we ignore a file that doesn't match any 
 
   $ cd ..
 
+A config file missing a :pattern suboption to match issue6077
+
+  $ REMOVE_WS=$TESTTMP/remove-trailing-whitespace.hgrc
+  $ cat >> $REMOVE_WS < [extensions]
+  > fix =
+  > [fix]
+  > trailing-whitespace:command = sed
+  > trailing-whitespace:linerange = -e '{first},{last}s/\s\+$//'
+  > EOF
+
 Fixing the working directory should still work if there are no revisions.
 
   $ hg init norevisions
   $ cd norevisions
 
-  $ printf "something\n" > something.whole
+  $ printf "something   \n" > something.whole
   $ hg add
   adding something.whole
-  $ hg fix --working-dir
+  $ HGRCPATH=$REMOVE_WS hg fix --working-dir
   $ cat something.whole
-  SOMETHING
+  something
 
   $ cd ..
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] chistedit: use magenta for current line as in crecord (issue6071)

2019-02-13 Thread Jordi Gutiérrez Hermoso
# HG changeset patch
# User Jordi Gutiérrez Hermoso 
# Date 1550095104 18000
#  Wed Feb 13 16:58:24 2019 -0500
# Node ID e31eb021571e1a6a63aab8090819184576236c58
# Parent  5d383d9636d0b81b416398913b32b8c715e98db5
chistedit: use magenta for current line as in crecord (issue6071)

It was inconsistent in the UI to have different way to show the
current line.

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -957,7 +957,7 @@ ACTION_LABELS = {
 'roll': '^roll',
 }
 
-COLOR_HELP, COLOR_SELECTED, COLOR_OK, COLOR_WARN  = 1, 2, 3, 4
+COLOR_HELP, COLOR_SELECTED, COLOR_OK, COLOR_WARN, COLOR_CURRENT  = 1, 2, 3, 4, 
5
 
 E_QUIT, E_HISTEDIT = 1, 2
 E_PAGEDOWN, E_PAGEUP, E_LINEUP, E_LINEDOWN, E_RESIZE = 3, 4, 5, 6, 7
@@ -1237,6 +1237,7 @@ def _chisteditmain(repo, rules, stdscr):
 curses.init_pair(COLOR_SELECTED, curses.COLOR_BLACK, curses.COLOR_WHITE)
 curses.init_pair(COLOR_WARN, curses.COLOR_BLACK, curses.COLOR_YELLOW)
 curses.init_pair(COLOR_OK, curses.COLOR_BLACK, curses.COLOR_GREEN)
+curses.init_pair(COLOR_CURRENT, curses.COLOR_WHITE, curses.COLOR_MAGENTA)
 
 # don't display the cursor
 try:
@@ -1327,7 +1328,7 @@ pgup/K: move patch up, pgdn/J: move patc
 if y + start == selected:
 addln(rulesscr, y, 2, rule, curses.color_pair(COLOR_SELECTED))
 elif y + start == pos:
-addln(rulesscr, y, 2, rule, curses.A_BOLD)
+addln(rulesscr, y, 2, rule, curses.color_pair(COLOR_CURRENT) | 
curses.A_BOLD)
 else:
 addln(rulesscr, y, 2, rule)
 rulesscr.noutrefresh()
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] histedit: remove "chistedit" mention from interface

2019-02-13 Thread Jordi Gutiérrez Hermoso
# HG changeset patch
# User Jordi Gutiérrez Hermoso 
# Date 1550091764 18000
#  Wed Feb 13 16:02:44 2019 -0500
# Node ID 94ccf890584ee3bae9e543fade578e0f05281347
# Parent  5d383d9636d0b81b416398913b32b8c715e98db5
histedit: remove "chistedit" mention from interface

"chisted" is internal jargon. The end user should not need to be aware
that it's different from histedit.

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1486,7 +1486,7 @@ def _chistedit(ui, repo, *freeargs, **op
 curses.echo()
 curses.endwin()
 if rc is False:
-ui.write(_("chistedit aborted\n"))
+ui.write(_("histedit aborted\n"))
 return 0
 if type(rc) is list:
 ui.status(_("running histedit\n"))
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5956: scmutil: fix a comment that doesn't match the code

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
martinvonz 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/D5956

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
@@ -1123,7 +1123,7 @@
 repo.ui.status(status)
 
 # TODO: We should probably have the caller pass in uipathfn and apply it to
-# the messages above too. forcerelativevalue=True is consistent with how
+# the messages above too. legacyrelativevalue=True is consistent with how
 # it used to work.
 uipathfn = getuipathfn(repo, legacyrelativevalue=True)
 renames = _findrenames(repo, m, added + unknown, removed + deleted,



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


D5941: tweakdefault: Add better documentation for ui.tweakdefault(issue6000)

2019-02-13 Thread akshjain.jain74 (Akshit Jain)
akshjain.jain74 updated this revision to Diff 14079.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5941?vs=14050=14079

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

AFFECTED FILES
  mercurial/help/config.txt

CHANGE DETAILS

diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -2394,13 +2394,21 @@
 
 ``tweakdefaults``
 
+Making fine adjustments in mercurial default behavior.
+
 By default Mercurial's behavior changes very little from release
 to release, but over time the recommended config settings
 shift. Enable this config to opt in to get automatic tweaks to
 Mercurial's behavior over time. This config setting will have no
 effect if ``HGPLAIN`` is set or ``HGPLAINEXCEPT`` is set and does
 not include ``tweakdefaults``. (default: False)
 
+It is a way to opt-in to what mercurial has decided
+is the best default experience for it.
+
+
+
+
 It currently means::
 
   .. tweakdefaultsmarker



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


D5743: patch: handle 0 context lines (diff.unified=0) when parsing patches

2019-02-13 Thread akshjain.jain74 (Akshit Jain)
akshjain.jain74 updated this revision to Diff 14078.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5743?vs=13571=14078

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

AFFECTED FILES
  mercurial/patch.py
  tests/test-commit-interactive.t
  tests/test-split.t

CHANGE DETAILS

diff --git a/tests/test-split.t b/tests/test-split.t
--- a/tests/test-split.t
+++ b/tests/test-split.t
@@ -103,6 +103,12 @@
   abort: cannot split multiple revisions
   [255]
 
+This function splits a bit strangely primarily to avoid changing the behavior 
of
+the test after a bug was fixed with how split/commit --interactive handled
+`diff.unified=0`: when there were no context lines, it kept only the last diff
+hunk. When running split, this meant that runsplit was always recording three 
commits,
+one for each diff hunk, in reverse order (the base commit was the last diff 
hunk
+in the file).
   $ runsplit() {
   > cat > $TESTTMP/messages < split 1
@@ -113,23 +119,36 @@
   > EOF
   > cat < y
+  > n
+  > n
   > y
   > y
+  > n
   > y
   > y
   > y
   > EOF
   > }
 
   $ HGEDITOR=false runsplit
   diff --git a/a b/a
-  1 hunks, 1 lines changed
+  3 hunks, 3 lines changed
   examine changes to 'a'? [Ynesfdaq?] y
   
+  @@ -1,1 +1,1 @@
+  -1
+  +11
+  record change 1/3 to 'a'? [Ynesfdaq?] n
+  
+  @@ -3,1 +3,1 @@ 2
+  -3
+  +33
+  record change 2/3 to 'a'? [Ynesfdaq?] n
+  
   @@ -5,1 +5,1 @@ 4
   -5
   +55
-  record this change to 'a'? [Ynesfdaq?] y
+  record change 3/3 to 'a'? [Ynesfdaq?] y
   
   transaction abort!
   rollback completed
@@ -140,13 +159,23 @@
   $ HGEDITOR="\"$PYTHON\" $TESTTMP/editor.py"
   $ runsplit
   diff --git a/a b/a
-  1 hunks, 1 lines changed
+  3 hunks, 3 lines changed
   examine changes to 'a'? [Ynesfdaq?] y
   
+  @@ -1,1 +1,1 @@
+  -1
+  +11
+  record change 1/3 to 'a'? [Ynesfdaq?] n
+  
+  @@ -3,1 +3,1 @@ 2
+  -3
+  +33
+  record change 2/3 to 'a'? [Ynesfdaq?] n
+  
   @@ -5,1 +5,1 @@ 4
   -5
   +55
-  record this change to 'a'? [Ynesfdaq?] y
+  record change 3/3 to 'a'? [Ynesfdaq?] y
   
   EDITOR: HG: Splitting 1df0d5c5a3ab. Write commit message for the first split 
changeset.
   EDITOR: a2
@@ -160,13 +189,18 @@
   EDITOR: HG: changed a
   created new head
   diff --git a/a b/a
-  1 hunks, 1 lines changed
+  2 hunks, 2 lines changed
   examine changes to 'a'? [Ynesfdaq?] y
   
+  @@ -1,1 +1,1 @@
+  -1
+  +11
+  record change 1/2 to 'a'? [Ynesfdaq?] n
+  
   @@ -3,1 +3,1 @@ 2
   -3
   +33
-  record this change to 'a'? [Ynesfdaq?] y
+  record change 2/2 to 'a'? [Ynesfdaq?] y
   
   EDITOR: HG: Splitting 1df0d5c5a3ab. So far it has been split into:
   EDITOR: HG: - e704349bd21b: split 1
diff --git a/tests/test-commit-interactive.t b/tests/test-commit-interactive.t
--- a/tests/test-commit-interactive.t
+++ b/tests/test-commit-interactive.t
@@ -1807,3 +1807,38 @@
   n   0 -1 unset   subdir/f1
   $ hg status -A subdir/f1
   M subdir/f1
+
+Test diff.unified=0
+
+  $ hg init $TESTTMP/b
+  $ cd $TESTTMP/b
+  $ cat > foo < 1
+  > 2
+  > 3
+  > 4
+  > 5
+  > EOF
+  $ hg ci -qAm initial
+  $ cat > foo < 1
+  > change1
+  > 2
+  > 3
+  > change2
+  > 4
+  > 5
+  > EOF
+  $ printf 'y\ny\ny\n' | hg ci -im initial --config diff.unified=0
+  diff --git a/foo b/foo
+  2 hunks, 2 lines changed
+  examine changes to 'foo'? [Ynesfdaq?] y
+  
+  @@ -1,0 +2,1 @@ 1
+  +change1
+  record change 1/2 to 'foo'? [Ynesfdaq?] y
+  
+  @@ -3,0 +5,1 @@ 3
+  +change2
+  record change 2/2 to 'foo'? [Ynesfdaq?] y
+  
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -1609,6 +1609,7 @@
 self.headers = []
 
 def addrange(self, limits):
+self.addcontext([])
 fromstart, fromend, tostart, toend, proc = limits
 self.fromline = int(fromstart)
 self.toline = int(tostart)
@@ -1629,6 +1630,8 @@
 if self.context:
 self.before = self.context
 self.context = []
+if self.hunk:
+self.addcontext([])
 self.hunk = hunk
 
 def newfile(self, hdr):



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


D5936: addremove: respect ui.relative-paths

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
martinvonz added a comment.


  In https://phab.mercurial-scm.org/D5936#86976, @martinvonz wrote:
  
  > Ironic given the subject line that I missed this hunk:
  >
  >   diff --git a/mercurial/commands.py b/mercurial/commands.py
  >   --- a/mercurial/commands.py
  >   +++ b/mercurial/commands.py
  >   @@ -256,7 +256,7 @@ def addremove(ui, repo, *pats, **opts):
  >opts['similarity'] = '100'
  >matcher = scmutil.match(repo[None], pats, opts)
  >relative = scmutil.anypats(pats, opts)
  >   -uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=relative)
  >   +uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
  >return scmutil.addremove(repo, matcher, "", uipathfn, opts)
  >   
  >@command('annotate|blame',
  >
  >
  > I'll fold that in in flight since the commit is not yet public.
  
  
  Hmm, the same thing for `hg forget`. I'll fix that too if people don't mind.

REPOSITORY
  rHG Mercurial

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

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


D5936: addremove: respect ui.relative-paths

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
martinvonz added a comment.


  Ironic given the subject line that I missed this hunk:
  
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -256,7 +256,7 @@ def addremove(ui, repo, *pats, **opts):
 opts['similarity'] = '100'
 matcher = scmutil.match(repo[None], pats, opts)
 relative = scmutil.anypats(pats, opts)
-uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=relative)
+uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
 return scmutil.addremove(repo, matcher, "", uipathfn, opts)
 
 @command('annotate|blame',
  
  I'll fold that in in flight since the commit is not yet public.

REPOSITORY
  rHG Mercurial

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

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


mercurial@41683: 2 new changesets

2019-02-13 Thread Mercurial Commits
2 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/1ab6f5df263e
changeset:   41682:1ab6f5df263e
user:Boris Feld 
date:Fri Feb 08 18:26:35 2019 +0100
summary: test: stabilize test-wireproto-exchangev2.t flaky output

https://www.mercurial-scm.org/repo/hg/rev/5d383d9636d0
changeset:   41683:5d383d9636d0
bookmark:@
tag: tip
user:Jordi Gutiérrez Hermoso 
date:Tue Feb 12 17:10:31 2019 -0500
summary: walkchangerevs: obey allfiles parameter when taking the slow path

-- 
Repository URL: https://www.mercurial-scm.org/repo/hg
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5590: watchman: ignore some of watchman errors

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan abandoned this revision.
lothiraldan added a comment.


  Resent as https://phab.mercurial-scm.org/D5955

REPOSITORY
  rHG Mercurial

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

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


D5589: watchman: add the possibility to set the exact watchman binary location

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan abandoned this revision.
lothiraldan added a comment.


  Resent as https://phab.mercurial-scm.org/D5954

REPOSITORY
  rHG Mercurial

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

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


D5955: watchman: ignore some of watchman errors

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Don't display 'illegal_fstypes' errors. In environments with network
  filesystems, the error messages are quickly pilling up and polluting outputs.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/fsmonitor/__init__.py

CHANGE DETAILS

diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -180,7 +180,8 @@
 if isinstance(ex, watchmanclient.Unavailable):
 # experimental config: fsmonitor.verbose
 if ex.warn and ui.configbool('fsmonitor', 'verbose'):
-ui.warn(str(ex) + '\n')
+if 'illegal_fstypes' not in str(ex):
+ui.warn(str(ex) + '\n')
 if ex.invalidate:
 state.invalidate()
 # experimental config: fsmonitor.verbose



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


D5954: watchman: add the possibility to set the exact watchman binary location

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan created this revision.
Herald added subscribers: mercurial-devel, mjpieters.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This is necessary to make rolling releases of new watchman versions across
  users.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/fsmonitor/__init__.py
  hgext/fsmonitor/pywatchman/__init__.py
  hgext/fsmonitor/watchmanclient.py

CHANGE DETAILS

diff --git a/hgext/fsmonitor/watchmanclient.py 
b/hgext/fsmonitor/watchmanclient.py
--- a/hgext/fsmonitor/watchmanclient.py
+++ b/hgext/fsmonitor/watchmanclient.py
@@ -82,9 +82,11 @@
 try:
 if self._watchmanclient is None:
 self._firsttime = False
+watchman_exe = self._ui.configpath('fsmonitor', 'watchman_exe')
 self._watchmanclient = pywatchman.client(
 timeout=self._timeout,
-useImmutableBser=True)
+useImmutableBser=True,
+watchman_exe=watchman_exe)
 return self._watchmanclient.query(*watchmanargs)
 except pywatchman.CommandError as ex:
 if 'unable to resolve root' in ex.msg:
diff --git a/hgext/fsmonitor/pywatchman/__init__.py 
b/hgext/fsmonitor/pywatchman/__init__.py
--- a/hgext/fsmonitor/pywatchman/__init__.py
+++ b/hgext/fsmonitor/pywatchman/__init__.py
@@ -317,7 +317,7 @@
 """ local unix domain socket transport """
 sock = None
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = timeout
 
@@ -397,7 +397,7 @@
 class WindowsNamedPipeTransport(Transport):
 """ connect to a named pipe """
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = int(math.ceil(timeout * 1000))
 self._iobuf = None
@@ -563,9 +563,10 @@
 proc = None
 closed = True
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = timeout
+self.watchman_exe = watchman_exe
 
 def close(self):
 if self.proc:
@@ -579,7 +580,7 @@
 if self.proc:
 return self.proc
 args = [
-'watchman',
+self.watchman_exe,
 '--sockname={0}'.format(self.sockpath),
 '--logfile=/BOGUS',
 '--statefile=/BOGUS',
@@ -756,17 +757,20 @@
 unilateral = ['log', 'subscription']
 tport = None
 useImmutableBser = None
+watchman_exe = None
 
 def __init__(self,
  sockpath=None,
  timeout=1.0,
  transport=None,
  sendEncoding=None,
  recvEncoding=None,
- useImmutableBser=False):
+ useImmutableBser=False,
+ watchman_exe=None):
 self.sockpath = sockpath
 self.timeout = timeout
 self.useImmutableBser = useImmutableBser
+self.watchman_exe = watchman_exe
 
 if inspect.isclass(transport) and issubclass(transport, Transport):
 self.transport = transport
@@ -817,7 +821,7 @@
 if path:
 return path
 
-cmd = ['watchman', '--output-encoding=bser', 'get-sockname']
+cmd = [self.watchman_exe, '--output-encoding=bser', 'get-sockname']
 try:
 args = dict(stdout=subprocess.PIPE,
 stderr=subprocess.PIPE,
@@ -858,7 +862,7 @@
 if self.sockpath is None:
 self.sockpath = self._resolvesockname()
 
-self.tport = self.transport(self.sockpath, self.timeout)
+self.tport = self.transport(self.sockpath, self.timeout, 
self.watchman_exe)
 self.sendConn = self.sendCodec(self.tport)
 self.recvConn = self.recvCodec(self.tport)
 
diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -161,6 +161,9 @@
 configitem('fsmonitor', 'blacklistusers',
 default=list,
 )
+configitem('fsmonitor', 'watchman_exe',
+default='watchman',
+)
 configitem('fsmonitor', 'verbose',
 default=True,
 )



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


D5587: watchman: detect nested mercurial repositories and abort

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan updated this revision to Diff 14075.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5587?vs=13645=14075

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

AFFECTED FILES
  hgext/fsmonitor/__init__.py

CHANGE DETAILS

diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -367,6 +367,9 @@
 fexists = entry['exists']
 kind = getkind(fmode)
 
+if '/.hg/' in fname or fname.endswith('/.hg'):
+return bail('nested-repo-detected')
+
 if not fexists:
 # if marked as deleted and we don't already have a change
 # record, mark it as deleted.  If we already have an entry
@@ -740,6 +743,14 @@
 repo, node, branchmerge, force, ancestor, mergeancestor,
 labels, matcher, **kwargs)
 
+def repo_has_depth_one_nested_repo(repo):
+for f in repo.wvfs.listdir():
+if os.path.isdir(os.path.join(repo.root, f, '.hg')):
+msg = 'fsmonitor: sub-repository %r detected, fsmonitor disabled\n'
+repo.ui.debug(msg % f)
+return True
+return False
+
 def reposetup(ui, repo):
 # We don't work with largefiles or inotify
 exts = extensions.enabled()
@@ -757,6 +768,9 @@
 if repo.wvfs.exists('.hgsubstate') or repo.wvfs.exists('.hgsub'):
 return
 
+if repo_has_depth_one_nested_repo(repo):
+return
+
 fsmonitorstate = state.state(repo)
 if fsmonitorstate.mode == 'off':
 return



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


D5590: watchman: ignore some of watchman errors

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan updated this revision to Diff 14074.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5590?vs=14071=14074

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

AFFECTED FILES
  hgext/fsmonitor/__init__.py

CHANGE DETAILS

diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -180,7 +180,8 @@
 if isinstance(ex, watchmanclient.Unavailable):
 # experimental config: fsmonitor.verbose
 if ex.warn and ui.configbool('fsmonitor', 'verbose'):
-ui.warn(str(ex) + '\n')
+if 'illegal_fstypes' not in str(ex):
+ui.warn(str(ex) + '\n')
 if ex.invalidate:
 state.invalidate()
 # experimental config: fsmonitor.verbose



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


D5589: watchman: add the possibility to set the exact watchman binary location

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan updated this revision to Diff 14073.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5589?vs=14070=14073

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

AFFECTED FILES
  hgext/fsmonitor/__init__.py
  hgext/fsmonitor/pywatchman/__init__.py
  hgext/fsmonitor/watchmanclient.py

CHANGE DETAILS

diff --git a/hgext/fsmonitor/watchmanclient.py 
b/hgext/fsmonitor/watchmanclient.py
--- a/hgext/fsmonitor/watchmanclient.py
+++ b/hgext/fsmonitor/watchmanclient.py
@@ -82,9 +82,11 @@
 try:
 if self._watchmanclient is None:
 self._firsttime = False
+watchman_exe = self._ui.configpath('fsmonitor', 'watchman_exe')
 self._watchmanclient = pywatchman.client(
 timeout=self._timeout,
-useImmutableBser=True)
+useImmutableBser=True,
+watchman_exe=watchman_exe)
 return self._watchmanclient.query(*watchmanargs)
 except pywatchman.CommandError as ex:
 if 'unable to resolve root' in ex.msg:
diff --git a/hgext/fsmonitor/pywatchman/__init__.py 
b/hgext/fsmonitor/pywatchman/__init__.py
--- a/hgext/fsmonitor/pywatchman/__init__.py
+++ b/hgext/fsmonitor/pywatchman/__init__.py
@@ -317,7 +317,7 @@
 """ local unix domain socket transport """
 sock = None
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = timeout
 
@@ -397,7 +397,7 @@
 class WindowsNamedPipeTransport(Transport):
 """ connect to a named pipe """
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = int(math.ceil(timeout * 1000))
 self._iobuf = None
@@ -563,9 +563,10 @@
 proc = None
 closed = True
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = timeout
+self.watchman_exe = watchman_exe
 
 def close(self):
 if self.proc:
@@ -579,7 +580,7 @@
 if self.proc:
 return self.proc
 args = [
-'watchman',
+self.watchman_exe,
 '--sockname={0}'.format(self.sockpath),
 '--logfile=/BOGUS',
 '--statefile=/BOGUS',
@@ -756,17 +757,20 @@
 unilateral = ['log', 'subscription']
 tport = None
 useImmutableBser = None
+watchman_exe = None
 
 def __init__(self,
  sockpath=None,
  timeout=1.0,
  transport=None,
  sendEncoding=None,
  recvEncoding=None,
- useImmutableBser=False):
+ useImmutableBser=False,
+ watchman_exe=None):
 self.sockpath = sockpath
 self.timeout = timeout
 self.useImmutableBser = useImmutableBser
+self.watchman_exe = watchman_exe
 
 if inspect.isclass(transport) and issubclass(transport, Transport):
 self.transport = transport
@@ -817,7 +821,7 @@
 if path:
 return path
 
-cmd = ['watchman', '--output-encoding=bser', 'get-sockname']
+cmd = [self.watchman_exe, '--output-encoding=bser', 'get-sockname']
 try:
 args = dict(stdout=subprocess.PIPE,
 stderr=subprocess.PIPE,
@@ -858,7 +862,7 @@
 if self.sockpath is None:
 self.sockpath = self._resolvesockname()
 
-self.tport = self.transport(self.sockpath, self.timeout)
+self.tport = self.transport(self.sockpath, self.timeout, 
self.watchman_exe)
 self.sendConn = self.sendCodec(self.tport)
 self.recvConn = self.recvCodec(self.tport)
 
diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -161,6 +161,9 @@
 configitem('fsmonitor', 'blacklistusers',
 default=list,
 )
+configitem('fsmonitor', 'watchman_exe',
+default='watchman',
+)
 configitem('fsmonitor', 'verbose',
 default=True,
 )



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


D5946: server: allow customizing the default repo filter

2019-02-13 Thread joerg.sonnenberger (Joerg Sonnenberger)
joerg.sonnenberger updated this revision to Diff 14072.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5946?vs=14047=14072

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

AFFECTED FILES
  mercurial/configitems.py
  mercurial/help/config.txt
  mercurial/wireprotov1server.py
  mercurial/wireprotov2server.py
  tests/test-server-view.t
  tests/test-wireproto.py

CHANGE DETAILS

diff --git a/tests/test-wireproto.py b/tests/test-wireproto.py
--- a/tests/test-wireproto.py
+++ b/tests/test-wireproto.py
@@ -78,6 +78,9 @@
 yield unmangle(f.value)
 
 class serverrepo(object):
+def __init__(self, ui):
+self.ui = ui
+
 def greet(self, name):
 return b"Hello, " + name
 
@@ -94,7 +97,7 @@
 
 wireprotov1server.commands[b'greet'] = (greet, b'name')
 
-srv = serverrepo()
+srv = serverrepo(uimod.ui())
 clt = clientpeer(srv, uimod.ui())
 
 def printb(data, end=b'\n'):
diff --git a/tests/test-server-view.t b/tests/test-server-view.t
new file mode 100644
--- /dev/null
+++ b/tests/test-server-view.t
@@ -0,0 +1,38 @@
+  $ hg init test
+  $ cd test
+  $ hg debugbuilddag '+2'
+  $ hg phase --public 0
+
+  $ hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
+  $ cat hg.pid >> $DAEMON_PIDS
+  $ cd ..
+  $ hg init test2
+  $ cd test2
+  $ hg incoming http://foo:xyzzy@localhost:$HGPORT/
+  comparing with http://foo:***@localhost:$HGPORT/
+  changeset:   0:1ea73414a91b
+  user:debugbuilddag
+  date:Thu Jan 01 00:00:00 1970 +
+  summary: r0
+  
+  changeset:   1:66f7d451a68b
+  tag: tip
+  user:debugbuilddag
+  date:Thu Jan 01 00:00:01 1970 +
+  summary: r1
+  
+  $ killdaemons.py
+
+  $ cd ../test
+  $ hg --config server.view=immutable serve -p $HGPORT -d --pid-file=hg.pid -E 
errors.log
+  $ cat hg.pid >> $DAEMON_PIDS
+  $ cd ../test2
+  $ hg incoming http://foo:xyzzy@localhost:$HGPORT/
+  comparing with http://foo:***@localhost:$HGPORT/
+  changeset:   0:1ea73414a91b
+  tag: tip
+  user:debugbuilddag
+  date:Thu Jan 01 00:00:00 1970 +
+  summary: r0
+  
+  $ killdaemons.py
diff --git a/mercurial/wireprotov2server.py b/mercurial/wireprotov2server.py
--- a/mercurial/wireprotov2server.py
+++ b/mercurial/wireprotov2server.py
@@ -342,7 +342,8 @@
  action)
 
 def getdispatchrepo(repo, proto, command):
-return repo.filtered('served')
+viewconfig = repo.ui.config('server', 'view')
+return repo.filtered(viewconfig)
 
 def dispatch(repo, proto, command, redirect):
 """Run a wire protocol command.
diff --git a/mercurial/wireprotov1server.py b/mercurial/wireprotov1server.py
--- a/mercurial/wireprotov1server.py
+++ b/mercurial/wireprotov1server.py
@@ -64,7 +64,8 @@
 extensions that need commands to operate on different repo views under
 specialized circumstances.
 """
-return repo.filtered('served')
+viewconfig = repo.ui.config('server', 'view')
+return repo.filtered(viewconfig)
 
 def dispatch(repo, proto, command):
 repo = getdispatchrepo(repo, proto, command)
@@ -166,7 +167,6 @@
 @wireprotocommand('batch', 'cmds *', permission='pull')
 def batch(repo, proto, cmds, others):
 unescapearg = wireprototypes.unescapebatcharg
-repo = repo.filtered("served")
 res = []
 for pair in cmds.split(';'):
 op, args = pair.split(' ', 1)
diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -1990,6 +1990,12 @@
 
 See also ``server.zliblevel``.
 
+``view``
+Repository filter used when exchanging revisions with the peer.
+
+The default view (``served``) excludes secret and hidden changesets.
+Another useful value is ``immutable`` (no draft, secret or hidden 
changesets).
+
 ``smtp``
 
 
diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -1029,6 +1029,9 @@
 coreconfigitem('server', 'uncompressedallowsecret',
 default=False,
 )
+coreconfigitem('server', 'view',
+default='served',
+)
 coreconfigitem('server', 'validate',
 default=False,
 )



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


D5589: watchman: add the possibility to set the exact watchman binary location

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan updated this revision to Diff 14070.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5589?vs=13414=14070

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

AFFECTED FILES
  hgext/fsmonitor/__init__.py
  hgext/fsmonitor/pywatchman/__init__.py
  hgext/fsmonitor/watchmanclient.py

CHANGE DETAILS

diff --git a/hgext/fsmonitor/watchmanclient.py 
b/hgext/fsmonitor/watchmanclient.py
--- a/hgext/fsmonitor/watchmanclient.py
+++ b/hgext/fsmonitor/watchmanclient.py
@@ -82,9 +82,11 @@
 try:
 if self._watchmanclient is None:
 self._firsttime = False
+watchman_exe = self._ui.configpath('fsmonitor', 'watchman_exe')
 self._watchmanclient = pywatchman.client(
 timeout=self._timeout,
-useImmutableBser=True)
+useImmutableBser=True,
+watchman_exe=watchman_exe)
 return self._watchmanclient.query(*watchmanargs)
 except pywatchman.CommandError as ex:
 if 'unable to resolve root' in ex.msg:
diff --git a/hgext/fsmonitor/pywatchman/__init__.py 
b/hgext/fsmonitor/pywatchman/__init__.py
--- a/hgext/fsmonitor/pywatchman/__init__.py
+++ b/hgext/fsmonitor/pywatchman/__init__.py
@@ -317,7 +317,7 @@
 """ local unix domain socket transport """
 sock = None
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = timeout
 
@@ -397,7 +397,7 @@
 class WindowsNamedPipeTransport(Transport):
 """ connect to a named pipe """
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = int(math.ceil(timeout * 1000))
 self._iobuf = None
@@ -563,9 +563,10 @@
 proc = None
 closed = True
 
-def __init__(self, sockpath, timeout):
+def __init__(self, sockpath, timeout, watchman_exe):
 self.sockpath = sockpath
 self.timeout = timeout
+self.watchman_exe = watchman_exe
 
 def close(self):
 if self.proc:
@@ -579,7 +580,7 @@
 if self.proc:
 return self.proc
 args = [
-'watchman',
+self.watchman_exe,
 '--sockname={0}'.format(self.sockpath),
 '--logfile=/BOGUS',
 '--statefile=/BOGUS',
@@ -756,17 +757,20 @@
 unilateral = ['log', 'subscription']
 tport = None
 useImmutableBser = None
+watchman_exe = None
 
 def __init__(self,
  sockpath=None,
  timeout=1.0,
  transport=None,
  sendEncoding=None,
  recvEncoding=None,
- useImmutableBser=False):
+ useImmutableBser=False,
+ watchman_exe=None):
 self.sockpath = sockpath
 self.timeout = timeout
 self.useImmutableBser = useImmutableBser
+self.watchman_exe = watchman_exe
 
 if inspect.isclass(transport) and issubclass(transport, Transport):
 self.transport = transport
@@ -817,7 +821,7 @@
 if path:
 return path
 
-cmd = ['watchman', '--output-encoding=bser', 'get-sockname']
+cmd = [self.watchman_exe, '--output-encoding=bser', 'get-sockname']
 try:
 args = dict(stdout=subprocess.PIPE,
 stderr=subprocess.PIPE,
@@ -858,7 +862,7 @@
 if self.sockpath is None:
 self.sockpath = self._resolvesockname()
 
-self.tport = self.transport(self.sockpath, self.timeout)
+self.tport = self.transport(self.sockpath, self.timeout, 
self.watchman_exe)
 self.sendConn = self.sendCodec(self.tport)
 self.recvConn = self.recvCodec(self.tport)
 
diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -164,6 +164,9 @@
 configitem('fsmonitor', 'enable_on_non_interactive',
 default=True,
 )
+configitem('fsmonitor', 'watchman_exe',
+default='watchman',
+)
 configitem('fsmonitor', 'verbose',
 default=True,
 )



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


D5590: watchman: ignore some of watchman errors

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan updated this revision to Diff 14071.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5590?vs=13415=14071

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

AFFECTED FILES
  hgext/fsmonitor/__init__.py

CHANGE DETAILS

diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -183,7 +183,8 @@
 if isinstance(ex, watchmanclient.Unavailable):
 # experimental config: fsmonitor.verbose
 if ex.warn and ui.configbool('fsmonitor', 'verbose'):
-ui.warn(str(ex) + '\n')
+if 'illegal_fstypes' not in str(ex):
+ui.warn(str(ex) + '\n')
 if ex.invalidate:
 state.invalidate()
 # experimental config: fsmonitor.verbose



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


D5588: watchman: disable fsmonitor when running non-interactively

2019-02-13 Thread lothiraldan (Boris Feld)
lothiraldan updated this revision to Diff 14069.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5588?vs=13413=14069

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

AFFECTED FILES
  hgext/fsmonitor/__init__.py

CHANGE DETAILS

diff --git a/hgext/fsmonitor/__init__.py b/hgext/fsmonitor/__init__.py
--- a/hgext/fsmonitor/__init__.py
+++ b/hgext/fsmonitor/__init__.py
@@ -161,6 +161,9 @@
 configitem('fsmonitor', 'blacklistusers',
 default=list,
 )
+configitem('fsmonitor', 'enable_on_non_interactive',
+default=True,
+)
 configitem('fsmonitor', 'verbose',
 default=True,
 )
@@ -760,6 +763,24 @@
   'extension and has been disabled.\n') % ext)
 return
 
+enabled = None
+if 'HGWATCHMAN_ENABLE' in encoding.environ:
+enabled = encoding.environ['HGWATCHMAN_ENABLE'].lower()
+
+if enabled == 'true' or enabled == '':
+pass
+elif enabled == 'false':
+ui.debug('fsmonitor: disabled through HGWATCHMAN_ENABLE env variable')
+return
+else:
+interactive = ui.interactive()
+enable_on_non_interactive = ui.configbool(
+'fsmonitor', 'enable_on_non_interactive'
+)
+if not interactive and not enable_on_non_interactive:
+ui.debug('fsmonitor: disabled for non-interactive commands')
+return
+
 if repo.local():
 # We don't work with subrepos either.
 #



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


[PATCH 2 of 2 RESENT] rewriting: add an option for rewrite commands to use the archived phase

2019-02-13 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1546394872 -3600
#  Wed Jan 02 03:07:52 2019 +0100
# Node ID 9939d8e412e3e440f3b564fb96c187745d7a008c
# Parent  61ec4a834e2c88056ff47c0d3a7ff3bcb0f0d912
# EXP-Topic archived-phase-UX
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
9939d8e412e3
rewriting: add an option for rewrite commands to use the archived phase

Using the archived phase for cleanup provide the same effect than stripping,
but in a faster, append-only way.

We keep the feature experimental for now until it gets a bit more testing.

diff --git a/mercurial/configitems.py b/mercurial/configitems.py
--- a/mercurial/configitems.py
+++ b/mercurial/configitems.py
@@ -470,6 +470,9 @@ coreconfigitem('experimental', 'bundleco
 coreconfigitem('experimental', 'changegroup3',
 default=False,
 )
+coreconfigitem('experimental', 'cleanup-as-archived',
+default=False,
+)
 coreconfigitem('experimental', 'clientcompressionengines',
 default=list,
 )
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -1014,6 +1014,7 @@ def cleanupnodes(repo, replacements, ope
 for phase, nodes in toadvance.items():
 phases.advanceboundary(repo, tr, phase, nodes)
 
+mayusearchived = repo.ui.config('experimental', 'cleanup-as-archived')
 # Obsolete or strip nodes
 if obsolete.isenabled(repo, obsolete.createmarkersopt):
 # If a node is already obsoleted, and we want to obsolete it
@@ -1031,6 +1032,17 @@ def cleanupnodes(repo, replacements, ope
 if rels:
 obsolete.createmarkers(repo, rels, operation=operation,
metadata=metadata)
+elif phases.supportinternal(repo) and mayusearchived:
+# this assume we do not have "unstable" nodes above the cleaned 
ones
+allreplaced = set()
+for ns in replacements.keys():
+allreplaced.update(ns)
+if backup:
+from . import repair # avoid import cycle
+node = min(allreplaced, key=repo.changelog.rev)
+repair.backupbundle(repo, allreplaced, allreplaced, node,
+operation)
+phases.retractboundary(repo, tr, phases.archived, allreplaced)
 else:
 from . import repair # avoid import cycle
 tostrip = list(n for ns in replacements for n in ns)
diff --git a/tests/test-phase-archived.t b/tests/test-phase-archived.t
--- a/tests/test-phase-archived.t
+++ b/tests/test-phase-archived.t
@@ -75,3 +75,69 @@ Test that bundle can unarchive a changes
  date:Thu Jan 01 00:00:00 1970 +
  summary: root
   
+
+Test that history rewriting command can use the archived phase when allowed to
+--
+
+  $ hg up 'desc(unbundletesting)'
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo bar >> a
+  $ hg commit --amend --config experimental.cleanup-as-archived=yes
+  $ hg log -G
+  @  changeset:   2:d1e73e428f29
+  |  tag: tip
+  |  parent:  0:c1863a3840c6
+  |  user:test
+  |  date:Thu Jan 01 00:00:00 1970 +
+  |  summary: unbundletesting
+  |
+  o  changeset:   0:c1863a3840c6
+ user:test
+ date:Thu Jan 01 00:00:00 1970 +
+ summary: root
+  
+  $ hg log -G --hidden
+  @  changeset:   2:d1e73e428f29
+  |  tag: tip
+  |  parent:  0:c1863a3840c6
+  |  user:test
+  |  date:Thu Jan 01 00:00:00 1970 +
+  |  summary: unbundletesting
+  |
+  | o  changeset:   1:883aadbbf309
+  |/   user:test
+  |date:Thu Jan 01 00:00:00 1970 +
+  |summary: unbundletesting
+  |
+  o  changeset:   0:c1863a3840c6
+ user:test
+ date:Thu Jan 01 00:00:00 1970 +
+ summary: root
+  
+  $ ls -1 .hg/strip-backup/
+  883aadbbf309-efc55adc-amend.hg
+  883aadbbf309-efc55adc-backup.hg
+  $ hg unbundle .hg/strip-backup/883aadbbf309*amend.hg
+  adding changesets
+  adding manifests
+  adding file changes
+  added 0 changesets with 0 changes to 1 files
+  (run 'hg update' to get a working copy)
+  $ hg log -G
+  @  changeset:   2:d1e73e428f29
+  |  tag: tip
+  |  parent:  0:c1863a3840c6
+  |  user:test
+  |  date:Thu Jan 01 00:00:00 1970 +
+  |  summary: unbundletesting
+  |
+  | o  changeset:   1:883aadbbf309
+  |/   user:test
+  |date:Thu Jan 01 00:00:00 1970 +
+  |summary: unbundletesting
+  |
+  o  changeset:   0:c1863a3840c6
+ user:test
+ date:Thu Jan 01 00:00:00 1970 +
+ summary: root
+  
___
Mercurial-devel mailing list

[PATCH 1 of 2 RESENT] strip: introduce a soft strip option

2019-02-13 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1539697680 -7200
#  Tue Oct 16 15:48:00 2018 +0200
# Node ID 61ec4a834e2c88056ff47c0d3a7ff3bcb0f0d912
# Parent  61415361e90684a8c7a031413e9182f51937c2e7
# EXP-Topic archived-phase-UX
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
61ec4a834e2c
strip: introduce a soft strip option

This is the first user-accessible way to use the archived phase introduced in
4.8. This implements a feature discussed during the Stockholm sprint, using
the archived phase for hiding changesets.

The archived phase behaves exactly as stripping: changesets are no longer
visible, but pulling/unbundling them will make then reappear. The only notable
difference is that unlike hard stripping, soft stripping does not affect
obsmarkers.

The next changeset will make use of the archived phase for history rewriting
command. However, having a way to manually trigger the feature first seems a
necessary step before exposing users to this phase; there is a way to
un-archived changesets (unbundling), so there must be a way to archive them
again.

Adding a flag to strip is a good way to provide access to the feature without
taking a too big risk on the final UI we want. The flag is experimental so it
won't be exposed by default.

Using the archived phase is faster and less traumatic for the repository than
actually stripping changesets.

diff --git a/hgext/strip.py b/hgext/strip.py
--- a/hgext/strip.py
+++ b/hgext/strip.py
@@ -76,7 +76,8 @@ def _findupdatetarget(repo, nodes):
 
 return unode
 
-def strip(ui, repo, revs, update=True, backup=True, force=None, 
bookmarks=None):
+def strip(ui, repo, revs, update=True, backup=True, force=None, bookmarks=None,
+  soft=False):
 with repo.wlock(), repo.lock():
 
 if update:
@@ -85,7 +86,10 @@ def strip(ui, repo, revs, update=True, b
 hg.clean(repo, urev)
 repo.dirstate.write(repo.currenttransaction())
 
-repair.strip(ui, repo, revs, backup)
+if soft:
+repair.softstrip(ui, repo, revs, backup)
+else:
+repair.strip(ui, repo, revs, backup)
 
 repomarks = repo._bookmarks
 if bookmarks:
@@ -110,7 +114,10 @@ def strip(ui, repo, revs, update=True, b
   ('k', 'keep', None, _("do not modify working directory during "
 "strip")),
   ('B', 'bookmark', [], _("remove revs only reachable from given"
-  " bookmark"), _('BOOKMARK'))],
+  " bookmark"), _('BOOKMARK')),
+  ('', 'soft', None,
+  _("simply drop changesets from visible history (EXPERIMENTAL)")),
+ ],
   _('hg strip [-k] [-f] [-B bookmark] [-r] REV...'),
   helpcategory=command.CATEGORY_MAINTENANCE)
 def stripcmd(ui, repo, *revs, **opts):
@@ -235,6 +242,7 @@ def stripcmd(ui, repo, *revs, **opts):
 
 
 strip(ui, repo, revs, backup=backup, update=update,
-  force=opts.get('force'), bookmarks=bookmarks)
+  force=opts.get('force'), bookmarks=bookmarks,
+  soft=opts['soft'])
 
 return 0
diff --git a/mercurial/repair.py b/mercurial/repair.py
--- a/mercurial/repair.py
+++ b/mercurial/repair.py
@@ -252,6 +252,24 @@ def strip(ui, repo, nodelist, backup=Tru
 # extensions can use it
 return backupfile
 
+def softstrip(ui, repo, nodelist, backup=True, topic='backup'):
+"""perform a "soft" strip using the archived phase"""
+tostrip = [c.node() for c in repo.set('sort(%ln::)', nodelist)]
+if not tostrip:
+return None
+
+newbmtarget, updatebm = _bookmarkmovements(repo, tostrip)
+if backup:
+node = tostrip[0]
+backupfile = _createstripbackup(repo, tostrip, node, topic)
+
+with repo.transaction('strip') as tr:
+phases.retractboundary(repo, tr, phases.archived, tostrip)
+bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm]
+repo._bookmarks.applychanges(repo, tr, bmchanges)
+return backupfile
+
+
 def _bookmarkmovements(repo, tostrip):
 # compute necessary bookmark movement
 bm = repo._bookmarks
diff --git a/tests/test-phase-archived.t b/tests/test-phase-archived.t
new file mode 100644
--- /dev/null
+++ b/tests/test-phase-archived.t
@@ -0,0 +1,77 @@
+=
+Test features and behaviors related to the archived phase
+=
+
+  $ cat << EOF >> $HGRCPATH
+  > [format]
+  > internal-phase=yes
+  > [extensions]
+  > strip=
+  > [experimental]
+  > EOF
+
+  $ hg init repo
+  $ cd repo
+  $ echo  root > a
+  $ hg add a
+  $ hg ci -m 'root'
+
+Test that bundle can unarchive a changeset
+--
+
+  $ echo foo >> a
+  $ hg st
+  M a
+  $ hg ci -m 'unbundletesting'
+  $ hg log -G
+  @  changeset:   

Re: [PATCH 3 of 4 V2] changelog: prefilter in headrevs()

2019-02-13 Thread Yuya Nishihara
On Wed, 13 Feb 2019 12:47:56 +0100, Georges Racinet wrote:
> # HG changeset patch
> # User Georges Racinet 
> # Date 1547815081 -3600
> #  Fri Jan 18 13:38:01 2019 +0100
> # Node ID eae29e210636ee44851e0caa385097a090c60af8
> # Parent  956c5b54b4ce3e8decf5243a7f73c6f9a06f1229
> # EXP-Topic revset.predicates
> changelog: prefilter in headrevs()

Queued the first two patches, thanks.

> +def _checknofilteredgenrevs(self, revs):
> +"""rewrap 'revs' generator to include check for filtered revisions
> +
> +This does not consume the incoming generator.
> +"""
> +filteredrevs = self.filteredrevs
> +for r in revs:
> +if r in filteredrevs:
> +raise error.FilteredIndexError(r)
> +yield r
> +
> +def _checknofilteredinrevs(self, revs):
> +"""raise the appropriate error if 'revs' contains a filtered revision
> +
> +This returns a version of 'revs' to be used by the caller, that works
> +for all cases, including lazy ones
> +"""
> +safehasattr = util.safehasattr
> +if safehasattr(revs, '__next__'):
> +# Note that inspect.isgenerator() is not true for iterators,
> +# and that calling even implicitely iter() on a iterator does not
> +# clone it
> +return self._checknofilteredgenrevs(revs)
> +
> +filteredrevs = self.filteredrevs
> +if safehasattr(revs, 'first'):  # smartset
> +offenders = revs & filteredrevs
> +else:
> +offenders = filteredrevs.intersection(revs)
> +
> +for rev in offenders:
> +raise error.FilteredIndexError(rev)
> +return revs

Do we need this complexity to handle various types of 'revs' differently?

IIUC, revlog.headrevs(revs) is just forwarded to dagop.headrevs(revs), where
'revs' is first converted to a set, and then iterated. Which means 'revs'
can't be an iterator, and the order doesn't basically matter.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5953: revset: improve documentation on expectsize()

2019-02-13 Thread navaneeth.suresh (Navaneeth Suresh)
navaneeth.suresh updated this revision to Diff 14068.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5953?vs=14063=14068

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

AFFECTED FILES
  mercurial/revset.py

CHANGE DETAILS

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -817,7 +817,12 @@
 
 @predicate('expectsize(set[, size])', safe=True, takeorder=True)
 def expectrevsetsize(repo, subset, x, order):
-"""Abort if the revset doesn't expect given size"""
+"""Return the given revset if size matches the revset size.
+Abort if the revset doesn't expect given size.
+size can either be an integer range or an integer.
+
+For example, ``expectsize(0:1, 3:5)`` will abort as revset size is 2 and
+2 is not between 3 and 5 inclusive."""
 args = getargsdict(x, 'expect', 'set size')
 minsize = 0
 maxsize = len(repo)+1



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


D5949: debugpathcopies: fix typo in synopsis

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGb738093d4b8f: debugpathcopies: fix typo in synopsis 
(authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5949?vs=14052=14066

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

AFFECTED FILES
  mercurial/debugcommands.py

CHANGE DETAILS

diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -1808,7 +1808,7 @@
 
 @command('debugpathcopies',
  cmdutil.walkopts,
- 'hg debugcopies REV1 REV2 [FILE]',
+ 'hg debugpathcopies REV1 REV2 [FILE]',
  inferrepo=True)
 def debugpathcopies(ui, repo, rev1, rev2, *pats, **opts):
 """show copies between two revisions"""



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


D5417: rust: translated random test of missingancestors

2019-02-13 Thread gracinet (Georges Racinet)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG9370f4843084: rust: translated random test of 
missingancestors (authored by gracinet, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5417?vs=14044=14067

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

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/src/lib.rs
  rust/hg-core/tests/test_missing_ancestors.rs

CHANGE DETAILS

diff --git a/rust/hg-core/tests/test_missing_ancestors.rs 
b/rust/hg-core/tests/test_missing_ancestors.rs
new file mode 100644
--- /dev/null
+++ b/rust/hg-core/tests/test_missing_ancestors.rs
@@ -0,0 +1,340 @@
+extern crate hg;
+extern crate rand;
+extern crate rand_pcg;
+
+use hg::testing::VecGraph;
+use hg::Revision;
+use hg::*;
+use rand::distributions::{Distribution, LogNormal, Uniform};
+use rand::{thread_rng, Rng, RngCore, SeedableRng};
+use std::cmp::min;
+use std::collections::HashSet;
+use std::env;
+use std::fmt::Debug;
+
+fn build_random_graph(
+nodes_opt: Option,
+rootprob_opt: Option,
+mergeprob_opt: Option,
+prevprob_opt: Option,
+) -> VecGraph {
+let nodes = nodes_opt.unwrap_or(100);
+let rootprob = rootprob_opt.unwrap_or(0.05);
+let mergeprob = mergeprob_opt.unwrap_or(0.2);
+let prevprob = prevprob_opt.unwrap_or(0.7);
+
+let mut rng = thread_rng();
+let mut vg: VecGraph = Vec::with_capacity(nodes);
+for i in 0..nodes {
+if i == 0 || rng.gen_bool(rootprob) {
+vg.push([NULL_REVISION, NULL_REVISION])
+} else if i == 1 {
+vg.push([0, NULL_REVISION])
+} else if rng.gen_bool(mergeprob) {
+let p1 = {
+if i == 2 || rng.gen_bool(prevprob) {
+(i - 1) as Revision
+} else {
+rng.gen_range(0, i - 1) as Revision
+}
+};
+// p2 is a random revision lower than i and different from p1
+let mut p2 = rng.gen_range(0, i - 1) as Revision;
+if p2 >= p1 {
+p2 = p2 + 1;
+}
+vg.push([p1, p2]);
+} else if rng.gen_bool(prevprob) {
+vg.push([(i - 1) as Revision, NULL_REVISION])
+} else {
+vg.push([rng.gen_range(0, i - 1) as Revision, NULL_REVISION])
+}
+}
+vg
+}
+
+/// Compute the ancestors set of all revisions of a VecGraph
+fn ancestors_sets(vg: ) -> Vec> {
+let mut ancs: Vec> = Vec::new();
+for i in 0..vg.len() {
+let mut ancs_i = HashSet::new();
+ancs_i.insert(i as Revision);
+for p in vg[i].iter().cloned() {
+if p != NULL_REVISION {
+ancs_i.extend([p as usize]);
+}
+}
+ancs.push(ancs_i);
+}
+ancs
+}
+
+#[derive(Clone, Debug)]
+enum MissingAncestorsAction {
+InitialBases(HashSet),
+AddBases(HashSet),
+RemoveAncestorsFrom(HashSet),
+MissingAncestors(HashSet),
+}
+
+/// An instrumented naive yet obviously correct implementation
+///
+/// It also records all its actions for easy reproduction for replay
+/// of problematic cases
+struct NaiveMissingAncestors<'a> {
+ancestors_sets: &'a Vec>,
+graph: &'a VecGraph, // used for error reporting only
+bases: HashSet,
+history: Vec,
+// for error reporting, assuming we are in a random test
+random_seed: String,
+}
+
+impl<'a> NaiveMissingAncestors<'a> {
+fn new(
+graph: &'a VecGraph,
+ancestors_sets: &'a Vec>,
+bases: ,
+random_seed: ,
+) -> Self {
+Self {
+ancestors_sets: ancestors_sets,
+bases: bases.clone(),
+graph: graph,
+history: vec![MissingAncestorsAction::InitialBases(bases.clone())],
+random_seed: random_seed.into(),
+}
+}
+
+fn add_bases( self, new_bases: HashSet) {
+self.bases.extend(_bases);
+self.history
+.push(MissingAncestorsAction::AddBases(new_bases))
+}
+
+fn remove_ancestors_from( self, revs:  HashSet) {
+revs.remove(_REVISION);
+self.history
+.push(MissingAncestorsAction::RemoveAncestorsFrom(revs.clone()));
+for base in self.bases.iter().cloned() {
+if base != NULL_REVISION {
+for rev in _sets[base as usize] {
+revs.remove();
+}
+}
+}
+}
+
+fn missing_ancestors(
+ self,
+revs: impl IntoIterator,
+) -> Vec {
+let revs_as_set: HashSet = revs.into_iter().collect();
+
+let mut missing: HashSet = HashSet::new();
+for rev in revs_as_set.iter().cloned() {
+if rev != NULL_REVISION {
+missing.extend(_sets[rev as usize])
+}
+}
+self.history
+.push(MissingAncestorsAction::MissingAncestors(revs_as_set));
+
+  

D5948: debugrename: don't require at least one path

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGa04e0ec65ce3: debugrename: dont require at least one 
path (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5948?vs=14051=14065

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

AFFECTED FILES
  mercurial/debugcommands.py

CHANGE DETAILS

diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -2010,13 +2010,13 @@
 
 @command('debugrename',
 [('r', 'rev', '', _('revision to debug'), _('REV'))],
-_('[-r REV] FILE'))
-def debugrename(ui, repo, file1, *pats, **opts):
+_('[-r REV] [FILE]...'))
+def debugrename(ui, repo, *pats, **opts):
 """dump rename information"""
 
 opts = pycompat.byteskwargs(opts)
 ctx = scmutil.revsingle(repo, opts.get('rev'))
-m = scmutil.match(ctx, (file1,) + pats, opts)
+m = scmutil.match(ctx, pats, opts)
 for abs in ctx.walk(m):
 fctx = ctx[abs]
 o = fctx.filelog().renamed(fctx.filenode())



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


D5953: revset: improve documentation on expectsize()

2019-02-13 Thread navaneeth.suresh (Navaneeth Suresh)
navaneeth.suresh created this revision.
Herald added subscribers: mercurial-devel, mjpieters.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This is a follow-up patch to https://phab.mercurial-scm.org/D5813. It 
improves the documentation of
  `expectsize(set, size)`.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/revset.py

CHANGE DETAILS

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -817,7 +817,12 @@
 
 @predicate('expectsize(set[, size])', safe=True, takeorder=True)
 def expectrevsetsize(repo, subset, x, order):
-"""Abort if the revset doesn't expect given size"""
+"""Return the given revset if size matches the revset size.
+Abort if the revset doesn't expect given size.
+size can either be an integer range or an integer.
+
+For example, ``expectsize(0:1, 3:5)`` will abort as revset size is 2 and
+2 is not between 3 and 4 inclusive."""
 args = getargsdict(x, 'expect', 'set size')
 minsize = 0
 maxsize = len(repo)+1



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


D5947: revlog: use iterbytestr()

2019-02-13 Thread indygreg (Gregory Szorc)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG389ad992d953: revlog: use iterbytestr() (authored by 
indygreg, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5947?vs=14049=14064

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

AFFECTED FILES
  mercurial/revlog.py

CHANGE DETAILS

diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -1340,7 +1340,7 @@
 return True
 
 def maybewdir(prefix):
-return all(c == 'f' for c in prefix)
+return all(c == 'f' for c in pycompat.iterbytestr(prefix))
 
 hexnode = hex(node)
 



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


D5813: revset: add expect to check the size of a set

2019-02-13 Thread navaneeth.suresh (Navaneeth Suresh)
navaneeth.suresh added inline comments.

INLINE COMMENTS

> pulkit wrote in revset.py:866
> Can you improve this documentation as a follow-up? We should mentioned about 
> specifying ranges, and also if the set has the given size, that set is 
> returned.

Doing that right away!

REPOSITORY
  rHG Mercurial

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

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


D5936: addremove: respect ui.relative-paths

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGf44ab808eb91: addremove: respect ui.relative-paths 
(authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5936?vs=14032=14059

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

AFFECTED FILES
  mercurial/cmdutil.py
  mercurial/commands.py
  mercurial/scmutil.py

CHANGE DETAILS

diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -1125,7 +1125,7 @@
 # TODO: We should probably have the caller pass in uipathfn and apply it to
 # the messages above too. forcerelativevalue=True is consistent with how
 # it used to work.
-uipathfn = getuipathfn(repo, forcerelativevalue=True)
+uipathfn = getuipathfn(repo, legacyrelativevalue=True)
 renames = _findrenames(repo, m, added + unknown, removed + deleted,
similarity, uipathfn)
 
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -180,7 +180,7 @@
 """
 
 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
-uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=True)
+uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
 rejected = cmdutil.add(ui, repo, m, "", uipathfn, False, **opts)
 return rejected and 1 or 0
 
@@ -4720,7 +4720,7 @@
 
 m = scmutil.match(repo[None], pats, opts)
 subrepos = opts.get('subrepos')
-uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=True)
+uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=True)
 return cmdutil.remove(ui, repo, m, "", uipathfn, after, force, subrepos,
   dryrun=dryrun)
 
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2401,7 +2401,7 @@
 with dsguard or util.nullcontextmanager():
 if dsguard:
 relative = scmutil.anypats(pats, opts)
-uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=relative)
+uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
 if scmutil.addremove(repo, matcher, "", uipathfn, opts) != 0:
 raise error.Abort(
 _("failed to mark all new/missing files as added/removed"))
@@ -2481,7 +2481,7 @@
 # was specified.
 matcher = scmutil.match(wctx, pats, opts)
 relative = scmutil.anypats(pats, opts)
-uipathfn = scmutil.getuipathfn(repo, forcerelativevalue=relative)
+uipathfn = scmutil.getuipathfn(repo, legacyrelativevalue=relative)
 if (opts.get('addremove')
 and scmutil.addremove(repo, matcher, "", uipathfn, opts)):
 raise error.Abort(



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


D5938: resolve: slightly simplify join expression by joining with empty strings

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGc31dd7b63ab3: resolve: slightly simplify join expression by 
joining with empty strings (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5938?vs=14034=14062

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

AFFECTED FILES
  mercurial/commands.py

CHANGE DETAILS

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -4985,9 +4985,8 @@
 
 if hasconflictmarkers:
 ui.warn(_('warning: the following files still have conflict '
-  'markers:\n  ') +
-'\n  '.join(uipathfn(f) for f in hasconflictmarkers) +
-'\n')
+  'markers:\n') + ''.join('  ' + uipathfn(f) + '\n'
+  for f in hasconflictmarkers))
 if markcheck == 'abort' and not all and not pats:
 raise error.Abort(_('conflict markers detected'),
   hint=_('use --all to mark anyway'))



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


D5937: resolve: respect ui.relative-paths also for warning messages

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGdf3c24966e4b: resolve: respect ui.relative-paths also for 
warning messages (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5937?vs=14033=14060

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

AFFECTED FILES
  mercurial/commands.py

CHANGE DETAILS

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -4922,11 +4922,11 @@
 if mark:
 if exact:
 ui.warn(_('not marking %s as it is driver-resolved\n')
-% f)
+% uipathfn(f))
 elif unmark:
 if exact:
 ui.warn(_('not unmarking %s as it is 
driver-resolved\n')
-% f)
+% uipathfn(f))
 else:
 runconclude = True
 continue
@@ -4940,7 +4940,7 @@
 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
 ui.warn(_('%s: path conflict must be resolved manually\n')
-% f)
+% uipathfn(f))
 continue
 
 if mark:
@@ -4985,7 +4985,9 @@
 
 if hasconflictmarkers:
 ui.warn(_('warning: the following files still have conflict '
-  'markers:\n  ') + '\n  '.join(hasconflictmarkers) + '\n')
+  'markers:\n  ') +
+'\n  '.join(uipathfn(f) for f in hasconflictmarkers) +
+'\n')
 if markcheck == 'abort' and not all and not pats:
 raise error.Abort(_('conflict markers detected'),
   hint=_('use --all to mark anyway'))



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


D5939: commit: respect ui.relative-paths

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG8fc63f5fb50d: commit: respect ui.relative-paths (authored 
by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5939?vs=14035=14061

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

AFFECTED FILES
  mercurial/localrepo.py

CHANGE DETAILS

diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -2455,10 +2455,11 @@
 
 # commit subs and write new state
 if subs:
+uipathfn = scmutil.getuipathfn(self)
 for s in sorted(commitsubs):
 sub = wctx.sub(s)
 self.ui.status(_('committing subrepository %s\n') %
-   subrepoutil.subrelpath(sub))
+   uipathfn(subrepoutil.subrelpath(sub)))
 sr = sub.commit(cctx._text, user, date)
 newstate[s] = (newstate[s][0], sr)
 subrepoutil.writestate(self, newstate)
@@ -2526,8 +2527,9 @@
 removed = list(ctx.removed())
 linkrev = len(self)
 self.ui.note(_("committing files:\n"))
+uipathfn = scmutil.getuipathfn(self)
 for f in sorted(ctx.modified() + ctx.added()):
-self.ui.note(f + "\n")
+self.ui.note(uipathfn(f) + "\n")
 try:
 fctx = ctx[f]
 if fctx is None:
@@ -2538,12 +2540,14 @@
 trp, changed)
 m.setflag(f, fctx.flags())
 except OSError:
-self.ui.warn(_("trouble committing %s!\n") % f)
+self.ui.warn(_("trouble committing %s!\n") %
+ uipathfn(f))
 raise
 except IOError as inst:
 errcode = getattr(inst, 'errno', errno.ENOENT)
 if error or errcode and errcode != errno.ENOENT:
-self.ui.warn(_("trouble committing %s!\n") % f)
+self.ui.warn(_("trouble committing %s!\n") %
+ uipathfn(f))
 raise
 
 # update manifest



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


D5935: windows: use util.localpath for repo-relative paths in getuipathfn()

2019-02-13 Thread martinvonz (Martin von Zweigbergk)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGa8d3a4be066e: windows: use util.localpath for repo-relative 
paths in getuipathfn() (authored by martinvonz, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5935?vs=14031=14058

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

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
@@ -756,8 +756,10 @@
 cwd = repo.getcwd()
 pathto = repo.pathto
 return lambda f: pathto(f, cwd)
+elif repo.ui.configbool('ui', 'slash'):
+return lambda f: f
 else:
-return lambda f: f
+return util.localpath
 
 def subdiruipathfn(subpath, uipathfn):
 '''Create a new uipathfn that treats the file as relative to subpath.'''



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


Re: [PATCH] walkchangerevs: obey allfiles parameter when taking the slow path

2019-02-13 Thread Yuya Nishihara
On Tue, 12 Feb 2019 17:20:56 -0500, Jordi Gutiérrez Hermoso wrote:
> # HG changeset patch
> # User Jordi Gutiérrez Hermoso 
> # Date 1550009431 18000
> #  Tue Feb 12 17:10:31 2019 -0500
> # Node ID 06f76b4009c4802a48abc184984d0eebc7d7d91e
> # Parent  61415361e90684a8c7a031413e9182f51937c2e7
> walkchangerevs: obey allfiles parameter when taking the slow path

Queued, thanks.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5945: rust: itering less on MissingAncestors.bases for max()

2019-02-13 Thread gracinet (Georges Racinet)
gracinet updated this revision to Diff 14057.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5945?vs=14046=14057

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

AFFECTED FILES
  rust/hg-core/src/ancestors.rs
  rust/hg-core/src/dagops.rs
  rust/hg-core/src/lib.rs

CHANGE DETAILS

diff --git a/rust/hg-core/src/lib.rs b/rust/hg-core/src/lib.rs
--- a/rust/hg-core/src/lib.rs
+++ b/rust/hg-core/src/lib.rs
@@ -14,6 +14,11 @@
 /// 4 bytes, and are liberally converted to ints, whence the i32
 pub type Revision = i32;
 
+
+/// Marker expressing the absence of a parent
+///
+/// Independently of the actual representation, `NULL_REVISION` is guaranteed
+/// to be smaller that all existing revisions.
 pub const NULL_REVISION: Revision = -1;
 
 /// Same as `mercurial.node.wdirrev`
diff --git a/rust/hg-core/src/dagops.rs b/rust/hg-core/src/dagops.rs
--- a/rust/hg-core/src/dagops.rs
+++ b/rust/hg-core/src/dagops.rs
@@ -46,7 +46,9 @@
 let mut heads: HashSet = iter_revs.clone().cloned().collect();
 heads.remove(_REVISION);
 for rev in iter_revs {
-remove_parents(graph, *rev,  heads)?;
+if *rev != NULL_REVISION {
+remove_parents(graph, *rev,  heads)?;
+}
 }
 Ok(heads)
 }
@@ -71,7 +73,9 @@
 // mutating
 let as_vec: Vec = revs.iter().cloned().collect();
 for rev in as_vec {
-remove_parents(graph, rev, revs)?;
+if rev != NULL_REVISION {
+remove_parents(graph, rev, revs)?;
+}
 }
 Ok(())
 }
diff --git a/rust/hg-core/src/ancestors.rs b/rust/hg-core/src/ancestors.rs
--- a/rust/hg-core/src/ancestors.rs
+++ b/rust/hg-core/src/ancestors.rs
@@ -38,6 +38,7 @@
 pub struct MissingAncestors {
 graph: G,
 bases: HashSet,
+max_base: Revision,
 }
 
 impl AncestorsIterator {
@@ -209,7 +210,13 @@
 
 impl MissingAncestors {
 pub fn new(graph: G, bases: impl IntoIterator) -> Self {
-MissingAncestors { graph: graph, bases: bases.into_iter().collect() }
+let mut created = MissingAncestors {
+graph: graph,
+bases: HashSet::new(),
+max_base: NULL_REVISION,
+};
+created.add_bases(bases);
+created
 }
 
 pub fn has_bases() -> bool {
@@ -232,17 +239,33 @@
 }
 
 /// Consumes the object and returns the relative heads of its bases.
-pub fn into_bases_heads(mut self) -> Result, GraphError> 
{
+pub fn into_bases_heads(
+mut self,
+) -> Result, GraphError> {
 dagops::retain_heads(,  self.bases)?;
 Ok(self.bases)
 }
 
+/// Add some revisions to `self.bases`
+///
+/// Takes care of keeping `self.max_base` up to date.
 pub fn add_bases(
  self,
 new_bases: impl IntoIterator,
 ) {
-self.bases
-.extend(new_bases.into_iter().filter(|| rev != NULL_REVISION));
+let mut max_base = self.max_base;
+self.bases.extend(
+new_bases
+.into_iter()
+.filter(|| rev != NULL_REVISION)
+.map(|r| {
+if r > max_base {
+max_base = r;
+}
+r
+}),
+);
+self.max_base = max_base;
 }
 
 /// Remove all ancestors of self.bases from the revs set (in place)
@@ -261,20 +284,16 @@
 }
 // anything in revs > start is definitely not an ancestor of bases
 // revs <= start need to be investigated
-// TODO optim: if a missingancestors is to be used several times,
-// we shouldn't need to iterate each time on bases
-let start = match self.bases.iter().cloned().max() {
-Some(m) => m,
-None => {  // self.bases is empty
-return Ok(());
-}
-};
+if self.max_base == NULL_REVISION {
+return Ok(());
+}
+
 // whatever happens, we'll keep at least keepcount of them
 // knowing this gives us a earlier stop condition than
 // going all the way to the root
-let keepcount = revs.iter().filter(|r| **r > start).count();
+let keepcount = revs.iter().filter(|r| **r > self.max_base).count();
 
-let mut curr = start;
+let mut curr = self.max_base;
 while curr != NULL_REVISION && revs.len() > keepcount {
 if self.bases.contains() {
 revs.remove();
@@ -285,12 +304,17 @@
 Ok(())
 }
 
-/// Add rev's parents to self.bases
+/// Add the parents of `rev` to `self.bases`
+///
+/// This has no effect on `self.max_base`
 #[inline]
 fn add_parents( self, rev: Revision) -> Result<(), GraphError> {
-// No need to bother the set with inserting NULL_REVISION over and
-// over
+if rev == NULL_REVISION {
+return Ok(());
+}
 for p in self.graph.parents(rev)?.iter().cloned() 

D5944: rust: stop putting NULL_REVISION in MissingAncestors.bases

2019-02-13 Thread gracinet (Georges Racinet)
gracinet updated this revision to Diff 14056.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5944?vs=14041=14056

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

AFFECTED FILES
  rust/hg-core/src/ancestors.rs

CHANGE DETAILS

diff --git a/rust/hg-core/src/ancestors.rs b/rust/hg-core/src/ancestors.rs
--- a/rust/hg-core/src/ancestors.rs
+++ b/rust/hg-core/src/ancestors.rs
@@ -209,15 +209,11 @@
 
 impl MissingAncestors {
 pub fn new(graph: G, bases: impl IntoIterator) -> Self {
-let mut bases: HashSet = bases.into_iter().collect();
-if bases.is_empty() {
-bases.insert(NULL_REVISION);
-}
-MissingAncestors { graph, bases }
+MissingAncestors { graph: graph, bases: bases.into_iter().collect() }
 }
 
 pub fn has_bases() -> bool {
-self.bases.iter().any(|| b != NULL_REVISION)
+!self.bases.is_empty()
 }
 
 /// Return a reference to current bases.
@@ -245,16 +241,20 @@
  self,
 new_bases: impl IntoIterator,
 ) {
-self.bases.extend(new_bases);
+self.bases
+.extend(new_bases.into_iter().filter(|| rev != NULL_REVISION));
 }
 
 /// Remove all ancestors of self.bases from the revs set (in place)
 pub fn remove_ancestors_from(
  self,
 revs:  HashSet,
 ) -> Result<(), GraphError> {
 revs.retain(|r| !self.bases.contains(r));
-// the null revision is always an ancestor
+// the null revision is always an ancestor. Logically speaking
+// it's debatable in case bases is empty, but the Python
+// implementation always adds NULL_REVISION to bases, making it
+// unconditionnally true.
 revs.remove(_REVISION);
 if revs.is_empty() {
 return Ok(());
@@ -265,8 +265,7 @@
 // we shouldn't need to iterate each time on bases
 let start = match self.bases.iter().cloned().max() {
 Some(m) => m,
-None => {
-// bases is empty (shouldn't happen, but let's be safe)
+None => {  // self.bases is empty
 return Ok(());
 }
 };



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


[PATCH 1 of 4 V2] rust-cpython: moved py_set() utility to conversion module

2019-02-13 Thread Georges Racinet
# HG changeset patch
# User Georges Racinet 
# Date 1547651127 -3600
#  Wed Jan 16 16:05:27 2019 +0100
# Node ID 309cd33d38043b3dec8b500551436aa369535943
# Parent  61415361e90684a8c7a031413e9182f51937c2e7
# EXP-Topic revset.predicates
rust-cpython: moved py_set() utility to conversion module

We're still hoping to get rid of it eventually, but we're going
to need it from outside the `ancestors` module before that.

diff -r 61415361e906 -r 309cd33d3804 rust/hg-cpython/src/ancestors.rs
--- a/rust/hg-cpython/src/ancestors.rs  Mon Feb 04 14:29:03 2019 -0800
+++ b/rust/hg-cpython/src/ancestors.rs  Wed Jan 16 16:05:27 2019 +0100
@@ -34,11 +34,11 @@
 //! [`LazyAncestors`]: struct.LazyAncestors.html
 //! [`MissingAncestors`]: struct.MissingAncestors.html
 //! [`AncestorsIterator`]: struct.AncestorsIterator.html
-use crate::conversion::rev_pyiter_collect;
+use crate::conversion::{py_set, rev_pyiter_collect};
 use cindex::Index;
 use cpython::{
 ObjectProtocol, PyClone, PyDict, PyList, PyModule, PyObject, PyResult,
-PyTuple, Python, PythonObject, ToPyObject,
+Python, PythonObject, ToPyObject,
 };
 use exceptions::GraphError;
 use hg::Revision;
@@ -90,24 +90,6 @@
 }
 }
 
-/// Copy and convert an `HashSet` in a Python set
-///
-/// This will probably turn useless once `PySet` support lands in
-/// `rust-cpython`.
-///
-/// This builds a Python tuple, then calls Python's "set()" on it
-fn py_set(py: Python, set: ) -> PyResult {
-let as_vec: Vec = set
-.iter()
-.map(|rev| rev.to_py_object(py).into_object())
-.collect();
-let as_pytuple = PyTuple::new(py, as_vec.as_slice());
-
-let locals = PyDict::new(py);
-locals.set_item(py, "obj", as_pytuple.to_py_object(py))?;
-py.eval("set(obj)", None, Some())
-}
-
 py_class!(pub class LazyAncestors |py| {
 data inner: RefCell>>;
 
diff -r 61415361e906 -r 309cd33d3804 rust/hg-cpython/src/conversion.rs
--- a/rust/hg-cpython/src/conversion.rs Mon Feb 04 14:29:03 2019 -0800
+++ b/rust/hg-cpython/src/conversion.rs Wed Jan 16 16:05:27 2019 +0100
@@ -8,8 +8,12 @@
 //! Bindings for the hg::ancestors module provided by the
 //! `hg-core` crate. From Python, this will be seen as `rustext.ancestor`
 
-use cpython::{ObjectProtocol, PyObject, PyResult, Python};
+use cpython::{
+ObjectProtocol, PyDict, PyObject, PyResult, PyTuple, Python, PythonObject,
+ToPyObject,
+};
 use hg::Revision;
+use std::collections::HashSet;
 use std::iter::FromIterator;
 
 /// Utility function to convert a Python iterable into various collections
@@ -26,3 +30,21 @@
 .map(|r| r.and_then(|o| o.extract::(py)))
 .collect()
 }
+
+/// Copy and convert an `HashSet` in a Python set
+///
+/// This will probably turn useless once `PySet` support lands in
+/// `rust-cpython`.
+///
+/// This builds a Python tuple, then calls Python's "set()" on it
+pub fn py_set(py: Python, set: ) -> PyResult {
+let as_vec: Vec = set
+.iter()
+.map(|rev| rev.to_py_object(py).into_object())
+.collect();
+let as_pytuple = PyTuple::new(py, as_vec.as_slice());
+
+let locals = PyDict::new(py);
+locals.set_item(py, "obj", as_pytuple.to_py_object(py))?;
+py.eval("set(obj)", None, Some())
+}
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 4 V2] rust-cpython: binding for headrevs()

2019-02-13 Thread Georges Racinet
# HG changeset patch
# User Georges Racinet 
# Date 1547141118 -3600
#  Thu Jan 10 18:25:18 2019 +0100
# Node ID 956c5b54b4ce3e8decf5243a7f73c6f9a06f1229
# Parent  309cd33d38043b3dec8b500551436aa369535943
# EXP-Topic revset.predicates
rust-cpython: binding for headrevs()

This uses the core `dagops::retain_heads` to give a Rust implementation
to `mercurial.dagop.headrevs`.

Testing happens for now from `test-rust-ancestors.py`
(for quick and minimal change), but it'd made more sense to put the binary
index data elsewhere and to create a new test python module

diff -r 309cd33d3804 -r 956c5b54b4ce rust/hg-cpython/src/dagops.rs
--- /dev/null   Thu Jan 01 00:00:00 1970 +
+++ b/rust/hg-cpython/src/dagops.rs Thu Jan 10 18:25:18 2019 +0100
@@ -0,0 +1,53 @@
+// dagops.rs
+//
+// Copyright 2019 Georges Racinet 
+//
+// This software may be used and distributed according to the terms of the
+// GNU General Public License version 2 or any later version.
+
+//! Bindings for the `hg::dagops` module provided by the
+//! `hg-core` package.
+//!
+//! From Python, this will be seen as `mercurial.rustext.dagop`
+use cindex::Index;
+use cpython::{PyDict, PyModule, PyObject, PyResult, Python};
+use crate::conversion::{py_set, rev_pyiter_collect};
+use exceptions::GraphError;
+use hg::dagops;
+use hg::Revision;
+use std::collections::HashSet;
+
+/// Using the the `index`, return heads out of any Python iterable of Revisions
+///
+/// This is the Rust counterpart for `mercurial.dagop.headrevs`
+pub fn headrevs(
+py: Python,
+index: PyObject,
+revs: PyObject,
+) -> PyResult {
+let mut as_set: HashSet = rev_pyiter_collect(py, )?;
+dagops::retain_heads(::new(py, index)?,  as_set)
+.map_err(|e| GraphError::pynew(py, e))?;
+py_set(py, _set)
+}
+
+/// Create the module, with `__package__` given from parent
+pub fn init_module(py: Python, package: ) -> PyResult {
+let dotted_name = !("{}.dagop", package);
+let m = PyModule::new(py, dotted_name)?;
+m.add(py, "__package__", package)?;
+m.add(py, "__doc__", "DAG operations - Rust implementation")?;
+m.add(
+py,
+"headrevs",
+py_fn!(py, headrevs(index: PyObject, revs: PyObject)),
+)?;
+
+let sys = PyModule::import(py, "sys")?;
+let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
+sys_modules.set_item(py, dotted_name, )?;
+// Example C code (see pyexpat.c and import.c) will "give away the
+// reference", but we won't because it will be consumed once the
+// Rust PyObject is dropped.
+Ok(m)
+}
diff -r 309cd33d3804 -r 956c5b54b4ce rust/hg-cpython/src/lib.rs
--- a/rust/hg-cpython/src/lib.rsWed Jan 16 16:05:27 2019 +0100
+++ b/rust/hg-cpython/src/lib.rsThu Jan 10 18:25:18 2019 +0100
@@ -27,6 +27,7 @@
 pub mod ancestors;
 mod cindex;
 mod conversion;
+pub mod dagops;
 pub mod exceptions;
 
 py_module_initializer!(rustext, initrustext, PyInit_rustext, |py, m| {
@@ -38,6 +39,7 @@
 
 let dotted_name: String = m.get(py, "__name__")?.extract(py)?;
 m.add(py, "ancestor", ancestors::init_module(py, _name)?)?;
+m.add(py, "dagop", dagops::init_module(py, _name)?)?;
 m.add(py, "GraphError", py.get_type::())?;
 Ok(())
 });
diff -r 309cd33d3804 -r 956c5b54b4ce tests/test-rust-ancestor.py
--- a/tests/test-rust-ancestor.py   Wed Jan 16 16:05:27 2019 +0100
+++ b/tests/test-rust-ancestor.py   Thu Jan 10 18:25:18 2019 +0100
@@ -19,6 +19,7 @@
 LazyAncestors,
 MissingAncestors,
 )
+from mercurial.rustext import dagop
 
 try:
 from mercurial.cext import parsers as cparsers
@@ -165,6 +166,10 @@
 with self.assertRaises(error.WdirUnsupported):
 list(AncestorsIterator(idx, [node.wdirrev], -1, False))
 
+def testheadrevs(self):
+idx = self.parseindex()
+self.assertEqual(dagop.headrevs(idx, [1, 2, 3]), {3})
+
 if __name__ == '__main__':
 import silenttestrunner
 silenttestrunner.main(__name__)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 4 V2] rust-cpython: using rustext.dagop.headrevs in revlog

2019-02-13 Thread Georges Racinet
# HG changeset patch
# User Georges Racinet 
# Date 1547651966 -3600
#  Wed Jan 16 16:19:26 2019 +0100
# Node ID 3cab9658d270ce28cb589f6adbf0a19dffe51341
# Parent  eae29e210636ee44851e0caa385097a090c60af8
# EXP-Topic revset.predicates
rust-cpython: using rustext.dagop.headrevs in revlog

As with the previous oxidation series, revlog plays the role
of the factory, either using its parents function, or passing the
index.

In most of the cases about heads revsetbenchmarks, this seems to be
either neutral or an improvement. There aren't many cases where it's
actually slower and they don't look too bad.

Result by revset


Revision:
 0) parent of this changeset: rust-cpython: binding for headrevs()
 1) this changeset: rust-cpython: using rustext.dagop.headrevs in revlog

revset #0: heads(commonancestors(last(head(), 2)))
   plain min   max   first last  
reverse   rev..rst  rev..ast  sort  sor..rst  sor..ast
0) 0.002913  0.002845  0.002976  0.002953  0.002978  
0.002894  0.002946  0.003127  0.002949  0.002977  0.003074
1) 0.002830  0.002900  0.002942  0.003066  0.002994  
0.002881  0.003041  0.002973  0.002942  0.003008  0.003012

revset #1: heads(commonancestors(head()))
   plain min   max   first last  
reverse   rev..rst  rev..ast  sort  sor..rst  sor..ast
0) 0.124867  0.117328  0.117523  0.117500  0.114464  
0.128686  0.121959  0.119129  0.114949  0.124387  0.119485
1) 0.125079  0.124376 106% 0.114437  0.118340  0.124021 108% 
0.123225  0.126748  0.122144  0.126391 109% 0.116410  93% 0.121342

revset #2: heads(all())
   plain min   max   first last  
reverse   rev..rst  rev..ast  sort  sor..rst  sor..ast
0) 0.080521  0.079977  0.079199  0.079454  0.084119  
0.079578  0.083369  0.080215  0.080788  0.079157  0.080142
1) 0.033069  41% 0.032773  40% 0.033060  41% 0.032708  41% 0.032987  39% 
0.032458  40% 0.033019  39% 0.032306  40% 0.032341  40% 0.033317  42% 0.032645  
40%

revset #3: heads(-1:-1)
   plain min   max   first last  
reverse   rev..rst  rev..ast  sort  sor..rst  sor..ast
0) 0.008496  0.008642  0.008398  0.008665  0.008896  
0.008857  0.008864  0.009749  0.009690  0.009445  0.008902
1) 0.002694  31% 0.002678  30% 0.002692  32% 0.002766  31% 0.002753  30% 
0.002931  33% 0.003023  34% 0.002787  28% 0.002735  28% 0.002789  29% 0.002943  
33%

revset #4: (-5000:-1000) and heads(-1:-1)
   plain min   max   first last  
reverse   rev..rst  rev..ast  sort  sor..rst  sor..ast
0) 0.008835  0.008711  0.008920  0.008824  0.008948  
0.009422  0.009073  0.008751  0.009244  0.009264  0.009489
1) 0.003033  34% 0.003027  34% 0.002885  32% 0.002911  32% 0.002850  31% 
0.003068  32% 0.002971  32% 0.002890  33% 0.003239  35% 0.002973  32% 0.003068  
32%

revset #5: heads(matching(tip, "author"))
   plain min   max   first last  
reverse   rev..rst  rev..ast  sort  sor..rst  sor..ast
0) 15.82091  15.47578  15.95506  15.74816  15.72207  
15.72779  15.52043  15.65250  15.40250  15.46190  15.34036
1) 15.29257  15.39349  15.52757  15.41417  15.58991  
15.42382  15.46773  15.48543  15.43644  15.76070  15.32104

revset #6: heads(matching(tip, "author")) and -1:-1
   plain min   max   first last  
reverse   rev..rst  rev..ast  sort  sor..rst  sor..ast
0) 15.74241  15.63808  15.46853  15.77480  15.61004  
15.80385  15.44905  15.38059  15.34111  15.45029  15.85194
1) 15.51474  15.45938  15.28755  15.77045  15.38245  
15.40625  15.53653  15.31534  15.64134  15.43437  15.29366

revset #7: (-1:-1) and heads(matching(tip, "author"))
   plain min   max   first last  
reverse   rev..rst  rev..ast  sort  sor..rst  sor..ast
0) 15.37988  15.59717  16.07863  15.29263  15.46472  
15.84978  15.35538  15.50673  15.37396  15.42426  15.44425
1) 15.51504  15.38657  15.30847  15.39458  15.60453  
15.26237  15.45240  15.34210  15.36410  15.53354  15.67735

diff -r eae29e210636 -r 3cab9658d270 mercurial/revlog.py
--- a/mercurial/revlog.py   Fri Jan 18 13:38:01 2019 +0100
+++ b/mercurial/revlog.py   Wed 

[PATCH 3 of 4 V2] changelog: prefilter in headrevs()

2019-02-13 Thread Georges Racinet
# HG changeset patch
# User Georges Racinet 
# Date 1547815081 -3600
#  Fri Jan 18 13:38:01 2019 +0100
# Node ID eae29e210636ee44851e0caa385097a090c60af8
# Parent  956c5b54b4ce3e8decf5243a7f73c6f9a06f1229
# EXP-Topic revset.predicates
changelog: prefilter in headrevs()

In case where headrevs() is called on some revisions, we perform
the check that aren't filtered in advance, and switch revlog to
use its unchecked form.

This allows to work with alternative implementations that don't have knowledge
of the filtering system, such as the Rust one.

diff -r 956c5b54b4ce -r eae29e210636 mercurial/changelog.py
--- a/mercurial/changelog.pyThu Jan 10 18:25:18 2019 +0100
+++ b/mercurial/changelog.pyFri Jan 18 13:38:01 2019 +0100
@@ -22,6 +22,7 @@
 error,
 pycompat,
 revlog,
+util,
 )
 from .utils import (
 dateutil,
@@ -350,6 +351,40 @@
 def reachableroots(self, minroot, heads, roots, includepath=False):
 return self.index.reachableroots2(minroot, heads, roots, includepath)
 
+def _checknofilteredgenrevs(self, revs):
+"""rewrap 'revs' generator to include check for filtered revisions
+
+This does not consume the incoming generator.
+"""
+filteredrevs = self.filteredrevs
+for r in revs:
+if r in filteredrevs:
+raise error.FilteredIndexError(r)
+yield r
+
+def _checknofilteredinrevs(self, revs):
+"""raise the appropriate error if 'revs' contains a filtered revision
+
+This returns a version of 'revs' to be used by the caller, that works
+for all cases, including lazy ones
+"""
+safehasattr = util.safehasattr
+if safehasattr(revs, '__next__'):
+# Note that inspect.isgenerator() is not true for iterators,
+# and that calling even implicitely iter() on a iterator does not
+# clone it
+return self._checknofilteredgenrevs(revs)
+
+filteredrevs = self.filteredrevs
+if safehasattr(revs, 'first'):  # smartset
+offenders = revs & filteredrevs
+else:
+offenders = filteredrevs.intersection(revs)
+
+for rev in offenders:
+raise error.FilteredIndexError(rev)
+return revs
+
 def headrevs(self, revs=None):
 if revs is None and self.filteredrevs:
 try:
@@ -359,6 +394,8 @@
 except AttributeError:
 return self._headrevs()
 
+if self.filteredrevs:
+revs = self._checknofilteredinrevs(revs)
 return super(changelog, self).headrevs(revs)
 
 def strip(self, *args, **kwargs):
diff -r 956c5b54b4ce -r eae29e210636 mercurial/revlog.py
--- a/mercurial/revlog.py   Thu Jan 10 18:25:18 2019 +0100
+++ b/mercurial/revlog.py   Fri Jan 18 13:38:01 2019 +0100
@@ -1121,7 +1121,7 @@
 return self.index.headrevs()
 except AttributeError:
 return self._headrevs()
-return dagop.headrevs(revs, self.parentrevs)
+return dagop.headrevs(revs, self._uncheckedparentrevs)
 
 def computephases(self, roots):
 return self.index.computephasesmapsets(roots)
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D5945: rust: itering less on MissingAncestors.bases for max()

2019-02-13 Thread gracinet (Georges Racinet)
gracinet added inline comments.

INLINE COMMENTS

> kevincox wrote in ancestors.rs:41
> If you don't want to depend on the value of NULL_REVISION you can use the 
> minimum value for the type backing revision.
> 
> Other special revisions shouldn't be relevant because you shouldn't be 
> comparing them as the max anyways.
> 
> That being said the currents state is fine. So if you think it makes more 
> sense that sounds good to me.

Ok, I've made up my mind: whatever the representation, `NULL_REVISION` must be 
smaller than all other `Revision`. Using it, rather than `-1`will indeed make 
this patch simpler.

Also, in subsequent (not yet submitted) works, I'm already liberally using this 
fact that `NULL_REVISION` is the smallest of all, so…

REPOSITORY
  rHG Mercurial

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

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


Re: Auto-formatting code with black - object now if you have a strong opinion

2019-02-13 Thread Boris FELD
On 01/12/2018 02:35, Matt Harbison wrote:
> On Fri, 30 Nov 2018 07:25:04 -0500, Boris FELD
>  wrote:
>
>> I think using automatic formatting is a great idea and we should move
>> forward with this plan. Black seems a good option. I share other's
>> concerns about the formatting of import. I also wonder if this also
>> applies to list and dict formatting that we tend to express with one
>> value per line for clarity.
>
> It looks like yes, unfortunately, if it fits on one line:
>
> diff --git a/hgext/lfs/blobstore.py b/hgext/lfs/blobstore.py
> --- a/hgext/lfs/blobstore.py
> +++ b/hgext/lfs/blobstore.py
> @@ -289,50 +289,47 @@ class _gitlfsremote(object):
>  Return decoded JSON object like {'objects': [{'oid': '',
> 'size': 1}]}
>  See
> https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md
>  """
> -    objects = [{'oid': p.oid(), 'size': p.size()} for p in pointers]
> -    requestdata = json.dumps({
> -    'objects': objects,
> -    'operation': action,
> -    })
> -    url = '%s/objects/batch' % self.baseurl
> +    objects = [{"oid": p.oid(), "size": p.size()} for p in pointers]
> +    requestdata = json.dumps({"objects": objects, "operation":
> action})
> +    url = "%s/objects/batch" % self.baseurl
>  batchreq = util.urlreq.request(url, data=requestdata)
> ...

We have been discussing with the Black author about how we could handle
those cases and we found a `hack` which is adding an empty comment on
the first line of a list, dict, multi-line construction:

For example:

requestdata = json.dumps({
    #
    'objects': objects,
    'operation': action,

})

Would get transformed into:

requestdata = json.dumps(
    {
    #
    "objects": objects,
    "operation": action,
    }
)

which is then stable.

> I'm also concerned about stuff like this, which seems far less
> readable than the original (especially the conditional):
>
> diff --git a/hgext/relink.py b/hgext/relink.py
> --- a/hgext/relink.py
> +++ b/hgext/relink.py
> @@ -56,29 +50,32 @@ def relink(ui, repo, origin=None, **opts
>  command is running. (Both repositories will be locked against
>  writes.)
>  """
> -    if (not util.safehasattr(util, 'samefile') or
> -    not util.safehasattr(util, 'samedevice')):
> -    raise error.Abort(_('hardlinks are not supported on this
> system'))
> -    src = hg.repository(repo.baseui, ui.expandpath(origin or
> 'default-relink',
> -  origin or 'default'))
> -    ui.status(_('relinking %s to %s\n') % (src.store.path,
> repo.store.path))
> +    if not util.safehasattr(util, "samefile") or not util.safehasattr(
> +    util, "samedevice"
> +    ):
> +    raise error.Abort(_("hardlinks are not supported on this
> system"))
> +    src = hg.repository(
> +    repo.baseui, ui.expandpath(origin or "default-relink", origin
> or "default")
> +    )
> +    ui.status(_("relinking %s to %s\n") % (src.store.path,
> repo.store.path))
>  if repo.root == src.root:
Black output is not final yet, Black author wants to have the
possibility to make bugfixes. This particular example might be a bug
that could be solved. It could also be solved by extracting parameters
into variables.
>
> This was actually in the first file that I randomly sampled.  I think
> there were a few more instances like this, but don't feel motivated to
> find them now.  There were a bunch of lines (in lfs anyway) that were
> flattened out, and were more readable.  But that was before I saw that
> the default formatting is 88 columns.  So maybe allowing longer lines
> would help?  (At the cost of possibly rolling up more lists and dicts
> into a single line.)
>
> I'm not adamantly opposed, and the idea of combining version control
> and tooling to enforce a format is intriguing.  But FWIW, I'm not
> thrilled with the result of this.
> ___
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel