[PATCH 1 of 2] cat: record the current behavior of wildcard matches in subrepos

2017-11-24 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1511591374 -32400
#  Sat Nov 25 15:29:34 2017 +0900
# Node ID 38e952030f0c4746257280d47f0f94b6cb9ddb41
# Parent  8287df8b7be545fdafa22b771012ac65f6264d12
cat: record the current behavior of wildcard matches in subrepos

It appears that Mercurial subrepo supports any match patterns.

diff --git a/mercurial/help/subrepos.txt b/mercurial/help/subrepos.txt
--- a/mercurial/help/subrepos.txt
+++ b/mercurial/help/subrepos.txt
@@ -90,7 +90,7 @@ Interaction with Mercurial Commands
 :archive: archive does not recurse in subrepositories unless
 -S/--subrepos is specified.
 
-:cat: cat currently only handles exact file matches in subrepos.
+:cat: cat currently only handles exact file matches in Git subrepos.
 Subversion subrepositories are currently ignored.
 
 :commit: commit creates a consistent snapshot of the state of the
diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t
--- a/tests/test-subrepo.t
+++ b/tests/test-subrepo.t
@@ -1071,6 +1071,18 @@ Prepare a repo with subrepo
 "path": "sub/repo/foo"
}
   ]
+
+ non-exact match:
+
+  $ hg cat -T '{path}\n' 'glob:**'
+  .hgsub
+  .hgsubstate
+  sub/repo/foo (glob)
+  $ hg cat -T '{path}\n' 're:^sub'
+  sub/repo/foo (glob)
+
+ missing subrepos in working directory:
+
   $ mkdir -p tmp/sub/repo
   $ hg cat -r 0 --output tmp/%p_p sub/repo/foo
   $ cat tmp/sub/repo/foo_p
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 2] cat: do not instantiate subrepo if no potential match in it

2017-11-24 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1511593310 -32400
#  Sat Nov 25 16:01:50 2017 +0900
# Node ID b6e526ee5d2662ca30a555ca51264b3e371fe44e
# Parent  38e952030f0c4746257280d47f0f94b6cb9ddb41
cat: do not instantiate subrepo if no potential match in it

This fixes the test failure in hg-git.

https://bitbucket.org/durin42/hg-git/issues/227/

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -3068,6 +3068,8 @@ def cat(ui, repo, ctx, matcher, basefm, 
 err = 0
 
 for subpath in sorted(ctx.substate):
+if not matcher.visitdir(subpath):
+continue
 sub = ctx.sub(subpath)
 try:
 submatch = matchmod.subdirmatcher(subpath, matcher)
diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t
--- a/tests/test-subrepo.t
+++ b/tests/test-subrepo.t
@@ -1081,6 +1081,36 @@ Prepare a repo with subrepo
   $ hg cat -T '{path}\n' 're:^sub'
   sub/repo/foo (glob)
 
+ inaccessible subrepos:
+
+  $ mv sub sub_
+  $ touch sub
+  $ hg cat .hgsub .hgsubstate
+  sub/repo = sub/repo
+  f42d5c7504a811dda50f5cf3e5e16c3330b87172 sub/repo
+  $ hg cat sub/repo/foo
+  abort: *: '$TESTTMP/issue1852a/sub/repo' (glob)
+  [255]
+  $ rm sub
+  $ mv sub_ sub
+
+ symlink traversal:
+
+#if symlink
+
+  $ mv sub/repo sub/repo_
+  $ ln -s repo_ sub/repo
+  $ hg cat .hgsub .hgsubstate
+  sub/repo = sub/repo
+  f42d5c7504a811dda50f5cf3e5e16c3330b87172 sub/repo
+  $ hg cat sub/repo/foo
+  abort: subrepo 'sub/repo' traverses symbolic link
+  [255]
+  $ rm sub/repo
+  $ mv sub/repo_ sub/repo
+
+#endif
+
  missing subrepos in working directory:
 
   $ mkdir -p tmp/sub/repo
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D1498: hbisect: use a revset for ancestor calculation

2017-11-24 Thread dsp (David Soria Parra)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGec25c8275cfa: hbisect: use a revset for ancestor 
calculation (authored by dsp, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1498?vs=3804&id=3857

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

AFFECTED FILES
  mercurial/hbisect.py

CHANGE DETAILS

diff --git a/mercurial/hbisect.py b/mercurial/hbisect.py
--- a/mercurial/hbisect.py
+++ b/mercurial/hbisect.py
@@ -37,29 +37,10 @@
 skip = set([changelog.rev(n) for n in state['skip']])
 
 def buildancestors(bad, good):
-# only the earliest bad revision matters
 badrev = min([changelog.rev(n) for n in bad])
-goodrevs = [changelog.rev(n) for n in good]
-goodrev = min(goodrevs)
-# build visit array
-ancestors = [None] * (len(changelog) + 1) # an extra for [-1]
-
-# set nodes descended from goodrevs
-for rev in goodrevs:
+ancestors = [None] * (len(changelog) + 1)
+for rev in repo.revs("descendants(%ln) - ancestors(%ln)", good, good):
 ancestors[rev] = []
-for rev in changelog.revs(goodrev + 1):
-for prev in clparents(rev):
-if ancestors[prev] == []:
-ancestors[rev] = []
-
-# clear good revs from array
-for rev in goodrevs:
-ancestors[rev] = None
-for rev in changelog.revs(len(changelog), goodrev):
-if ancestors[rev] is None:
-for prev in clparents(rev):
-ancestors[prev] = None
-
 if ancestors[badrev] is None:
 return badrev, None
 return badrev, ancestors



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


D1494: develwarn: do not emit warning if "config" is unspecified

2017-11-24 Thread spectral (Kyle Lippincott)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGfa2395db68c6: develwarn: do not emit warning if 
"config" is unspecified (authored by spectral, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1494?vs=3798&id=3855

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

AFFECTED FILES
  mercurial/ui.py

CHANGE DETAILS

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -1603,7 +1603,7 @@
 stack.
 """
 if not self.configbool('devel', 'all-warnings'):
-if config is not None and not self.configbool('devel', config):
+if config is None or not self.configbool('devel', config):
 return
 msg = 'devel-warn: ' + msg
 stacklevel += 1 # get in develwarn



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


D1499: hbisect: use a defaultdict to avoid large allocations for a large changelogs

2017-11-24 Thread dsp (David Soria Parra)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG8287df8b7be5: hbisect: use a defaultdict to avoid large 
allocations for a large changelogs (authored by dsp, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1499?vs=3805&id=3858

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

AFFECTED FILES
  mercurial/hbisect.py

CHANGE DETAILS

diff --git a/mercurial/hbisect.py b/mercurial/hbisect.py
--- a/mercurial/hbisect.py
+++ b/mercurial/hbisect.py
@@ -38,7 +38,7 @@
 
 def buildancestors(bad, good):
 badrev = min([changelog.rev(n) for n in bad])
-ancestors = [None] * (len(changelog) + 1)
+ancestors = collections.defaultdict(lambda: None)
 for rev in repo.revs("descendants(%ln) - ancestors(%ln)", good, good):
 ancestors[rev] = []
 if ancestors[badrev] is None:



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


D1497: hbisect: pass repo into hbisect.bisect

2017-11-24 Thread dsp (David Soria Parra)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGfd8b6b183073: hbisect: pass repo into hbisect.bisect 
(authored by dsp, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1497?vs=3803&id=3856

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

AFFECTED FILES
  mercurial/commands.py
  mercurial/hbisect.py

CHANGE DETAILS

diff --git a/mercurial/hbisect.py b/mercurial/hbisect.py
--- a/mercurial/hbisect.py
+++ b/mercurial/hbisect.py
@@ -21,7 +21,7 @@
 error,
 )
 
-def bisect(changelog, state):
+def bisect(repo, state):
 """find the next node (if any) for testing during a bisect search.
 returns a (nodes, number, good) tuple.
 
@@ -32,6 +32,7 @@
 if searching for a first bad one.
 """
 
+changelog = repo.changelog
 clparents = changelog.parentrevs
 skip = set([changelog.rev(n) for n in state['skip']])
 
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -854,7 +854,7 @@
 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
 hbisect.checkstate(state)
 # bisect
-nodes, changesets, bgood = hbisect.bisect(repo.changelog, 
state)
+nodes, changesets, bgood = hbisect.bisect(repo, state)
 # update to next check
 node = nodes[0]
 mayupdate(repo, node, show_stats=False)
@@ -867,7 +867,7 @@
 hbisect.checkstate(state)
 
 # actually bisect
-nodes, changesets, good = hbisect.bisect(repo.changelog, state)
+nodes, changesets, good = hbisect.bisect(repo, state)
 if extend:
 if not changesets:
 extendnode = hbisect.extendrange(repo, state, nodes, good)



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


D1348: histedit: add support to output nodechanges using formatter

2017-11-24 Thread pulkit (Pulkit Goyal)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGa9cc233de513: histedit: add support to output nodechanges 
using formatter (authored by pulkit, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D1348?vs=3783&id=3854#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D1348?vs=3783&id=3854

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

AFFECTED FILES
  hgext/histedit.py
  tests/test-histedit-templates.t

CHANGE DETAILS

diff --git a/tests/test-histedit-templates.t b/tests/test-histedit-templates.t
new file mode 100644
--- /dev/null
+++ b/tests/test-histedit-templates.t
@@ -0,0 +1,54 @@
+Testing templating for histedit command
+
+Setup
+
+  $ cat >> $HGRCPATH < [extensions]
+  > histedit=
+  > [experimental]
+  > evolution=createmarkers
+  > EOF
+
+  $ hg init repo
+  $ cd repo
+  $ for ch in a b c d; do echo foo > $ch; hg commit -Aqm "Added "$ch; done
+
+  $ hg log -G -T "{rev}:{node|short} {desc}"
+  @  3:62615734edd5 Added d
+  |
+  o  2:28ad74487de9 Added c
+  |
+  o  1:29becc82797a Added b
+  |
+  o  0:18d04c59bb5d Added a
+  
+Getting the JSON output for nodechanges
+
+  $ hg histedit -Tjson --commands - 2>&1 < pick 28ad74487de9 Added c
+  > pick 62615734edd5 Added d
+  > pick 18d04c59bb5d Added a
+  > pick 29becc82797a Added b
+  > EOF
+  [
+   {
+"nodechanges": {"18d04c59bb5d2d4090ad9a5b59bd6274adb63add": 
["109f8ec895447f81b380ba8d4d8b66539ccdcb94"], 
"28ad74487de9599d00d81085be739c61fc340652": 
["bff9e07c1807942b161dab768aa793b48e9a7f9d"], 
"29becc82797a4bc11ec8880b58eaecd2ab3e7760": 
["f5dcf3b4db23f31f1aacf46c33d1393de303d26f"], 
"62615734edd52f06b6fb9c2beb429e4fe30d57b8": 
["201423b441c84d9e6858daed653e0d22485c1cfa"]}
+   }
+  ]
+
+  $ hg log -G -T "{rev}:{node|short} {desc}"
+  @  7:f5dcf3b4db23 Added b
+  |
+  o  6:109f8ec89544 Added a
+  |
+  o  5:201423b441c8 Added d
+  |
+  o  4:bff9e07c1807 Added c
+  
+  $ hg histedit -T "{nodechanges|json}" --commands - 2>&1 < pick bff9e07c1807 Added c
+  > pick 201423b441c8 Added d
+  > pick 109f8ec89544 Added a
+  > roll f5dcf3b4db23 Added b
+  > EOF
+  {"109f8ec895447f81b380ba8d4d8b66539ccdcb94": 
["8d01470bfeab64d3de13c49adb79d88790d38396"], 
"f3ec56a374bdbdf1953cacca505161442c6f3a3e": [], 
"f5dcf3b4db23f31f1aacf46c33d1393de303d26f": 
["8d01470bfeab64d3de13c49adb79d88790d38396"]} (no-eol)
diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -917,7 +917,8 @@
  ('o', 'outgoing', False, _('changesets not found in destination')),
  ('f', 'force', False,
   _('force outgoing even for unrelated repositories')),
- ('r', 'rev', [], _('first revision to be edited'), _('REV'))],
+ ('r', 'rev', [], _('first revision to be edited'), _('REV'))] +
+cmdutil.formatteropts,
  _("[OPTIONS] ([ANCESTOR] | --outgoing [URL])"))
 def histedit(ui, repo, *freeargs, **opts):
 """interactively edit changeset history
@@ -1095,6 +1096,8 @@
 
 def _histedit(ui, repo, state, *freeargs, **opts):
 opts = pycompat.byteskwargs(opts)
+fm = ui.formatter('histedit', opts)
+fm.startitem()
 goal = _getgoal(opts)
 revs = opts.get('rev', [])
 rules = opts.get('commands', '')
@@ -1117,7 +1120,8 @@
 _newhistedit(ui, repo, state, revs, freeargs, opts)
 
 _continuehistedit(ui, repo, state)
-_finishhistedit(ui, repo, state)
+_finishhistedit(ui, repo, state, fm)
+fm.end()
 
 def _continuehistedit(ui, repo, state):
 """This function runs after either:
@@ -1164,7 +1168,7 @@
 state.write()
 ui.progress(_("editing"), None)
 
-def _finishhistedit(ui, repo, state):
+def _finishhistedit(ui, repo, state, fm):
 """This action runs when histedit is finishing its session"""
 repo.ui.pushbuffer()
 hg.update(repo, state.parentctxnode, quietempty=True)
@@ -1198,6 +1202,13 @@
 mapping = {k: v for k, v in mapping.items()
if k in nodemap and all(n in nodemap for n in v)}
 scmutil.cleanupnodes(repo, mapping, 'histedit')
+hf = fm.hexfunc
+fl = fm.formatlist
+fd = fm.formatdict
+nodechanges = fd({hf(oldn): fl([hf(n) for n in newn], name='node')
+  for oldn, newn in mapping.iteritems()},
+ key="oldnode", value="newnodes")
+fm.data(nodechanges=nodechanges)
 
 state.clear()
 if os.path.exists(repo.sjoin('undo')):



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


D1494: develwarn: do not emit warning if "config" is unspecified

2017-11-24 Thread yuja (Yuya Nishihara)
yuja added a comment.


  > (Specifically picked yuja as reviewer since they reviewed the original
  >  https://www.mercurial-scm.org/repo/hg/rev/3f33831a9202,
  >  so hopefully can tell me whether this was intentional
  
  I think it was intentional during the migration to the config gating API,
  i.e. no gating unless `config=` is specified, but the current behavior is
  weird, and should be worth breaking the old API.

REPOSITORY
  rHG Mercurial

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

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


D1506: dagop: handle IndexError when using wdir() in dag range

2017-11-24 Thread yuja (Yuya Nishihara)
yuja requested changes to this revision.
yuja added a comment.
This revision now requires changes to proceed.


  I think it's better to fail fast instead of trying the slow path which is 
supposed
  to raise WdirUnsupported exception.
  
  > $ hg status --rev '.::wdir()'
  >  abort: working directory revision cannot be specified
  
  Can you add test?

REPOSITORY
  rHG Mercurial

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

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


D1499: hbisect: use a defaultdict to avoid large allocations for a large changelogs

2017-11-24 Thread yuja (Yuya Nishihara)
yuja added a comment.


  Queued, thanks. I don't have any number, but this seems good for a common
  scenario in which a small part of a large repository will be bisected.

REPOSITORY
  rHG Mercurial

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

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


D1494: develwarn: do not emit warning if "config" is unspecified

2017-11-24 Thread yuja (Yuya Nishihara)
yuja accepted this revision.
yuja added a comment.
This revision is now accepted and ready to land.


  Makes sense. Queued, thanks.

REPOSITORY
  rHG Mercurial

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

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


D1348: histedit: add support to output nodechanges using formatter

2017-11-24 Thread yuja (Yuya Nishihara)
yuja accepted this revision.
yuja added a comment.
This revision is now accepted and ready to land.


  Queued, thanks.

REPOSITORY
  rHG Mercurial

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

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


[PATCH 2 of 2] obsolete: drop usage of changectx in '_computecontentdivergentset'

2017-11-24 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1511066090 -3600
#  Sun Nov 19 05:34:50 2017 +0100
# Node ID 15d0adf567fa66fbc33146e296fbc293bb507663
# Parent  b76ac906d1ecea6bcac489834699d01273112fc8
# EXP-Topic instability-speed
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
15d0adf567fa
obsolete: drop usage of changectx in '_computecontentdivergentset'

Changectx are expensive and not needed there. The use of `repo.set` denote old
code that predate the introduction of `repo.revs` that we now use.

On my mercurial repository 495 draft:

before: 0.054239 second
after:  0.046935 second

On a mercurial repository with 115973 draft:

before: 0.564548 second
after:  0.130534 second

diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -1023,8 +1023,10 @@ def _computecontentdivergentset(repo):
 divergent = set()
 obsstore = repo.obsstore
 newermap = {}
-for ctx in repo.set('(not public()) - obsolete()'):
-mark = obsstore.predecessors.get(ctx.node(), ())
+tonode = repo.changelog.node
+for rev in repo.revs('(not public()) - obsolete()'):
+node = tonode(rev)
+mark = obsstore.predecessors.get(node, ())
 toprocess = set(mark)
 seen = set()
 while toprocess:
@@ -1036,7 +1038,7 @@ def _computecontentdivergentset(repo):
 obsutil.successorssets(repo, prec, cache=newermap)
 newer = [n for n in newermap[prec] if n]
 if len(newer) > 1:
-divergent.add(ctx.rev())
+divergent.add(rev)
 break
 toprocess.update(obsstore.predecessors.get(prec, ()))
 return divergent
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2] obsolete: drop usage of changectx in '_computephasedivergentset'

2017-11-24 Thread Boris Feld
# HG changeset patch
# User Boris Feld 
# Date 1511065392 -3600
#  Sun Nov 19 05:23:12 2017 +0100
# Node ID b76ac906d1ecea6bcac489834699d01273112fc8
# Parent  75013952d8d9608f73cd45f68405fbd6ec112bf2
# EXP-Topic instability-speed
# Available At https://bitbucket.org/octobus/mercurial-devel/
#  hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 
b76ac906d1ec
obsolete: drop usage of changectx in '_computephasedivergentset'

Changectx are expensive and not needed there. The use of `repo.set` denote old
code that predate the introduction of `repo.revs` that we now use.

On my mercurial repository 495 draft:

before: 0.010275 second
after:  0.008832 second

On a mercurial repository with 115973 draft:

before: 0.899255 second
after:  0.397131 second

diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -994,10 +994,10 @@ def _computephasedivergentset(repo):
 public = phases.public
 cl = repo.changelog
 torev = cl.nodemap.get
-for ctx in repo.set('(not public()) and (not obsolete())'):
-rev = ctx.rev()
+tonode = cl.node
+for rev in repo.revs('(not public()) and (not obsolete())'):
 # We only evaluate mutable, non-obsolete revision
-node = ctx.node()
+node = tonode(rev)
 # (future) A cache of predecessors may worth if split is very common
 for pnode in obsutil.allpredecessors(repo.obsstore, [node],
ignoreflags=bumpedfix):
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 1 of 2 STABLE V2] fancyopts: add early-options parser compatible with getopt()

2017-11-24 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1511442293 -32400
#  Thu Nov 23 22:04:53 2017 +0900
# Branch stable
# Node ID 78d25e7afffe6ce150da8b1ca32418d6394b0442
# Parent  02845f7441aff30bc01975a5881cabfa922c12d4
fancyopts: add early-options parser compatible with getopt()

The next patch will add a flag for strict parsing of early options, where
we'll have to parse all early options at once instead of processing them
one-by-one by dispatch._earlygetopt(). That's why I decided to hook
fancyopts().

All dispatch._early*opt() functions is planned to be replaced with this
function. But in this stable series, only the strict mode will be handled
by fancyopts.earlygetopt().

diff --git a/mercurial/fancyopts.py b/mercurial/fancyopts.py
--- a/mercurial/fancyopts.py
+++ b/mercurial/fancyopts.py
@@ -7,6 +7,8 @@
 
 from __future__ import absolute_import
 
+import functools
+
 from .i18n import _
 from . import (
 error,
@@ -24,6 +26,179 @@ nevernegate = {
 'version',
 }
 
+def _earlyoptarg(arg, shortlist, namelist):
+"""Check if the given arg is a valid unabbreviated option
+
+Returns (flag_str, has_embedded_value?, embedded_value, takes_value?)
+
+>>> def opt(arg):
+... return _earlyoptarg(arg, b'R:q', [b'cwd=', b'debugger'])
+
+long form:
+
+>>> opt(b'--cwd')
+('--cwd', False, '', True)
+>>> opt(b'--cwd=')
+('--cwd', True, '', True)
+>>> opt(b'--cwd=foo')
+('--cwd', True, 'foo', True)
+>>> opt(b'--debugger')
+('--debugger', False, '', False)
+>>> opt(b'--debugger=')  # invalid but parsable
+('--debugger', True, '', False)
+
+short form:
+
+>>> opt(b'-R')
+('-R', False, '', True)
+>>> opt(b'-Rfoo')
+('-R', True, 'foo', True)
+>>> opt(b'-q')
+('-q', False, '', False)
+>>> opt(b'-qfoo')  # invalid but parsable
+('-q', True, 'foo', False)
+
+unknown or invalid:
+
+>>> opt(b'--unknown')
+('', False, '', False)
+>>> opt(b'-u')
+('', False, '', False)
+>>> opt(b'-ufoo')
+('', False, '', False)
+>>> opt(b'--')
+('', False, '', False)
+>>> opt(b'-')
+('', False, '', False)
+>>> opt(b'-:')
+('', False, '', False)
+>>> opt(b'-:foo')
+('', False, '', False)
+"""
+if arg.startswith('--'):
+flag, eq, val = arg.partition('=')
+if flag[2:] in namelist:
+return flag, bool(eq), val, False
+if flag[2:] + '=' in namelist:
+return flag, bool(eq), val, True
+elif arg.startswith('-') and arg != '-' and not arg.startswith('-:'):
+flag, val = arg[:2], arg[2:]
+i = shortlist.find(flag[1:])
+if i >= 0:
+return flag, bool(val), val, shortlist.startswith(':', i + 1)
+return '', False, '', False
+
+def earlygetopt(args, shortlist, namelist, gnu=False, keepsep=False):
+"""Parse options like getopt, but ignores unknown options and abbreviated
+forms
+
+If gnu=False, this stops processing options as soon as a non/unknown-option
+argument is encountered. Otherwise, option and non-option arguments may be
+intermixed, and unknown-option arguments are taken as non-option.
+
+If keepsep=True, '--' won't be removed from the list of arguments left.
+This is useful for stripping early options from a full command arguments.
+
+>>> def get(args, gnu=False, keepsep=False):
+... return earlygetopt(args, b'R:q', [b'cwd=', b'debugger'],
+...gnu=gnu, keepsep=keepsep)
+
+default parsing rules for early options:
+
+>>> get([b'x', b'--cwd', b'foo', b'-Rbar', b'-q', b'y'], gnu=True)
+([('--cwd', 'foo'), ('-R', 'bar'), ('-q', '')], ['x', 'y'])
+>>> get([b'x', b'--cwd=foo', b'y', b'-R', b'bar', b'--debugger'], gnu=True)
+([('--cwd', 'foo'), ('-R', 'bar'), ('--debugger', '')], ['x', 'y'])
+>>> get([b'--unknown', b'--cwd=foo', b'--', '--debugger'], gnu=True)
+([('--cwd', 'foo')], ['--unknown', '--debugger'])
+
+restricted parsing rules (early options must come first):
+
+>>> get([b'--cwd', b'foo', b'-Rbar', b'x', b'-q', b'y'], gnu=False)
+([('--cwd', 'foo'), ('-R', 'bar')], ['x', '-q', 'y'])
+>>> get([b'--cwd=foo', b'x', b'y', b'-R', b'bar', b'--debugger'], 
gnu=False)
+([('--cwd', 'foo')], ['x', 'y', '-R', 'bar', '--debugger'])
+>>> get([b'--unknown', b'--cwd=foo', b'--', '--debugger'], gnu=False)
+([], ['--unknown', '--cwd=foo', '--debugger'])
+
+stripping early options (without loosing '--'):
+
+>>> get([b'x', b'-Rbar', b'--', '--debugger'], gnu=True, keepsep=True)[1]
+['x', '--', '--debugger']
+
+last argument:
+
+>>> get([b'--cwd'])
+([], ['--cwd'])
+>>> get([b'--cwd=foo'])
+([('--cwd', 'foo')], [])
+>>> get([b'-R'])
+([], ['-R'])
+>>> get([b'-Rbar'])
+([('-R', 'bar')], [])
+>>> get([b'-q'])
+([('-q', '')], [])
+>>> get([b'-q', b'--'])
+([('-q', '')], [])
+
+value passed to bool options:
+
+>>> ge

[PATCH 2 of 2 STABLE V2] dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options

2017-11-24 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1511443023 -32400
#  Thu Nov 23 22:17:03 2017 +0900
# Branch stable
# Node ID 54e6e3b35ea5a96d2d822ac23d44b4d105178c05
# Parent  78d25e7afffe6ce150da8b1ca32418d6394b0442
dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options

If this feature is enabled, early options are parsed using the global options
table. As the parser stops processing options when non/unknown option is
encountered, it won't mistakenly take an option value as a new early option.
Still "--" can be injected to terminate the parsing (e.g. "hg -R -- log"), I
think it's unlikely to lead to an RCE.

To minimize a risk of this change, new fancyopts.earlygetopt() path is enabled
only when +strictflags is set. Also the strict parser doesn't support '--repo',
a short for '--repository' yet. This limitation will be removed later.

As this feature is backward incompatible, I decided to add a new opt-in
mechanism to HGPLAIN. I'm not pretty sure if this is the right choice, but
I'm thinking of adding +feature/-feature syntax to HGPLAIN. Alternatively,
we could add a new environment variable. Any bikeshedding is welcome.

Note that HGPLAIN=+strictflags doesn't work correctly in chg session since
command arguments are pre-processed in C. This wouldn't be easily fixed.

diff --git a/mercurial/chgserver.py b/mercurial/chgserver.py
--- a/mercurial/chgserver.py
+++ b/mercurial/chgserver.py
@@ -220,8 +220,17 @@ def _loadnewui(srcui, args):
 newui._csystem = srcui._csystem
 
 # command line args
-args = args[:]
-dispatch._parseconfig(newui, dispatch._earlygetopt(['--config'], args))
+options = {}
+if srcui.plain('strictflags'):
+options.update(dispatch._earlyparseopts(args))
+else:
+args = args[:]
+options['config'] = dispatch._earlygetopt(['--config'], args)
+cwds = dispatch._earlygetopt(['--cwd'], args)
+options['cwd'] = cwds and cwds[-1] or ''
+rpath = dispatch._earlygetopt(["-R", "--repository", "--repo"], args)
+options['repository'] = rpath and rpath[-1] or ''
+dispatch._parseconfig(newui, options['config'])
 
 # stolen from tortoisehg.util.copydynamicconfig()
 for section, name, value in srcui.walkconfig():
@@ -232,10 +241,9 @@ def _loadnewui(srcui, args):
 newui.setconfig(section, name, value, source)
 
 # load wd and repo config, copied from dispatch.py
-cwds = dispatch._earlygetopt(['--cwd'], args)
-cwd = cwds and os.path.realpath(cwds[-1]) or None
-rpath = dispatch._earlygetopt(["-R", "--repository", "--repo"], args)
-rpath = rpath and rpath[-1] or ''
+cwd = options['cwd']
+cwd = cwd and os.path.realpath(cwd) or None
+rpath = options['repository']
 path, newlui = dispatch._getlocal(newui, rpath, wd=cwd)
 
 return (newui, newlui)
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -150,6 +150,8 @@ def dispatch(req):
 try:
 if not req.ui:
 req.ui = uimod.ui.load()
+if req.ui.plain('strictflags'):
+req.earlyoptions.update(_earlyparseopts(req.args))
 if _earlyreqoptbool(req, 'traceback', ['--traceback']):
 req.ui.setconfig('ui', 'traceback', 'on', '--traceback')
 
@@ -644,6 +646,12 @@ def _parseconfig(ui, config):
 
 return configs
 
+def _earlyparseopts(args):
+options = {}
+fancyopts.fancyopts(args, commands.globalopts, options,
+gnu=False, early=True)
+return options
+
 def _earlygetopt(aliases, args, strip=True):
 """Return list of values for an option (or aliases).
 
@@ -732,12 +740,16 @@ def _earlygetopt(aliases, args, strip=Tr
 
 def _earlyreqopt(req, name, aliases):
 """Peek a list option without using a full options table"""
+if req.ui.plain('strictflags'):
+return req.earlyoptions[name]
 values = _earlygetopt(aliases, req.args, strip=False)
 req.earlyoptions[name] = values
 return values
 
 def _earlyreqoptstr(req, name, aliases):
 """Peek a string option without using a full options table"""
+if req.ui.plain('strictflags'):
+return req.earlyoptions[name]
 value = (_earlygetopt(aliases, req.args, strip=False) or [''])[-1]
 req.earlyoptions[name] = value
 return value
@@ -745,13 +757,15 @@ def _earlyreqoptstr(req, name, aliases):
 def _earlyreqoptbool(req, name, aliases):
 """Peek a boolean option without using a full options table
 
->>> req = request([b'x', b'--debugger'])
+>>> req = request([b'x', b'--debugger'], uimod.ui())
 >>> _earlyreqoptbool(req, b'debugger', [b'--debugger'])
 True
 
->>> req = request([b'x', b'--', b'--debugger'])
+>>> req = request([b'x', b'--', b'--debugger'], uimod.ui())
 >>> _earlyreqoptbool(req, b'debugger', [b'--debugger'])
 """
+if req.ui.plain('strictflags'):
+return req.earlyoptions[name]
 try:
 argc

D1506: dagop: handle IndexError when using wdir() in dag range

2017-11-24 Thread swhitaker (Simon Whitaker)
swhitaker created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Using wdir() in a dag range revset can crash Mercurial. For example:
  
hg status --rev '.^::wdir()
  
  revlog.c reports an IndexError in this instance, but it isn't caught
  by the calling code. This change adds IndexError to the set of exception
  types the calling code catches. When an IndexError is caught, the code
  falls back to calling the pure Python implementation of reachableroots,
  which fails gracefully.

TEST PLAN
  $ hg status --rev '.::wdir()'
  abort: working directory revision cannot be specified

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/dagop.py

CHANGE DETAILS

diff --git a/mercurial/dagop.py b/mercurial/dagop.py
--- a/mercurial/dagop.py
+++ b/mercurial/dagop.py
@@ -230,7 +230,7 @@
 heads = list(heads)
 try:
 revs = repo.changelog.reachableroots(minroot, heads, roots, 
includepath)
-except AttributeError:
+except (AttributeError, IndexError):
 revs = _reachablerootspure(repo, minroot, roots, heads, includepath)
 revs = baseset(revs)
 revs.sort()



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


D1502: rewriteutil: add utility function to check if we can create new unstable cset

2017-11-24 Thread dlax (Denis Laxalde)
dlax added a comment.


  > This rewriteutil.py introduced in this patch and the utility functions 
added in the upcoming patches exists in the evolve extension are being ported 
from there.
  
  Is it worth porting this alone if nothing in core makes use of this module?
  Or is there a larger plan?

REPOSITORY
  rHG Mercurial

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

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