Re: D3826: grep : change default behaviour of grep

2018-06-23 Thread Yuya Nishihara
> @@ -2431,6 +2431,10 @@
>  Returns 0 if a match is found, 1 otherwise.
>  """
>  opts = pycompat.byteskwargs(opts)
> +
> +if len(opts.get('rev')) ==1:
> +opts['allfiles'] = True

So, `-rA` implies `--allfiles` but `-rA -rB` doesn't? which seems worse than
the current situation.

And we'll need an option to get back the original behavior.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3826: grep: change default behaviour of grep

2018-06-23 Thread yuja (Yuya Nishihara)
yuja added a comment.


  > @@ -2431,6 +2431,10 @@
  > 
  >   Returns 0 if a match is found, 1 otherwise.
  >   """
  >   opts = pycompat.byteskwargs(opts)
  > 
  > +
  >  +if len(opts.get('rev')) ==1:
  >  +opts['allfiles'] = True
  
  So, `-rA` implies `--allfiles` but `-rA -rB` doesn't? which seems worse than
  the current situation.
  
  And we'll need an option to get back the original behavior.

REPOSITORY
  rHG Mercurial

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

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


Re: D3829: rebase: make dry-run return 1 or 0 according to result

2018-06-23 Thread Yuya Nishihara
> --- a/hgext/rebase.py
> +++ b/hgext/rebase.py
> @@ -825,10 +825,13 @@
>  **opts)
>  except error.InMemoryMergeConflictsError:
>  ui.status(_('hit a merge conflict\n'))
> +retcode = 1
>  else:
> +retcode = 0
>  ui.status(_('there will be no conflict, you can rebase\n'))
>  finally:
>  _origrebase(ui, repo, abort=True)
> +return retcode

`retcode` may be undefined depending on the error type occurred in
`_origrebase()`. Instead, you can simply return 1 and 0 in the `except`
and `else` clauses respectively.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3829: rebase: make dry-run return 1 or 0 according to result

2018-06-23 Thread yuja (Yuya Nishihara)
yuja added a comment.


  > - a/hgext/rebase.py +++ b/hgext/rebase.py @@ -825,10 +825,13 @@ **opts) 
except error.InMemoryMergeConflictsError: ui.status(_('hit a merge 
conflict\n')) +retcode = 1 else: +retcode = 0 
ui.status(_('there will be no conflict, you can rebase\n')) finally: 
_origrebase(ui, repo, abort=True) +return retcode
  
  `retcode` may be undefined depending on the error type occurred in
  `_origrebase()`. Instead, you can simply return 1 and 0 in the `except`
  and `else` clauses respectively.

REPOSITORY
  rHG Mercurial

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

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


D3827: rebase: no need to store backup during dry-run while aborting

2018-06-23 Thread yuja (Yuya Nishihara)
yuja added a comment.


  > - def _prepareabortorcontinue(self, isabort): +def 
_prepareabortorcontinue(self, isabort, opts={}):
  
  Mutable default value should be avoided. It can be `backup=True` since we
  aren't processing command-level thingy here.
  
  And please make sure tests pass before sending out patches.
  
  > @@ -828,7 +829,8 @@
  > 
  >   else:
  >   ui.status(_('there will be no conflict, you can rebase\n'))
  >   finally:
  > 
  > - _origrebase(ui, repo, abort=True) +opts = {'abort':True, 
'no_backup':True} +_origrebase(ui, repo, **opts)
  
  Maybe we can refactor the dryrun handling in a way we don't have to pass 
around
  the no_backup flag. IIUC, `_origrebase()` is a high-level function which has
  many parameter/state checks, but what we want is to cancel the in-memory
  session we've made just before. No user error should occur.
  
  > @@ -1588,7 +1590,10 @@
  > 
  >   1. Strip from the first rebased revision if rebased:
  > - repair.strip(repo.ui, repo, strippoints) +if nobackup: +  
  repair.strip(repo.ui, repo, strippoints, backup=False) +  
  else: +repair.strip(repo.ui, repo, strippoints)
  
  This can be written as `backup=not nobackup` or `backup=backup`.

REPOSITORY
  rHG Mercurial

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

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


Re: D3827: rebase: no need to store backup during dry-run while aborting

2018-06-23 Thread Yuya Nishihara
> -def _prepareabortorcontinue(self, isabort):
> +def _prepareabortorcontinue(self, isabort, opts={}):

Mutable default value should be avoided. It can be `backup=True` since we
aren't processing command-level thingy here.

And please make sure tests pass before sending out patches.

> @@ -828,7 +829,8 @@
>  else:
>  ui.status(_('there will be no conflict, you can rebase\n'))
>  finally:
> -_origrebase(ui, repo, abort=True)
> +opts = {'abort':True, 'no_backup':True}
> +_origrebase(ui, repo, **opts)

Maybe we can refactor the dryrun handling in a way we don't have to pass around
the no_backup flag. IIUC, `_origrebase()` is a high-level function which has
many parameter/state checks, but what we want is to cancel the in-memory
session we've made just before. No user error should occur.

> @@ -1588,7 +1590,10 @@
>  
>  # Strip from the first rebased revision
>  if rebased:
> -repair.strip(repo.ui, repo, strippoints)
> +if nobackup:
> +repair.strip(repo.ui, repo, strippoints, backup=False)
> +else:
> +repair.strip(repo.ui, repo, strippoints)

This can be written as `backup=not nobackup` or `backup=backup`.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[Bug 5928] New: log command streams entire log after pager closes

2018-06-23 Thread mercurial-bugs
https://bz.mercurial-scm.org/show_bug.cgi?id=5928

Bug ID: 5928
   Summary: log command streams entire log after pager closes
   Product: Mercurial
   Version: 4.6.1
  Hardware: PC
OS: Windows
Status: UNCONFIRMED
  Severity: bug
  Priority: wish
 Component: pager
  Assignee: bugzi...@mercurial-scm.org
  Reporter: edwin.br...@gmail.com
CC: mercurial-devel@mercurial-scm.org

On windows when using pager with hg log mercurial will stream the entire log
after terminating the pager. The user must manually terminate the process. 

This problem has existed on windows for several releases.

Ideally, the log command should stop streaming data once the pager is closed.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D3764: rebase: improve output of --dry-run

2018-06-23 Thread khanchi97 (Sushil khanchi)
khanchi97 updated this revision to Diff 9264.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3764?vs=9263=9264

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

AFFECTED FILES
  hgext/rebase.py
  tests/test-rebase-inmemory.t

CHANGE DETAILS

diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t
--- a/tests/test-rebase-inmemory.t
+++ b/tests/test-rebase-inmemory.t
@@ -208,11 +208,11 @@
 
 Check dryrun gives correct results when there is no conflict in rebasing
   $ hg rebase -s 2 -d 6 -n
+  starting dry-run rebase; repository will not be changed
   rebasing 2:177f92b77385 "c"
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
-  there will be no conflict, you can rebase
-  rebase aborted
+  dry-run rebase completed successfully; run without -n/--dry-run to perform 
this rebase
 
   $ hg diff
   $ hg status
@@ -241,11 +241,11 @@
   
 Check dryrun working with --collapse when there is no conflict
   $ hg rebase -s 2 -d 6 -n --collapse
+  starting dry-run rebase; repository will not be changed
   rebasing 2:177f92b77385 "c"
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
-  there will be no conflict, you can rebase
-  rebase aborted
+  dry-run rebase completed successfully; run without -n/--dry-run to perform 
this rebase
 
 Check dryrun gives correct results when there is conflict in rebasing
 Make a conflict:
@@ -278,14 +278,14 @@
  a
   
   $ hg rebase -s 2 -d 7 -n
+  starting dry-run rebase; repository will not be changed
   rebasing 2:177f92b77385 "c"
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
   merging e
   transaction abort!
   rollback completed
   hit a merge conflict
-  rebase aborted
   $ hg diff
   $ hg status
   $ hg log -G --template "{rev}:{short(node)} 
{person(author)}\n{firstline(desc)} {topic}\n\n"
@@ -315,9 +315,9 @@
   
 Check dryrun working with --collapse when there is conflicts
   $ hg rebase -s 2 -d 7 -n --collapse
+  starting dry-run rebase; repository will not be changed
   rebasing 2:177f92b77385 "c"
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
   merging e
   hit a merge conflict
-  rebase aborted
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -341,9 +341,11 @@
 hint = _('use "hg rebase --abort" to clear broken state')
 raise error.Abort(msg, hint=hint)
 if isabort:
+suppwarns = opts.get(r'dry_run')
 nobackup = opts.get(r'no_backup')
 return abort(self.repo, self.originalwd, self.destmap, self.state,
- activebookmark=self.activebookmark, nobackup=nobackup)
+ activebookmark=self.activebookmark, nobackup=nobackup,
+ suppwarns=suppwarns)
 
 def _preparenewrebase(self, destmap):
 if not destmap:
@@ -819,17 +821,19 @@
 opts[r'dest'] = '_destautoorphanrebase(SRC)'
 
 if dryrun:
+ui.status(_('starting dry-run rebase; repository will not be 
changed\n'))
 try:
 overrides = {('rebase', 'singletransaction'): True}
 with ui.configoverride(overrides, 'rebase'):
 _origrebase(ui, repo, inmemory=True, leaveunfinished=True,
 **opts)
 except error.InMemoryMergeConflictsError:
 ui.status(_('hit a merge conflict\n'))
 else:
-ui.status(_('there will be no conflict, you can rebase\n'))
+ui.status(_('dry-run rebase completed successfully; run without '
+'-n/--dry-run to perform this rebase\n'))
 finally:
-opts = {'abort':True, 'no_backup':True}
+opts = {'abort':True, 'no_backup':True, 'dry_run':True}
 _origrebase(ui, repo, **opts)
 elif inmemory:
 try:
@@ -1545,7 +1549,8 @@
 
 return False
 
-def abort(repo, originalwd, destmap, state, activebookmark=None, 
nobackup=False):
+def abort(repo, originalwd, destmap, state, activebookmark=None, 
nobackup=False,
+  suppwarns=False):
 '''Restore the repository to its original state.  Additional args:
 
 activebookmark: the name of the bookmark that should be active after the
@@ -1601,7 +1606,8 @@
 finally:
 clearstatus(repo)
 clearcollapsemsg(repo)
-repo.ui.warn(_('rebase aborted\n'))
+if not suppwarns:
+repo.ui.warn(_('rebase aborted\n'))
 return 0
 
 def sortsource(destmap):



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


D3764: rebase: improve output of --dry-run

2018-06-23 Thread khanchi97 (Sushil khanchi)
khanchi97 updated this revision to Diff 9263.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3764?vs=9259=9263

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

AFFECTED FILES
  hgext/rebase.py
  tests/test-rebase-inmemory.t

CHANGE DETAILS

diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t
--- a/tests/test-rebase-inmemory.t
+++ b/tests/test-rebase-inmemory.t
@@ -208,11 +208,11 @@
 
 Check dryrun gives correct results when there is no conflict in rebasing
   $ hg rebase -s 2 -d 6 -n
+  starting dry-run rebase; repository will not be changed
   rebasing 2:177f92b77385 "c"
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
-  there will be no conflict, you can rebase
-  rebase aborted
+  dry-run rebase completed successfully; run without -n/--dry-run to perform 
this rebase
 
   $ hg diff
   $ hg status
@@ -241,11 +241,11 @@
   
 Check dryrun working with --collapse when there is no conflict
   $ hg rebase -s 2 -d 6 -n --collapse
+  starting dry-run rebase; repository will not be changed
   rebasing 2:177f92b77385 "c"
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
-  there will be no conflict, you can rebase
-  rebase aborted
+  dry-run rebase completed successfully; run without -n/--dry-run to perform 
this rebase
 
 Check dryrun gives correct results when there is conflict in rebasing
 Make a conflict:
@@ -278,14 +278,14 @@
  a
   
   $ hg rebase -s 2 -d 7 -n
+  starting dry-run rebase; repository will not be changed
   rebasing 2:177f92b77385 "c"
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
   merging e
   transaction abort!
   rollback completed
   hit a merge conflict
-  rebase aborted
   $ hg diff
   $ hg status
   $ hg log -G --template "{rev}:{short(node)} 
{person(author)}\n{firstline(desc)} {topic}\n\n"
@@ -315,9 +315,9 @@
   
 Check dryrun working with --collapse when there is conflicts
   $ hg rebase -s 2 -d 7 -n --collapse
+  starting dry-run rebase; repository will not be changed
   rebasing 2:177f92b77385 "c"
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
   merging e
   hit a merge conflict
-  rebase aborted
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -341,9 +341,11 @@
 hint = _('use "hg rebase --abort" to clear broken state')
 raise error.Abort(msg, hint=hint)
 if isabort:
+suppwarns = opts.get(r'dry_run')
 nobackup = opts.get(r'no_backup')
 return abort(self.repo, self.originalwd, self.destmap, self.state,
- activebookmark=self.activebookmark, nobackup=nobackup)
+ activebookmark=self.activebookmark, nobackup=nobackup,
+ suppwarns=suppwarns)
 
 def _preparenewrebase(self, destmap):
 if not destmap:
@@ -819,17 +821,19 @@
 opts[r'dest'] = '_destautoorphanrebase(SRC)'
 
 if dryrun:
+ui.status(_('starting dry-run rebase; repository will not be 
changed\n'))
 try:
 overrides = {('rebase', 'singletransaction'): True}
 with ui.configoverride(overrides, 'rebase'):
 _origrebase(ui, repo, inmemory=True, leaveunfinished=True,
 **opts)
 except error.InMemoryMergeConflictsError:
 ui.status(_('hit a merge conflict\n'))
 else:
-ui.status(_('there will be no conflict, you can rebase\n'))
+ui.status(_('dry-run rebase completed successfully; run without '
+'-n/--dry-run to perform this rebase\n'))
 finally:
-opts = {'abort':True, 'no_backup':True}
+opts = {'abort':True, 'no_backup':True, 'dry_run':True}
 _origrebase(ui, repo, **opts)
 elif inmemory:
 try:
@@ -1545,7 +1549,8 @@
 
 return False
 
-def abort(repo, originalwd, destmap, state, activebookmark=None, 
nobackup=False):
+def abort(repo, originalwd, destmap, state, activebookmark=None, 
nobackup=False,
+  suppwarning=False):
 '''Restore the repository to its original state.  Additional args:
 
 activebookmark: the name of the bookmark that should be active after the
@@ -1601,7 +1606,8 @@
 finally:
 clearstatus(repo)
 clearcollapsemsg(repo)
-repo.ui.warn(_('rebase aborted\n'))
+if not suppwarning:
+repo.ui.warn(_('rebase aborted\n'))
 return 0
 
 def sortsource(destmap):



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


D3827: rebase: no need to store backup during dry-run while aborting

2018-06-23 Thread khanchi97 (Sushil khanchi)
khanchi97 updated this revision to Diff 9262.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3827?vs=9260=9262

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

AFFECTED FILES
  hgext/rebase.py
  tests/test-rebase-inmemory.t

CHANGE DETAILS

diff --git a/tests/test-rebase-inmemory.t b/tests/test-rebase-inmemory.t
--- a/tests/test-rebase-inmemory.t
+++ b/tests/test-rebase-inmemory.t
@@ -212,7 +212,6 @@
   rebasing 3:055a42cdd887 "d"
   rebasing 4:e860deea161a "e"
   there will be no conflict, you can rebase
-  saved backup bundle to 
$TESTTMP/repo1/repo2/skrepo/.hg/strip-backup/c83b1da5b1ae-f1e0beb9-backup.hg
   rebase aborted
 
   $ hg diff
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -325,7 +325,7 @@
 skippedset.update(obsoleteextinctsuccessors)
 _checkobsrebase(self.repo, self.ui, obsoleteset, skippedset)
 
-def _prepareabortorcontinue(self, isabort):
+def _prepareabortorcontinue(self, isabort, opts={}):
 try:
 self.restorestatus()
 self.collapsemsg = restorecollapsemsg(self.repo, isabort)
@@ -341,8 +341,9 @@
 hint = _('use "hg rebase --abort" to clear broken state')
 raise error.Abort(msg, hint=hint)
 if isabort:
-return abort(self.repo, self.originalwd, self.destmap,
- self.state, activebookmark=self.activebookmark)
+nobackup = opts.get(r'no_backup')
+return abort(self.repo, self.originalwd, self.destmap, self.state,
+ activebookmark=self.activebookmark, nobackup=nobackup)
 
 def _preparenewrebase(self, destmap):
 if not destmap:
@@ -828,7 +829,8 @@
 else:
 ui.status(_('there will be no conflict, you can rebase\n'))
 finally:
-_origrebase(ui, repo, abort=True)
+opts = {'abort':True, 'no_backup':True}
+_origrebase(ui, repo, **opts)
 elif inmemory:
 try:
 # in-memory merge doesn't support conflicts, so if we hit any, 
abort
@@ -889,7 +891,7 @@
 ms = mergemod.mergestate.read(repo)
 mergeutil.checkunresolved(ms)
 
-retcode = rbsrt._prepareabortorcontinue(abortf)
+retcode = rbsrt._prepareabortorcontinue(abortf, opts=opts)
 if retcode is not None:
 return retcode
 else:
@@ -1543,7 +1545,7 @@
 
 return False
 
-def abort(repo, originalwd, destmap, state, activebookmark=None):
+def abort(repo, originalwd, destmap, state, activebookmark=None, 
nobackup=False):
 '''Restore the repository to its original state.  Additional args:
 
 activebookmark: the name of the bookmark that should be active after the
@@ -1588,7 +1590,10 @@
 
 # Strip from the first rebased revision
 if rebased:
-repair.strip(repo.ui, repo, strippoints)
+if nobackup:
+repair.strip(repo.ui, repo, strippoints, backup=False)
+else:
+repair.strip(repo.ui, repo, strippoints)
 
 if activebookmark and activebookmark in repo._bookmarks:
 bookmarks.activate(repo, activebookmark)



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


[PATCH 1 of 4] templater: fix truth testing of integer 0 taken from a list/dict

2018-06-23 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1529219438 -32400
#  Sun Jun 17 16:10:38 2018 +0900
# Node ID 720fc7b592ef6dd5dc11a7ec48a715ee39c1006a
# Parent  36edfbac7281c731b1aed8e73555b22c2ccb96c0
templater: fix truth testing of integer 0 taken from a list/dict

Broken at f9c426385853. bool(python_value) shouldn't be used here since
an integer 0 has to be truthy for backward compatibility.

diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py
--- a/mercurial/templateutil.py
+++ b/mercurial/templateutil.py
@@ -350,7 +350,8 @@ class hybriditem(mappable, wrapped):
 return gen
 
 def tobool(self, context, mapping):
-return bool(self.tovalue(context, mapping))
+w = makewrapped(context, mapping, self._value)
+return w.tobool(context, mapping)
 
 def tovalue(self, context, mapping):
 return _unthunk(context, mapping, self._value)
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
@@ -932,6 +932,8 @@ Test boolean expression/literal passed t
   rev 0 is True
   $ hg log -r 0 -T '{if(0, "literal 0 is True as well")}\n'
   literal 0 is True as well
+  $ hg log -r 0 -T '{if(min(revset(r"0")), "0 of hybriditem is also True")}\n'
+  0 of hybriditem is also True
   $ hg log -r 0 -T '{if("", "", "empty string is False")}\n'
   empty string is False
   $ hg log -r 0 -T '{if(revset(r"0 - 0"), "", "empty list is False")}\n'
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 4 of 4] show: use filter() function to strip "tip" tag

2018-06-23 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1528986171 -32400
#  Thu Jun 14 23:22:51 2018 +0900
# Node ID 7d4982dc9d52624ebd62f249639ca596101415ca
# Parent  f2d42f1933ce7e28647f2b834c86de3369fbbe00
show: use filter() function to strip "tip" tag

Before, an empty tag "" was inserted in place of "tip", resulting in double
spaces.

diff --git a/mercurial/templates/map-cmdline.show 
b/mercurial/templates/map-cmdline.show
--- a/mercurial/templates/map-cmdline.show
+++ b/mercurial/templates/map-cmdline.show
@@ -15,8 +15,11 @@ cset_shortnode = '{labelcset(shortest(no
 # Treat branch and tags specially so we don't display "default" or "tip"
 cset_namespace = '{ifeq(namespace, "branches", names_branches, ifeq(namespace, 
"tags", names_tags, names_others))}'
 names_branches = '{ifeq(branch, "default", "", " ({label('log.{colorname}', 
branch)})")}'
-names_tags = '{if(stringify(names % "{ifeq(name, 'tip', '', name)}"),
-  " ({label('log.{colorname}', join(names % "{ifeq(name, 
'tip', '', name)}", ' '))})")}'
+names_tags = '{if(filter_tags(names),
+  " ({label('log.{colorname}', join(filter_tags(names), ' 
'))})")}'
 names_others = '{if(names, " ({label('log.{colorname}', join(names, ' '))})")}'
 
 cset_shortdesc = '{label("log.description", desc|firstline)}'
+
+[templatealias]
+filter_tags(names) = filter(names, ifeq(name, 'tip', '', name))
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH 2 of 4] templater: introduce filter() function to remove empty items from list

2018-06-23 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1528983206 -32400
#  Thu Jun 14 22:33:26 2018 +0900
# Node ID f14965009644ab63cbe1990081493e8d490a30eb
# Parent  720fc7b592ef6dd5dc11a7ec48a715ee39c1006a
templater: introduce filter() function to remove empty items from list

The primary use case is to filter out "tip" from a list of tags.

diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -727,6 +727,10 @@ class sessionvars(templateutil.wrapped):
 def getmax(self, context, mapping):
 raise error.ParseError(_('not comparable'))
 
+def filter(self, context, mapping, select):
+# implement if necessary
+raise error.ParseError(_('not filterable'))
+
 def itermaps(self, context):
 separator = self._start
 for key, value in sorted(self._vars.iteritems()):
diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -166,6 +166,17 @@ def fill(context, mapping, args):
 
 return templatefilters.fill(text, width, initindent, hangindent)
 
+@templatefunc('filter(iterable)')
+def filter_(context, mapping, args):
+"""Remove empty elements from a list or a dict."""
+if len(args) != 1:
+# i18n: "filter" is a keyword
+raise error.ParseError(_("filter expects one argument"))
+iterable = evalwrapped(context, mapping, args[0])
+def select(w):
+return w.tobool(context, mapping)
+return iterable.filter(context, mapping, select)
+
 @templatefunc('formatnode(node)', requires={'ui'})
 def formatnode(context, mapping, args):
 """Obtain the preferred form of a changeset hash. (DEPRECATED)"""
diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py
--- a/mercurial/templateutil.py
+++ b/mercurial/templateutil.py
@@ -63,6 +63,14 @@ class wrapped(object):
 value depending on the self type"""
 
 @abc.abstractmethod
+def filter(self, context, mapping, select):
+"""Return new container of the same type which includes only the
+selected elements
+
+select() takes each item as a wrapped object and returns True/False.
+"""
+
+@abc.abstractmethod
 def itermaps(self, context):
 """Yield each template mapping"""
 
@@ -130,6 +138,10 @@ class wrappedbytes(wrapped):
 raise error.ParseError(_('empty string'))
 return func(pycompat.iterbytestr(self._value))
 
+def filter(self, context, mapping, select):
+raise error.ParseError(_('%r is not filterable')
+   % pycompat.bytestr(self._value))
+
 def itermaps(self, context):
 raise error.ParseError(_('%r is not iterable of mappings')
% pycompat.bytestr(self._value))
@@ -164,6 +176,9 @@ class wrappedvalue(wrapped):
 def getmax(self, context, mapping):
 raise error.ParseError(_("%r is not iterable") % self._value)
 
+def filter(self, context, mapping, select):
+raise error.ParseError(_("%r is not iterable") % self._value)
+
 def itermaps(self, context):
 raise error.ParseError(_('%r is not iterable of mappings')
% self._value)
@@ -208,6 +223,9 @@ class date(mappable, wrapped):
 def getmax(self, context, mapping):
 raise error.ParseError(_('date is not iterable'))
 
+def filter(self, context, mapping, select):
+raise error.ParseError(_('date is not iterable'))
+
 def join(self, context, mapping, sep):
 raise error.ParseError(_("date is not iterable"))
 
@@ -273,6 +291,14 @@ class hybrid(wrapped):
 return val
 return hybriditem(None, key, val, self._makemap)
 
+def filter(self, context, mapping, select):
+if util.safehasattr(self._values, 'get'):
+values = {k: v for k, v in self._values.iteritems()
+  if select(self._wrapvalue(k, v))}
+else:
+values = [v for v in self._values if select(self._wrapvalue(v, v))]
+return hybrid(None, values, self._makemap, self._joinfmt, 
self._keytype)
+
 def itermaps(self, context):
 makemap = self._makemap
 for x in self._values:
@@ -336,6 +362,10 @@ class hybriditem(mappable, wrapped):
 w = makewrapped(context, mapping, self._value)
 return w.getmax(context, mapping)
 
+def filter(self, context, mapping, select):
+w = makewrapped(context, mapping, self._value)
+return w.filter(context, mapping, select)
+
 def join(self, context, mapping, sep):
 w = makewrapped(context, mapping, self._value)
 return w.join(context, mapping, sep)
@@ -384,6 +414,9 @@ class _mappingsequence(wrapped):
 def getmax(self, context, mapping):
 raise error.ParseError(_('not comparable'))
 
+def filter(self, context, mapping, select):
+raise error.ParseError(_('not 

[PATCH 3 of 4] templater: extend filter() to accept template expression for emptiness test

2018-06-23 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1528985414 -32400
#  Thu Jun 14 23:10:14 2018 +0900
# Node ID f2d42f1933ce7e28647f2b834c86de3369fbbe00
# Parent  f14965009644ab63cbe1990081493e8d490a30eb
templater: extend filter() to accept template expression for emptiness test

This utilizes the pass-by-name nature of template arguments.

diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -166,15 +166,23 @@ def fill(context, mapping, args):
 
 return templatefilters.fill(text, width, initindent, hangindent)
 
-@templatefunc('filter(iterable)')
+@templatefunc('filter(iterable[, expr])')
 def filter_(context, mapping, args):
-"""Remove empty elements from a list or a dict."""
-if len(args) != 1:
+"""Remove empty elements from a list or a dict. If expr specified, it's
+applied to each element to test emptiness."""
+if not (1 <= len(args) <= 2):
 # i18n: "filter" is a keyword
-raise error.ParseError(_("filter expects one argument"))
+raise error.ParseError(_("filter expects one or two arguments"))
 iterable = evalwrapped(context, mapping, args[0])
-def select(w):
-return w.tobool(context, mapping)
+if len(args) == 1:
+def select(w):
+return w.tobool(context, mapping)
+else:
+def select(w):
+if not isinstance(w, templateutil.mappable):
+raise error.ParseError(_("not filterable by expression"))
+lm = context.overlaymap(mapping, w.tomap(context))
+return evalboolean(context, lm, args[1])
 return iterable.filter(context, mapping, select)
 
 @templatefunc('formatnode(node)', requires={'ui'})
diff --git a/mercurial/templateutil.py b/mercurial/templateutil.py
--- a/mercurial/templateutil.py
+++ b/mercurial/templateutil.py
@@ -415,6 +415,7 @@ class _mappingsequence(wrapped):
 raise error.ParseError(_('not comparable'))
 
 def filter(self, context, mapping, select):
+# implement if necessary; we'll need a wrapped type for a mapping dict
 raise error.ParseError(_('not filterable without template'))
 
 def join(self, context, mapping, sep):
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
@@ -449,6 +449,13 @@ Test filter() empty values:
   $ hg log -R a -r 0 -T '{filter(revset("0:2"))}\n'
   0 1 2
 
+Test filter() by expression:
+
+  $ hg log -R a -r 1 -T '{filter(desc|splitlines, ifcontains("1", line, 
"t"))}\n'
+  other 1
+  $ hg log -R a -r 0 -T '{filter(dict(a=0, b=1), ifeq(key, "b", "t"))}\n'
+  b=1
+
 Test filter() shouldn't crash:
 
   $ hg log -R a -r 0 -T '{filter(extras)}\n'
@@ -459,7 +466,7 @@ Test filter() shouldn't crash:
 Test filter() unsupported arguments:
 
   $ hg log -R a -r 0 -T '{filter()}\n'
-  hg: parse error: filter expects one argument
+  hg: parse error: filter expects one or two arguments
   [255]
   $ hg log -R a -r 0 -T '{filter(date)}\n'
   hg: parse error: date is not iterable
@@ -476,6 +483,9 @@ Test filter() unsupported arguments:
   $ hg log -R a -r 0 -T '{filter(succsandmarkers)}\n'
   hg: parse error: not filterable without template
   [255]
+  $ hg log -R a -r 0 -T '{filter(desc|splitlines % "{line}", "")}\n'
+  hg: parse error: not filterable by expression
+  [255]
 
 Test manifest/get() can be join()-ed as string, though it's silly:
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel