D9081: git: add test showing `hg commit -i` working on a git repo

2020-09-24 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Shows `hg commit -i` working on a git repo via the `git`
  extension. Adds working directory changes to files `alpha` and
  `beta`, then selects only `alpha` changes and commits them.
  
  As of now this would fail for a filename that
  includes uppercase characters due to the lack of case folding
  support in the extension.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  tests/test-git-interop.t

CHANGE DETAILS

diff --git a/tests/test-git-interop.t b/tests/test-git-interop.t
--- a/tests/test-git-interop.t
+++ b/tests/test-git-interop.t
@@ -272,6 +272,87 @@
   +beta
 
 
+Interactive commit should work as expected
+
+  $ echo bar >> alpha
+  $ echo bar >> beta
+  $ hg commit -m "test interactive commit" -i --config ui.interactive=true 
--config ui.interface=text << EOF
+  > y
+  > y
+  > n
+  > EOF
+  diff --git a/alpha b/alpha
+  1 hunks, 1 lines changed
+  examine changes to 'alpha'?
+  (enter ? for help) [Ynesfdaq?] y
+  
+  @@ -1,3 +1,4 @@
+   alpha
+   a
+   a
+  +bar
+  record change 1/2 to 'alpha'?
+  (enter ? for help) [Ynesfdaq?] y
+  
+  diff --git a/beta b/beta
+  1 hunks, 1 lines changed
+  examine changes to 'beta'?
+  (enter ? for help) [Ynesfdaq?] n
+  
+Status should be consistent for both systems
+
+  $ hg status
+  heads mismatch, rebuilding dagcache
+  M beta
+  $ git status
+  On branch master
+  Changes not staged for commit:
+(use "git add ..." to update what will be committed)
+(use "git checkout -- ..." to discard changes in working directory)
+  
+   modified:   beta
+  
+  no changes added to commit (use "git add" and/or "git commit -a")
+
+Contents of each commit should be the same
+
+  $ hg ex -r .
+  # HG changeset patch
+  # User test 
+  # Date 0 0
+  #  Thu Jan 01 00:00:00 1970 +
+  # Node ID 80adc61cf57e99f6a412d83fee6239d1556cefcf
+  # Parent  ae1ab744f95bfd5b07cf573baef98a778058537b
+  test interactive commit
+  
+  diff -r ae1ab744f95b -r 80adc61cf57e alpha
+  --- a/alpha  Thu Jan 01 00:00:00 1970 +
+  +++ b/alpha  Thu Jan 01 00:00:00 1970 +
+  @@ -1,3 +1,4 @@
+   alpha
+   a
+   a
+  +bar
+  $ git show 
+  commit 80adc61cf57e99f6a412d83fee6239d1556cefcf
+  Author: test 
+  Date:   Thu Jan 1 00:00:00 1970 +
+  
+  test interactive commit
+  
+  diff --git a/alpha b/alpha
+  index d112a75..d2a2e9a 100644
+  --- a/alpha
+  +++ b/alpha
+  @@ -1,3 +1,4 @@
+   alpha
+   a
+   a
+  +bar
+
 Deleting files should also work (this was issue6398)
+  $ hg revert -r . --all
+  reverting beta
   $ hg rm beta
   $ hg ci -m 'remove beta'
+



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


D9068: git: pass `id` attribute of `pygit2.Tree` object

2020-09-22 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  `pygit2`'s Repository object expects an instance of `Oid`
  to return the corresponding object, instead of the object
  itself.
  
  After this change and D9062 , `hg 
commit -i` seems to work,
  unless it hits a case folding assertion (ie trying to add
  a file like `README.md`).

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  hgext/git/manifest.py

CHANGE DETAILS

diff --git a/hgext/git/manifest.py b/hgext/git/manifest.py
--- a/hgext/git/manifest.py
+++ b/hgext/git/manifest.py
@@ -322,7 +322,8 @@
 for part in comps:
 parent = trees[full]
 try:
-new = self._repo[parent[pycompat.fsdecode(part)]]
+parent_tree_id = parent[pycompat.fsdecode(part)].id
+new = self._repo[parent_tree_id]
 except KeyError:
 # new directory
 new = None



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


D8781: infinitepush: fix `{get,put}_args` formatting on Python 3

2020-07-21 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Calling `.format()` on a byte-string does not work, thus
  causing an exception on Python 3. This commit adds a function
  to paper over the difference.

REPOSITORY
  rHG Mercurial

BRANCH
  stable

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

AFFECTED FILES
  hgext/infinitepush/store.py

CHANGE DETAILS

diff --git a/hgext/infinitepush/store.py b/hgext/infinitepush/store.py
--- a/hgext/infinitepush/store.py
+++ b/hgext/infinitepush/store.py
@@ -106,6 +106,23 @@
 return None
 
 
+def format_placeholders_args(args, filename=None, handle=None):
+"""Formats `args` with Infinitepush replacements.
+
+Hack to get `str.format()`-ed strings working in a BC way with
+bytes.
+"""
+formatted_args = []
+for arg in args:
+if filename and arg == b'{filename}':
+formatted_args.append(filename)
+elif handle and arg == b'{handle}':
+formatted_args.append(handle)
+else:
+formatted_args.append(arg)
+return formatted_args
+
+
 class externalbundlestore(abstractbundlestore):
 def __init__(self, put_binary, put_args, get_binary, get_args):
 """
@@ -144,9 +161,9 @@
 temp.write(data)
 temp.flush()
 temp.seek(0)
-formatted_args = [
-arg.format(filename=temp.name) for arg in self.put_args
-]
+formatted_args = format_placeholders_args(
+self.put_args, filename=temp.name
+)
 returncode, stdout, stderr = self._call_binary(
 [self.put_binary] + formatted_args
 )
@@ -166,12 +183,10 @@
 def read(self, handle):
 # Won't work on windows because you can't open file second time without
 # closing it
-# TODO: rewrite without str.format()
 with pycompat.namedtempfile() as temp:
-formatted_args = [
-arg.format(filename=temp.name, handle=handle)
-for arg in self.get_args
-]
+formatted_args = format_placeholders_args(
+self.get_args, filename=temp.name, handle=handle
+)
 returncode, stdout, stderr = self._call_binary(
 [self.get_binary] + formatted_args
 )



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


D8780: infinitepush: replace `NamedTemporaryFile` with `pycompat.namedtempfile`

2020-07-21 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Fixes a Python 3 compat error when using the external bundle store.

REPOSITORY
  rHG Mercurial

BRANCH
  stable

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

AFFECTED FILES
  hgext/infinitepush/store.py

CHANGE DETAILS

diff --git a/hgext/infinitepush/store.py b/hgext/infinitepush/store.py
--- a/hgext/infinitepush/store.py
+++ b/hgext/infinitepush/store.py
@@ -20,8 +20,6 @@
 procutil,
 )
 
-NamedTemporaryFile = tempfile.NamedTemporaryFile
-
 
 class BundleWriteException(Exception):
 pass
@@ -142,7 +140,7 @@
 # closing it
 # TODO: rewrite without str.format() and replace NamedTemporaryFile()
 # with pycompat.namedtempfile()
-with NamedTemporaryFile() as temp:
+with pycompat.namedtempfile() as temp:
 temp.write(data)
 temp.flush()
 temp.seek(0)
@@ -168,9 +166,8 @@
 def read(self, handle):
 # Won't work on windows because you can't open file second time without
 # closing it
-# TODO: rewrite without str.format() and replace NamedTemporaryFile()
-# with pycompat.namedtempfile()
-with NamedTemporaryFile() as temp:
+# TODO: rewrite without str.format()
+with pycompat.namedtempfile() as temp:
 formatted_args = [
 arg.format(filename=temp.name, handle=handle)
 for arg in self.get_args



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


D8573: fsmonitor: coerce `clock` variable to byte-string (issue6321)

2020-05-20 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Callers of `fsmonitor.state.setlastclock` pass their arguments
  wrapped in `pycompat.sysbytes` to ensure the value is a `bytes`
  on Python 3. However in `fsmonitor.poststatus.__call__`, if the
  return value of `getlastclock()` is `None`, we use the value of
  `fsmonitor.poststatus._startclock` instead, which is not converted
  to a byte string in the same manner. This commit converts the
  value of `startclock` to a byte string using `pycompat.sysbytes`
  in the constructor for `poststatus`, to avoid the "`str` + `bytes`"
  error from issue 6321.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

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
@@ -667,7 +667,7 @@
 
 class poststatus(object):
 def __init__(self, startclock):
-self._startclock = startclock
+self._startclock = pycompat.sysbytes(startclock)
 
 def __call__(self, wctx, status):
 clock = wctx.repo()._fsmonitorstate.getlastclock() or self._startclock



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


D7810: packaging: update Ubuntu docker build dependencies to Python 3

2020-01-08 Thread sheehan (Connor Sheehan)
Closed by commit rHGb084ad4875a4: packaging: update Ubuntu docker build 
dependencies to Python 3 (authored by sheehan).
This revision was automatically updated to reflect the committed changes.
This revision was not accepted when it landed; it landed in state "Needs 
Review".

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D7810?vs=19085=19110

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

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

AFFECTED FILES
  contrib/packaging/docker/ubuntu.template

CHANGE DETAILS

diff --git a/contrib/packaging/docker/ubuntu.template 
b/contrib/packaging/docker/ubuntu.template
--- a/contrib/packaging/docker/ubuntu.template
+++ b/contrib/packaging/docker/ubuntu.template
@@ -10,7 +10,8 @@
   dh-python \
   less \
   python \
-  python-all-dev \
-  python-docutils \
+  python3-all \
+  python3-all-dev \
+  python3-docutils \
   unzip \
   zip



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


D7810: packaging: update Ubuntu docker build dependencies to Python 3

2020-01-08 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Changeset 7574ccd87200f02e 
 
updated the Debian docker builds to Python 3. In doing
  so, the Ubuntu docker-based builds broke, as the Dockerfile does not
  include the new dependencies as specified in 
`contrib/packaging/debian/control`.
  
  This commit changes the dependencies in the Ubuntu Dockerfile template
  to their Python 3 equivalents, fixing `make docker-ubuntu-bionic`.

REPOSITORY
  rHG Mercurial

BRANCH
  default

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

AFFECTED FILES
  contrib/packaging/docker/ubuntu.template

CHANGE DETAILS

diff --git a/contrib/packaging/docker/ubuntu.template 
b/contrib/packaging/docker/ubuntu.template
--- a/contrib/packaging/docker/ubuntu.template
+++ b/contrib/packaging/docker/ubuntu.template
@@ -10,7 +10,8 @@
   dh-python \
   less \
   python \
-  python-all-dev \
-  python-docutils \
+  python3-all \
+  python3-all-dev \
+  python3-docutils \
   unzip \
   zip



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


D6840: hgweb: add a `message` attribute to `hgweb.common.ErrorResponse`

2019-09-10 Thread sheehan (Connor Sheehan)
sheehan added a comment.


  The error I mentioned looks like this:
  
Traceback (most recent call last):
  File 
"/var/hg/venv_hgweb/lib64/python3.6/site-packages/mercurial/hgweb/hgwebdir_mod.py",
 line 358, in run_wsgi
for r in self._runwsgi(req, res):
  File 
"/var/hg/venv_hgweb/lib64/python3.6/site-packages/mercurial/hgweb/hgwebdir_mod.py",
 line 463, in _runwsgi
res.setbodygen(tmpl.generate('error', {'error': e.message or ''}))
AttributeError: 'ErrorResponse' object has no attribute 'message'

REPOSITORY
  rHG Mercurial

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

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

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


D6840: hgweb: add a `message` attribute to `hgweb.common.ErrorResponse`

2019-09-10 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This fixes a Python 3 bug where hgweb assumes an Exception
  subclass will have a `.message` attribute after running
  `Exception.__init__`.[1] The Python 3 way to get this info would
  be `e.args[0]`, but adding a new named attribute is more
  ergonomic in my view.
  
  [1] 
https://www.mercurial-scm.org/repo/hg-committed/file/6ccf539aec71/mercurial/hgweb/hgwebdir_mod.py#l459

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/hgweb/common.py

CHANGE DETAILS

diff --git a/mercurial/hgweb/common.py b/mercurial/hgweb/common.py
--- a/mercurial/hgweb/common.py
+++ b/mercurial/hgweb/common.py
@@ -106,6 +106,7 @@
 if headers is None:
 headers = []
 self.headers = headers
+self.message = message
 
 class continuereader(object):
 """File object wrapper to handle HTTP 100-continue.



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


D6832: highlight: fix encoding issues to enable Py3 compatibility

2019-09-09 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a reviewer: pulkit.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This commit fixes various encoding issues with the `highlight` extension
  to enable compatibility with Python 3. Python `.encode()` and `.decode()`
  requires the target encoding to be passed as a `str`, so the value of
  `mercurial.encoding.encoding` must be converted before passing to the
  function. Pygments also assumes the `str` type for values it works with,
  so we must perform conversions before and after receiving values from its
  APIs.
  
  After applying this patch, `test-highlight.t` passes under Python 3. We
  add it to `python3-whitelist` as well.
  
  Tested with Pygments 2.4.2.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  contrib/python3-whitelist
  hgext/highlight/__init__.py
  hgext/highlight/highlight.py

CHANGE DETAILS

diff --git a/hgext/highlight/highlight.py b/hgext/highlight/highlight.py
--- a/hgext/highlight/highlight.py
+++ b/hgext/highlight/highlight.py
@@ -15,6 +15,7 @@
 
 from mercurial import (
 encoding,
+pycompat,
 )
 
 from mercurial.utils import (
@@ -61,11 +62,12 @@
 
 # Pygments is best used with Unicode strings:
 # 
-text = text.decode(encoding.encoding, 'replace')
+text = text.decode(pycompat.sysstr(encoding.encoding), 'replace')
 
 # To get multi-line strings right, we can't format line-by-line
 try:
-lexer = guess_lexer_for_filename(fctx.path(), text[:1024],
+path = pycompat.sysstr(fctx.path())
+lexer = guess_lexer_for_filename(path, text[:1024],
  stripnl=False)
 except (ClassNotFound, ValueError):
 # guess_lexer will return a lexer if *any* lexer matches. There is
@@ -84,10 +86,10 @@
 if isinstance(lexer, TextLexer):
 return
 
-formatter = HtmlFormatter(nowrap=True, style=style)
+formatter = HtmlFormatter(nowrap=True, style=pycompat.sysstr(style))
 
 colorized = highlight(text, lexer, formatter)
-coloriter = (s.encode(encoding.encoding, 'replace')
+coloriter = (s.encode(pycompat.sysstr(encoding.encoding), 'replace')
  for s in colorized.splitlines())
 
 tmpl._filters['colorize'] = lambda x: next(coloriter)
diff --git a/hgext/highlight/__init__.py b/hgext/highlight/__init__.py
--- a/hgext/highlight/__init__.py
+++ b/hgext/highlight/__init__.py
@@ -36,6 +36,7 @@
 
 from mercurial import (
 extensions,
+pycompat,
 )
 
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' 
for
@@ -79,11 +80,12 @@
 
 def generate_css(web):
 pg_style = web.config('web', 'pygments_style', 'colorful')
-fmter = highlight.HtmlFormatter(style=pg_style)
+fmter = highlight.HtmlFormatter(style=pycompat.sysstr(pg_style))
 web.res.headers['Content-Type'] = 'text/css'
+style_defs = fmter.get_style_defs(pycompat.sysstr(''))
 web.res.setbodybytes(''.join([
 '/* pygments_style = %s */\n\n' % pg_style,
-fmter.get_style_defs(''),
+pycompat.bytestr(style_defs),
 ]))
 return web.res.sendresponse()
 
diff --git a/contrib/python3-whitelist b/contrib/python3-whitelist
--- a/contrib/python3-whitelist
+++ b/contrib/python3-whitelist
@@ -296,6 +296,7 @@
 test-hgwebdir-paths.py
 test-hgwebdir.t
 test-hgwebdirsym.t
+test-highlight.t
 test-histedit-arguments.t
 test-histedit-base.t
 test-histedit-bookmark-motion.t



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


D6788: hgweb: fix websub regex flag syntax on Python 3

2019-09-09 Thread sheehan (Connor Sheehan)
sheehan updated this revision to Diff 16466.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D6788?vs=16391=16466

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

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

AFFECTED FILES
  mercurial/hgweb/webutil.py
  tests/test-websub.t

CHANGE DETAILS

diff --git a/tests/test-websub.t b/tests/test-websub.t
--- a/tests/test-websub.t
+++ b/tests/test-websub.t
@@ -11,16 +11,18 @@
   > 
   > [websub]
   > issues = s|Issue(\d+)|http://bts.example.org/issue\1;>Issue\1|
+  > tickets = s|ticket(\d+)|http://ticket.example.org/issue\1;>Ticket\1|i
   > 
   > [interhg]
   > # check that we maintain some interhg backwards compatibility...
   > # yes, 'x' is a weird delimiter...
   > markbugs = sxbugxbugx
+  > problems = sxPROBLEMxproblemxi
   > EOF
 
   $ touch foo
   $ hg add foo
-  $ hg commit -d '1 0' -m 'Issue123: fixed the bug!'
+  $ hg commit -d '1 0' -m 'Issue123: fixed the bug! Ticket456 and problem789 
too'
 
   $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E 
errors.log
   $ cat hg.pid >> $DAEMON_PIDS
@@ -28,7 +30,7 @@
 log
 
   $ get-with-headers.py localhost:$HGPORT "rev/tip" | grep bts
-  http://bts.example.org/issue123;>Issue123: fixed the bug!
+  http://bts.example.org/issue123;>Issue123: fixed the bug! http://ticket.example.org/issue456;>Ticket456 
and problem789 too
 errors
 
   $ cat errors.log
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -791,7 +791,7 @@
 flagin = match.group(3)
 flags = 0
 if flagin:
-for flag in flagin.upper():
+for flag in pycompat.sysstr(flagin.upper()):
 flags |= re.__dict__[flag]
 
 try:



To: sheehan, #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


D6788: hgweb: fix websub regex flag syntax on Python 3

2019-09-06 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The `websub` config section for hgweb is broken under Python 3
  when using regex flags syntax (ie the optional `i` in the example
  from `hg help config.websub`:
  
patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
  
  Flags are pulled out of the specified byte-string using a regular
  expression, and uppercased. The flags are then iterated over and
  passed to the `re` module using `re.__dict__[item]`, to get the
  object attribute of the same name from the `re` module. So on Python
  2 if the `il` flags are passed, this transition looks like:
  
`'il'` -> `'IL'` -> `'I'` -> `re.__dict__['I']` -> `re.I`
  
  However on Python 3, these are bytes objects. When we iterate over
  a bytes object in Python 3, instead of getting the individual characters
  in the string as string objects of length one, we get the integer \
  value corresponding to that byte. So the same transition looks like:
  
`b'il'` -> `b'IL'` -> `73` -> `re.__dict__[73]` -> `KeyError`
  
  This commit fixes the type mismatch by decoding the bytes to an
  ascii string before iterating over each element to pass to `re`.
  The transition will now look like:
  
`b'il'` -> `u'IL'` -> `u'I'` -> `re.__dict__[u'I']` -> `re.I`
  
  In addition we expand `test-websub.t` to cover the regex flag case
  (for both the `websub` section and `interhg`).

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/hgweb/webutil.py
  tests/test-websub.t

CHANGE DETAILS

diff --git a/tests/test-websub.t b/tests/test-websub.t
--- a/tests/test-websub.t
+++ b/tests/test-websub.t
@@ -11,16 +11,18 @@
   > 
   > [websub]
   > issues = s|Issue(\d+)|http://bts.example.org/issue\1;>Issue\1|
+  > tickets = s|ticket(\d+)|http://ticket.example.org/issue\1;>Ticket\1|i
   > 
   > [interhg]
   > # check that we maintain some interhg backwards compatibility...
   > # yes, 'x' is a weird delimiter...
   > markbugs = sxbugxbugx
+  > problems = sxPROBLEMxproblemxi
   > EOF
 
   $ touch foo
   $ hg add foo
-  $ hg commit -d '1 0' -m 'Issue123: fixed the bug!'
+  $ hg commit -d '1 0' -m 'Issue123: fixed the bug! Ticket456 and problem789 
too'
 
   $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E 
errors.log
   $ cat hg.pid >> $DAEMON_PIDS
@@ -28,7 +30,7 @@
 log
 
   $ get-with-headers.py localhost:$HGPORT "rev/tip" | grep bts
-  http://bts.example.org/issue123;>Issue123: fixed the bug!
+  http://bts.example.org/issue123;>Issue123: fixed the bug! http://ticket.example.org/issue456;>Ticket456 
and problem789 too
 errors
 
   $ cat errors.log
diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
--- a/mercurial/hgweb/webutil.py
+++ b/mercurial/hgweb/webutil.py
@@ -791,7 +791,7 @@
 flagin = match.group(3)
 flags = 0
 if flagin:
-for flag in flagin.upper():
+for flag in flagin.upper().decode('ascii'):
 flags |= re.__dict__[flag]
 
 try:



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


D5194: wireprotov2: add an extension to cache wireproto v2 responses in S3

2018-11-02 Thread sheehan (Connor Sheehan)
sheehan abandoned this revision.
sheehan added a comment.


  > Either way, we'll be deploying this to Mozilla's hg servers in the next few 
months and testing it out. Perhaps after it's been in production for some time 
we will have a stronger case for inclusion in core. :)
  
  Going to deploy and maintain this at Mozilla for the time being and consider 
moving into core at a later time.

REPOSITORY
  rHG Mercurial

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

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


D5194: wireprotov2: add an extension to cache wireproto v2 responses in S3

2018-10-30 Thread sheehan (Connor Sheehan)
sheehan added a comment.


  In https://phab.mercurial-scm.org/D5194#77606, @martinvonz wrote:
  
  > Is this useful enough to others that it should live in the hg core repo? It 
doesn't seem like it to me, but maybe I'm wrong.
  
  
  My thought process was that since the new wire protocol supports caching 
command responses but does not actually provide any cache implementations, 
including some optional OOB support for something as common as S3 would be 
useful for anyone considering use of that feature.
  
  Maybe that's not enough reason to justify an extension in the core repo, I'm 
not certain. Either way, we'll be deploying this to Mozilla's hg servers in the 
next few months and testing it out. Perhaps after it's been in production for 
some time we will have a stronger case for inclusion in core. :)

REPOSITORY
  rHG Mercurial

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

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


D5194: wireprotov2: add an extension to cache wireproto v2 responses in S3

2018-10-26 Thread sheehan (Connor Sheehan)
sheehan added a subscriber: indygreg.
sheehan added a comment.


  Throwing this up for review now, but there are a few things that could be 
done to improve this. A cache expiration policy might be useful, but is 
difficult to test with the S3 bucket expiration rules. It may also be desirable 
to be able to specify more than one S3 bucket/region/account in the future.
  
  @indygreg will have more thoughts when he returns, I'm sure. :)

INLINE COMMENTS

> s3wireprotocache.py:185
> +def adjustcachekeystate(self, state):
> +if self.s3_endpoint_url:  # testing backdoor
> +del state[b'repo']

This is needed for determinism in testing, but there is likely a better way to 
avoid it that checking for an alternative endpoint url.

REPOSITORY
  rHG Mercurial

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

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


D5194: wireprotov2: add an extension to cache wireproto v2 responses in S3

2018-10-26 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  With wireprotocol version two introducing command response caching
  and enabling content redirect responses, it is possible to store
  response objects in an arbitrary blob store and send clients to
  the store to retrieve large responses. This commit adds an extension
  which implements such wire protocol caching in Amazon S3.
  
  Servers add their AWS access key and key ID to an hgrc config,
  and specify the name of the S3 bucket which holds the objects.
  When a cache lookup request comes in, the cacher sends a HEAD
  request to S3 which will return a 404 if the object does not
  exist (ie a cache miss). If the request is a cache hit, a presigned
  url for the object is generated and used to issue a content
  redirect response which is sent to the client. If the response
  indicates a cache miss, the response is generated by the server
  and buffered in the cache until `onfinished` is called. During
  `onfinished`, we calculate the size of the response and can
  optionally avoid caching if the response is below a configured
  minimum threshold. Otherwise we insert the object into the
  cache bucket using the `put_object` API.
  
  To test this extension, we require the `moto` mock AWS library.
  Specifically, we use the "standalone server" functionality,
  which creates a Flask application that imitates S3. A new hghave
  predicate is added to check for this functionality before
  testing.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/s3wireprotocache.py
  tests/hghave.py
  tests/test-help.t
  tests/test-s3wireprotocache.t

CHANGE DETAILS

diff --git a/tests/test-s3wireprotocache.t b/tests/test-s3wireprotocache.t
new file mode 100644
--- /dev/null
+++ b/tests/test-s3wireprotocache.t
@@ -0,0 +1,219 @@
+#require motoserver
+
+  $ . $TESTDIR/wireprotohelpers.sh
+
+Set up the mock S3 server, create a bucket
+
+  $ moto_server -p 15467 s3 >> mocks3.log 2>&1 &
+  $ MOTO_PID=$!
+  >>> import boto3
+  >>> s3 = boto3.client('s3',
+  ... aws_access_key_id='dummyaccessid',
+  ... aws_secret_access_key='dummysecretkey',
+  ... endpoint_url='http://localhost:15467/')
+  >>> _ = s3.create_bucket(
+  ... ACL='public-read',
+  ... Bucket='testbucket')
+
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > blackbox =
+  > [blackbox]
+  > track = s3wireprotocache
+  > EOF
+  $ hg init server
+  $ enablehttpv2 server
+  $ cd server
+  $ cat >> .hg/hgrc << EOF
+  > [extensions]
+  > s3wireprotocache =
+  > [s3wireprotocache]
+  > access_key_id = dummyaccessid
+  > secret_access_key = dummysecretkey
+  > bucket = testbucket
+  > redirecttargets = http://localhost:15467/
+  > endpoint_url = http://localhost:15467/
+  > EOF
+
+  $ echo a0 > a
+  $ echo b0 > b
+  $ hg -q commit -A -m 'commit 0'
+  $ echo a1 > a
+  $ hg commit -m 'commit 1'
+  $ echo b1 > b
+  $ hg commit -m 'commit 2'
+  $ echo a2 > a
+  $ echo b2 > b
+  $ hg commit -m 'commit 3'
+
+  $ hg log -G -T '{rev}:{node} {desc}'
+  @  3:50590a86f3ff5d1e9a1624a7a6957884565cc8e8 commit 3
+  |
+  o  2:4d01eda50c6ac5f7e89cbe1880143a32f559c302 commit 2
+  |
+  o  1:4432d83626e8a98655f062ec1f2a43b07f7fbbb0 commit 1
+  |
+  o  0:3390ef850073fbc2f0dfff2244342c8e9229013a commit 0
+  
+  $ hg --debug debugindex -m
+ rev linkrev nodeid   p1   
p2
+   0   0 992f4779029a3df8d0666d00bb924f69634e2641 
 

+   1   1 a988fb43583e871d1ed5750ee074c6d840bbbfc8 
992f4779029a3df8d0666d00bb924f69634e2641 

+   2   2 a8853dafacfca6fc807055a660d8b835141a3bb4 
a988fb43583e871d1ed5750ee074c6d840bbbfc8 

+   3   3 3fe11dfbb13645782b0addafbe75a87c210ffddc 
a8853dafacfca6fc807055a660d8b835141a3bb4 

+
+  $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log
+  $ HGSERVEPID=`cat hg.pid`
+
+  $ cat hg.pid > $DAEMON_PIDS
+  $ printf "\n" >> $DAEMON_PIDS
+  $ echo $MOTO_PID >> $DAEMON_PIDS
+
+Performing the same request twice should produce the same result,
+with the first request caching the response in S3 and the second
+result coming as an S3 redirect
+
+  $ sendhttpv2peer << EOF
+  > command manifestdata
+  > nodes 
eval:[b'\x99\x2f\x47\x79\x02\x9a\x3d\xf8\xd0\x66\x6d\x00\xbb\x92\x4f\x69\x63\x4e\x26\x41']
+  > tree eval:b''
+  > fields eval:[b'parents']
+  > EOF
+  creating http peer for wire protocol version 2
+  sending manifestdata command
+  response: gen[
+{
+  b'totalitems': 1
+},
+{
+  b'node': b'\x99/Gy\x02\x9a=\xf8\xd0fm\x00\xbb\x92OicN',
+  b'parents': [
+
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
+

D5090: wireproto: fix incorrect function name in docstring

2018-10-14 Thread sheehan (Connor Sheehan)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG4821affc154f: wireproto: fix incorrect function name in 
docstring (authored by sheehan, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D5090?vs=12099=12108

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

AFFECTED FILES
  mercurial/repository.py

CHANGE DETAILS

diff --git a/mercurial/repository.py b/mercurial/repository.py
--- a/mercurial/repository.py
+++ b/mercurial/repository.py
@@ -1713,7 +1713,7 @@
 8. The command function is invoked.
 9. ``onobject()`` is called for each object emitted by the command
function.
-10. After the final object is seen, ``onoutputfinished()`` is called.
+10. After the final object is seen, ``onfinished()`` is called.
 11. ``__exit__`` is called to signal the end of use of the instance.
 
 Cache *key* derivation can be influenced by the instance.
@@ -1748,7 +1748,7 @@
 
 Implementations could also choose to not emit objects - instead locally
 buffering objects or their encoded representation. They could then emit
-a single "coalesced" object when ``onoutputfinished()`` is called. In
+a single "coalesced" object when ``onfinished()`` is called. In
 this way, the implementation would function as a filtering layer of
 sorts.
 



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


D5090: wireproto: fix incorrect function name in docstring

2018-10-14 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The docstring for `iwireprotocolcommandcacher` references
  an `onoutputfinished` method. The actual name of the function
  is `onfinished`.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/repository.py

CHANGE DETAILS

diff --git a/mercurial/repository.py b/mercurial/repository.py
--- a/mercurial/repository.py
+++ b/mercurial/repository.py
@@ -1713,7 +1713,7 @@
 8. The command function is invoked.
 9. ``onobject()`` is called for each object emitted by the command
function.
-10. After the final object is seen, ``onoutputfinished()`` is called.
+10. After the final object is seen, ``onfinished()`` is called.
 11. ``__exit__`` is called to signal the end of use of the instance.
 
 Cache *key* derivation can be influenced by the instance.
@@ -1748,7 +1748,7 @@
 
 Implementations could also choose to not emit objects - instead locally
 buffering objects or their encoded representation. They could then emit
-a single "coalesced" object when ``onoutputfinished()`` is called. In
+a single "coalesced" object when ``onfinished()`` is called. In
 this way, the implementation would function as a filtering layer of
 sorts.
 



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


D4283: webcommands: fix `@webcommand` decorator

2018-08-20 Thread sheehan (Connor Sheehan)
sheehan planned changes to this revision.
sheehan added a comment.


  In https://phab.mercurial-scm.org/D4283#65988, @indygreg wrote:
  
  > This seems like a strict improvement.
  >
  > But the proper way to register web commands from extensions would be to go 
through the `registrar` API and have the extension loader look for a well-named 
symbol in each extension module that is loaded and hgweb would consult the 
registrar for active commands. In theory, this will only activate web commands 
on repositories that have an extension loaded.
  >
  > Search for `templatefilter` in `mercurial/extensions.py` for an example of 
how all this works.
  >
  > Would you be willing to try that approach? It doesn't have to be perfect. 
But we are moving to the registrar for extensions wishing to install 
well-defined things. And web commands fit that bill.
  
  
  Seems reasonable to me! I took a look through the code and I think I 
understand what is going on. I'll update this patch with something that uses 
the registrar API.

REPOSITORY
  rHG Mercurial

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

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


D4283: webcommands: fix `@webcommand` decorator

2018-08-15 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This commit fixes the `@webcommand` decorator used to define
  webcommands. Although webcommands are currently using this
  decorator, it does not behave as intended. Using the decorator
  should record the name of the decorator in a `commands` dict,
  and when a request arrives to hgweb the correct function to
  call should be resolved from that dict.
  
  In the current implementation the command is added to the
  commands dict, but when hgweb attempts to resolve the function
  while processing a request, it instead looks for an attribute
  with the same name attached to the `webcommands` module. To
  summarize, a command 'commandname' should be resolved from
  
`mercurial.hgweb.webcommands.commands['commandname']`
  
  but is instead being resolved from
  
`mercurial.hgweb.webcommands.commandname`
  
  The decorator appears to be working on the core webcommands
  (such as log, rev, file) however this is because those
  commands are defined with the same name in the underlying
  Python function.
  
  This commit changes hgweb_mod.py to resolve the function used
  from webcommands to come from the `commands` dict in the
  `webcommands` module. Due to the change in how webcommands
  are resolved, a `wrapwebcommand` function is also added, which
  wraps a webcommand by applying the wrapper as a partial function
  and overwrites the existing function in the `commands` dict.
  
  Wrapped webcommands in shipped extensions and hgweb tests
  are changed to use the fixed decorator and `wrapwebcommand`
  function.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/highlight/__init__.py
  hgext/keyword.py
  hgext/largefiles/uisetup.py
  mercurial/hgweb/hgweb_mod.py
  mercurial/hgweb/webcommands.py
  tests/hgweberror.py

CHANGE DETAILS

diff --git a/tests/hgweberror.py b/tests/hgweberror.py
--- a/tests/hgweberror.py
+++ b/tests/hgweberror.py
@@ -6,6 +6,7 @@
 webcommands,
 )
 
+@webcommands.webcommand('raiseerror')
 def raiseerror(web):
 '''Dummy web command that raises an uncaught Exception.'''
 
@@ -18,7 +19,3 @@
 web.res.getbodyfile().write(b'partial content\n')
 
 raise AttributeError('I am an uncaught error!')
-
-def extsetup(ui):
-setattr(webcommands, 'raiseerror', raiseerror)
-webcommands.__all__.append('raiseerror')
diff --git a/mercurial/hgweb/webcommands.py b/mercurial/hgweb/webcommands.py
--- a/mercurial/hgweb/webcommands.py
+++ b/mercurial/hgweb/webcommands.py
@@ -8,6 +8,7 @@
 from __future__ import absolute_import
 
 import copy
+import functools
 import mimetypes
 import os
 import re
@@ -47,7 +48,6 @@
 webutil,
 )
 
-__all__ = []
 commands = {}
 
 class webcommand(object):
@@ -77,10 +77,34 @@
 self.name = name
 
 def __call__(self, func):
-__all__.append(self.name)
 commands[self.name] = func
 return func
 
+def wrapwebcommand(command, wrapper):
+"""Utility to wrap functions defined as webcommands
+
+Wrap the webcommand 'command' using the specified wrapper.
+The wrapper function should have the signature
+
+  wrapper(orig, web)
+
+where 'orig' is the webcommand to be wrapped, and 'web' is the
+requestcontext instance that will be passed to the webcommand
+at runtime."""
+
+if command not in commands:
+raise error.ProgrammingError('no webcommand named %s' % command)
+
+if not callable(wrapper):
+raise error.ProgrammingError('wrapper must be a callable')
+
+# Create the new webcommand
+orig = commands[command]
+newfunc = functools.partial(wrapper, orig)
+
+# Overwrite the old webcommand with the new one
+commands[command] = newfunc
+
 @webcommand('log')
 def log(web):
 """
diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -354,7 +354,7 @@
 cmd = cmd[style + 1:]
 
 # avoid accepting e.g. style parameter as command
-if util.safehasattr(webcommands, cmd):
+if cmd in webcommands.commands:
 req.qsparams['cmd'] = cmd
 
 if cmd == 'static':
@@ -416,15 +416,15 @@
 
 res.headers['ETag'] = tag
 
-if cmd not in webcommands.__all__:
+if cmd not in webcommands.commands:
 msg = 'no such method: %s' % cmd
 raise ErrorResponse(HTTP_BAD_REQUEST, msg)
 else:
 # Set some globals appropriate for web handlers. Commands can
 # override easily enough.
 res.status = '200 Script output follows'
 res.headers['Content-Type'] = ctype
-return getattr(webcommands, cmd)(rctx)
+return webcommands.commands[cmd](rctx)
 
 except 

D3001: templatefuncs: remove redundant "or author" from mailmap return statement

2018-03-31 Thread sheehan (Connor Sheehan)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG3685a79ea51b: templatefuncs: remove redundant or 
author from mailmap return statement (authored by sheehan, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3001?vs=7477=7481

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

AFFECTED FILES
  mercurial/templatefuncs.py

CHANGE DETAILS

diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -184,7 +184,7 @@
 data = repo.wvfs.tryread('.mailmap')
 cache['mailmap'] = stringutil.parsemailmap(data)
 
-return stringutil.mapname(cache['mailmap'], author) or author
+return stringutil.mapname(cache['mailmap'], author)
 
 @templatefunc('pad(text, width[, fillchar=\' \'[, left=False]])',
   argspec='text width fillchar left')



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


D3002: stringutil: rename local email/names variables to their plural forms

2018-03-31 Thread sheehan (Connor Sheehan)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG54b896f195d1: stringutil: rename local email/names 
variables to their plural forms (authored by sheehan, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D3002?vs=7478=7482#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3002?vs=7478=7482

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -202,9 +202,9 @@
 if line.lstrip().startswith('#') or any(c not in line for c in '<>@'):
 continue
 
-# name, email hold the parsed emails and names for each line
+# names, emails hold the parsed emails and names for each line
 # name_builder holds the words in a persons name
-name, email = [], []
+names, emails = [], []
 namebuilder = []
 
 for element in line.split():
@@ -215,29 +215,29 @@
 elif element.startswith('<') and element.endswith('>'):
 # We have found an email.
 # Parse it, and finalize any names from earlier
-email.append(element[1:-1])  # Slice off the "<>"
+emails.append(element[1:-1])  # Slice off the "<>"
 
 if namebuilder:
-name.append(' '.join(namebuilder))
+names.append(' '.join(namebuilder))
 namebuilder = []
 
 # Break if we have found a second email, any other
 # data does not fit the spec for .mailmap
-if len(email) > 1:
+if len(emails) > 1:
 break
 
 else:
 # We have found another word in the committers name
 namebuilder.append(element)
 
 mailmapkey = mailmapping(
-email=email[-1],
-name=name[-1] if len(name) == 2 else None,
+email=emails[-1],
+name=names[-1] if len(names) == 2 else None,
 )
 
 mailmap[mailmapkey] = mailmapping(
-email=email[0],
-name=name[0] if name else None,
+email=emails[0],
+name=names[0] if names else None,
 )
 
 return mailmap



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


D3004: stringutil: edit comment to reflect actual data type name

2018-03-31 Thread sheehan (Connor Sheehan)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG2ed180117f76: stringutil: edit comment to reflect actual 
data type name (authored by sheehan, committed by ).

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3004?vs=7480=7483

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -300,7 +300,7 @@
 if not isauthorwellformed(author) or not mailmap:
 return author
 
-# Turn the user name into a mailmaptup
+# Turn the user name into a mailmapping
 commit = mailmapping(name=person(author), email=email(author))
 
 try:



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


D3003: stringutil: improve check for failed mailmap line parsing

2018-03-31 Thread sheehan (Connor Sheehan)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG0e7550b0964c: stringutil: improve check for failed mailmap 
line parsing (authored by sheehan, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D3003?vs=7479=7484#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D3003?vs=7479=7484

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -166,6 +166,30 @@
 email = attr.ib()
 name = attr.ib(default=None)
 
+def _ismailmaplineinvalid(names, emails):
+'''Returns True if the parsed names and emails
+in a mailmap entry are invalid.
+
+>>> # No names or emails fails
+>>> names, emails = [], []
+>>> _ismailmaplineinvalid(names, emails)
+True
+>>> # Only one email fails
+>>> emails = [b'em...@email.com']
+>>> _ismailmaplineinvalid(names, emails)
+True
+>>> # One email and one name passes
+>>> names = [b'Test Name']
+>>> _ismailmaplineinvalid(names, emails)
+False
+>>> # No names but two emails passes
+>>> names = []
+>>> emails = [b'pro...@email.com', b'com...@email.com']
+>>> _ismailmaplineinvalid(names, emails)
+False
+'''
+return not emails or not names and len(emails) < 2
+
 def parsemailmap(mailmapcontent):
 """Parses data in the .mailmap format
 
@@ -199,7 +223,7 @@
 
 # Don't bother checking the line if it is a comment or
 # is an improperly formed author field
-if line.lstrip().startswith('#') or any(c not in line for c in '<>@'):
+if line.lstrip().startswith('#'):
 continue
 
 # names, emails hold the parsed emails and names for each line
@@ -230,6 +254,12 @@
 # We have found another word in the committers name
 namebuilder.append(element)
 
+# Check to see if we have parsed the line into a valid form
+# We require at least one email, and either at least one
+# name or a second email
+if _ismailmaplineinvalid(names, emails):
+continue
+
 mailmapkey = mailmapping(
 email=emails[-1],
 name=names[-1] if len(names) == 2 else None,



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


D3003: stringutil: improve check for failed mailmap line parsing

2018-03-31 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The existing check for a bad mailmap file entry fails with inputs
  like b'>@<'. This commit adds a function to check if a sufficient
  amount of information has been parsed from a mailmap file entry.
  
  At minimum, one email must be found (assumed to be the commit email).
  If email is not empty and no names are found, then there must be
  two emails. If there are at least one email and name, the mapping
  is valid.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -166,6 +166,30 @@
 email = attr.ib()
 name = attr.ib(default=None)
 
+def ismailmaplineinvalid(names, emails):
+'''Returns True if the parsed names and emails
+in a mailmap entry are invalid.
+
+>>> # No names or emails fails
+>>> names, emails = [], []
+>>> ismailmaplineinvalid(names, emails)
+True
+>>> # Only one email fails
+>>> emails = [b'em...@email.com']
+>>> ismailmaplineinvalid(names, emails)
+True
+>>> # One email and one name passes
+>>> names = [b'Test Name']
+>>> ismailmaplineinvalid(names, emails)
+False
+>>> # No names but two emails passes
+>>> names = []
+>>> emails = [b'pro...@email.com', b'com...@email.com']
+>>> ismailmaplineinvalid(names, emails)
+False
+'''
+return not emails or not names and len(emails) < 2
+
 def parsemailmap(mailmapcontent):
 """Parses data in the .mailmap format
 
@@ -199,7 +223,7 @@
 
 # Don't bother checking the line if it is a comment or
 # is an improperly formed author field
-if line.lstrip().startswith('#') or any(c not in line for c in '<>@'):
+if line.lstrip().startswith('#'):
 continue
 
 # name, email hold the parsed emails and names for each line
@@ -230,6 +254,12 @@
 # We have found another word in the committers name
 namebuilder.append(element)
 
+# Check to see if we have parsed the line into a valid form
+# We require at least one email, and either at least one
+# name or a second email
+if ismailmaplineinvalid(names, emails):
+continue
+
 mailmapkey = mailmapping(
 email=emails[-1],
 name=names[-1] if len(names) == 2 else None,



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


D3002: stringutil: rename local email/names variables to their plural forms

2018-03-31 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  email and name variables are renamed to emails and names (respectively).
  This is because the email variable name shadows the email function
  within the stringutil module. Since we are renaming email, we also rename
  name for consistency.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -204,7 +204,7 @@
 
 # name, email hold the parsed emails and names for each line
 # name_builder holds the words in a persons name
-name, email = [], []
+names, emails = [], []
 namebuilder = []
 
 for element in line.split():
@@ -215,29 +215,29 @@
 elif element.startswith('<') and element.endswith('>'):
 # We have found an email.
 # Parse it, and finalize any names from earlier
-email.append(element[1:-1])  # Slice off the "<>"
+emails.append(element[1:-1])  # Slice off the "<>"
 
 if namebuilder:
-name.append(' '.join(namebuilder))
+names.append(' '.join(namebuilder))
 namebuilder = []
 
 # Break if we have found a second email, any other
 # data does not fit the spec for .mailmap
-if len(email) > 1:
+if len(emails) > 1:
 break
 
 else:
 # We have found another word in the committers name
 namebuilder.append(element)
 
 mailmapkey = mailmapping(
-email=email[-1],
-name=name[-1] if len(name) == 2 else None,
+email=emails[-1],
+name=names[-1] if len(names) == 2 else None,
 )
 
 mailmap[mailmapkey] = mailmapping(
-email=email[0],
-name=name[0] if name else None,
+email=emails[0],
+name=names[0] if names else None,
 )
 
 return mailmap



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


D3001: templatefuncs: remove redundant "or author" from mailmap return statement

2018-03-31 Thread sheehan (Connor Sheehan)
sheehan 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/D3001

AFFECTED FILES
  mercurial/templatefuncs.py

CHANGE DETAILS

diff --git a/mercurial/templatefuncs.py b/mercurial/templatefuncs.py
--- a/mercurial/templatefuncs.py
+++ b/mercurial/templatefuncs.py
@@ -185,7 +185,7 @@
 data = repo.wvfs.tryread('.mailmap')
 cache['mailmap'] = stringutil.parsemailmap(data)
 
-return stringutil.mapname(cache['mailmap'], author) or author
+return stringutil.mapname(cache['mailmap'], author)
 
 @templatefunc('pad(text, width[, fillchar=\' \'[, left=False]])',
   argspec='text width fillchar left')



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


D3004: stringutil: edit comment to reflect actual data type name

2018-03-31 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  In development the data type used to hold an email/name pair
  was called a "mailmaptup" since it was implemented as a
  namedtuple. The implementation has since been changed to use
  an @attr.s decorated class named mailmapping. This commit
  changes a comment to reflect this change.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -300,7 +300,7 @@
 if not isauthorwellformed(author) or not mailmap:
 return author
 
-# Turn the user name into a mailmaptup
+# Turn the user name into a mailmapping
 commit = mailmapping(name=person(author), email=email(author))
 
 try:



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


D2903: utils: add isauthorwellformed function

2018-03-31 Thread sheehan (Connor Sheehan)
sheehan abandoned this revision.
sheehan added a comment.


  Abandoning, this was landed as another differential.

REPOSITORY
  rHG Mercurial

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

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


D2904: templatefuncs: add mailmap template function

2018-03-30 Thread sheehan (Connor Sheehan)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHG2a2ce93e12f4: templatefuncs: add mailmap template function 
(authored by sheehan, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D2904?vs=7381=7453#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2904?vs=7381=7453

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

AFFECTED FILES
  mercurial/templatefuncs.py
  mercurial/utils/stringutil.py
  tests/test-mailmap.t

CHANGE DETAILS

diff --git a/tests/test-mailmap.t b/tests/test-mailmap.t
new file mode 100644
--- /dev/null
+++ b/tests/test-mailmap.t
@@ -0,0 +1,67 @@
+Create a repo and add some commits
+
+  $ hg init mm
+  $ cd mm
+  $ echo "Test content" > testfile1
+  $ hg add testfile1
+  $ hg commit -m "First commit" -u "Proper "
+  $ echo "Test content 2" > testfile2
+  $ hg add testfile2
+  $ hg commit -m "Second commit" -u "Commit Name 2 "
+  $ echo "Test content 3" > testfile3
+  $ hg add testfile3
+  $ hg commit -m "Third commit" -u "Commit Name 3 "
+  $ echo "Test content 4" > testfile4
+  $ hg add testfile4
+  $ hg commit -m "Fourth commit" -u "Commit Name 4 "
+
+Add a .mailmap file with each possible entry type plus comments
+  $ cat > .mailmap << EOF
+  > # Comment shouldn't break anything
+  >   # Should update email only
+  > Proper Name 2  # Should update name only
+  > Proper Name 3   # Should update name, email due 
to email
+  > Proper Name 4  Commit Name 4  # Should update 
name, email due to name, email
+  > EOF
+  $ hg add .mailmap
+  $ hg commit -m "Add mailmap file" -u "Testuser "
+
+Output of commits should be normal without filter
+  $ hg log -T "{author}\n" -r "all()"
+  Proper 
+  Commit Name 2 
+  Commit Name 3 
+  Commit Name 4 
+  Testuser 
+
+Output of commits with filter shows their mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+Add new mailmap entry for testuser
+  $ cat >> .mailmap << EOF
+  >  
+  > EOF
+
+Output of commits with filter shows their updated mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+A commit with improperly formatted user field should not break the filter
+  $ echo "some more test content" > testfile1
+  $ hg commit -m "Commit with improper user field" -u "Improper user"
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+  Improper user
diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -14,6 +14,7 @@
 import textwrap
 
 from ..i18n import _
+from ..thirdparty import attr
 
 from .. import (
 encoding,
@@ -158,6 +159,136 @@
 f = author.find('@')
 return author[:f].replace('.', ' ')
 
+@attr.s(hash=True)
+class mailmapping(object):
+'''Represents a username/email key or value in
+a mailmap file'''
+email = attr.ib()
+name = attr.ib(default=None)
+
+def parsemailmap(mailmapcontent):
+"""Parses data in the .mailmap format
+
+>>> mmdata = b"\\n".join([
+... b'# Comment',
+... b'Name ',
+... b' ',
+... b'Name  ',
+... b'Name  Commit ',
+... ])
+>>> mm = parsemailmap(mmdata)
+>>> for key in sorted(mm.keys()):
+... print(key)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name='Commit')
+>>> for val in sorted(mm.values()):
+... print(val)
+mailmapping(email='comm...@email.xx', name='Name')
+mailmapping(email='n...@email.xx', name=None)
+mailmapping(email='pro...@email.xx', name='Name')
+mailmapping(email='pro...@email.xx', name='Name')
+"""
+mailmap = {}
+
+if mailmapcontent is None:
+return mailmap
+
+for line in mailmapcontent.splitlines():
+
+# Don't bother checking the line if it is a comment or
+# is an improperly formed author field
+if line.lstrip().startswith('#') or any(c not in line for c in '<>@'):
+continue
+
+# name, email hold the parsed emails and names for each line
+# name_builder holds 

D2904: templatefuncs: add mailmap template function

2018-03-30 Thread sheehan (Connor Sheehan)
sheehan updated this revision to Diff 7381.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2904?vs=7361=7381

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

AFFECTED FILES
  mercurial/templatefuncs.py
  mercurial/utils/stringutil.py
  tests/test-mailmap.t

CHANGE DETAILS

diff --git a/tests/test-mailmap.t b/tests/test-mailmap.t
new file mode 100644
--- /dev/null
+++ b/tests/test-mailmap.t
@@ -0,0 +1,67 @@
+Create a repo and add some commits
+
+  $ hg init mm
+  $ cd mm
+  $ echo "Test content" > testfile1
+  $ hg add testfile1
+  $ hg commit -m "First commit" -u "Proper "
+  $ echo "Test content 2" > testfile2
+  $ hg add testfile2
+  $ hg commit -m "Second commit" -u "Commit Name 2 "
+  $ echo "Test content 3" > testfile3
+  $ hg add testfile3
+  $ hg commit -m "Third commit" -u "Commit Name 3 "
+  $ echo "Test content 4" > testfile4
+  $ hg add testfile4
+  $ hg commit -m "Fourth commit" -u "Commit Name 4 "
+
+Add a .mailmap file with each possible entry type plus comments
+  $ cat > .mailmap << EOF
+  > # Comment shouldn't break anything
+  >   # Should update email only
+  > Proper Name 2  # Should update name only
+  > Proper Name 3   # Should update name, email due 
to email
+  > Proper Name 4  Commit Name 4  # Should update 
name, email due to name, email
+  > EOF
+  $ hg add .mailmap
+  $ hg commit -m "Add mailmap file" -u "Testuser "
+
+Output of commits should be normal without filter
+  $ hg log -T "{author}\n" -r "all()"
+  Proper 
+  Commit Name 2 
+  Commit Name 3 
+  Commit Name 4 
+  Testuser 
+
+Output of commits with filter shows their mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+Add new mailmap entry for testuser
+  $ cat >> .mailmap << EOF
+  >  
+  > EOF
+
+Output of commits with filter shows their updated mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+A commit with improperly formatted user field should not break the filter
+  $ echo "some more test content" > testfile1
+  $ hg commit -m "Commit with improper user field" -u "Improper user"
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+  Improper user
diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -14,6 +14,7 @@
 import textwrap
 
 from ..i18n import _
+from ..thirdparty import attr
 
 from .. import (
 encoding,
@@ -335,3 +336,133 @@
 return author[:f].strip(' "').replace('\\"', '"')
 f = author.find('@')
 return author[:f].replace('.', ' ')
+
+@attr.s(hash=True)
+class mailmapping(object):
+'''Represents a username/email key or value in
+a mailmap file'''
+email = attr.ib()
+name = attr.ib(default=None)
+
+def parsemailmap(mailmapcontent):
+"""Parses data in the .mailmap format
+
+>>> mmdata = b"\\n".join([
+... b'# Comment',
+... b'Name ',
+... b' ',
+... b'Name  ',
+... b'Name  Commit ',
+... ])
+>>> mm = parsemailmap(mmdata)
+>>> for key in sorted(mm.keys()):
+... print(key)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name='Commit')
+>>> for val in sorted(mm.values()):
+... print(val)
+mailmapping(email='comm...@email.xx', name='Name')
+mailmapping(email='n...@email.xx', name=None)
+mailmapping(email='pro...@email.xx', name='Name')
+mailmapping(email='pro...@email.xx', name='Name')
+"""
+mailmap = {}
+
+if mailmapcontent is None:
+return mailmap
+
+for line in mailmapcontent.splitlines():
+
+# Don't bother checking the line if it is a comment or
+# is an improperly formed author field
+if line.lstrip().startswith('#') or any(c not in line for c in '<>@'):
+continue
+
+# name, email hold the parsed emails and names for each line
+# name_builder holds the words in a persons name
+name, email = [], []
+namebuilder = []
+
+for element in line.split():
+if element.startswith('#'):
+   

D2960: stringutil: move person function from templatefilters

2018-03-30 Thread sheehan (Connor Sheehan)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGfb7140f1d09d: stringutil: move person function from 
templatefilters (authored by sheehan, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D2960?vs=7360=7380#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2960?vs=7360=7380

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

AFFECTED FILES
  mercurial/templatefilters.py
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -131,6 +131,33 @@
 r = None
 return author[author.find('<') + 1:r]
 
+def person(author):
+"""Returns the name before an email address,
+interpreting it as per RFC 5322
+
+>>> person(b'foo@bar')
+'foo'
+>>> person(b'Foo Bar ')
+'Foo Bar'
+>>> person(b'"Foo Bar" ')
+'Foo Bar'
+>>> person(b'"Foo \"buz\" Bar" ')
+'Foo "buz" Bar'
+>>> # The following are invalid, but do exist in real-life
+...
+>>> person(b'Foo "buz" Bar ')
+'Foo "buz" Bar'
+>>> person(b'"Foo Bar ')
+'Foo Bar'
+"""
+if '@' not in author:
+return author
+f = author.find('<')
+if f != -1:
+return author[:f].strip(' "').replace('\\"', '"')
+f = author.find('@')
+return author[:f].replace('.', ' ')
+
 _correctauthorformat = remod.compile(br'^[^<]+\s\<[^<>]+@[^<>]+\>$')
 
 def isauthorwellformed(author):
diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py
--- a/mercurial/templatefilters.py
+++ b/mercurial/templatefilters.py
@@ -292,29 +292,8 @@
 def person(author):
 """Any text. Returns the name before an email address,
 interpreting it as per RFC 5322.
-
->>> person(b'foo@bar')
-'foo'
->>> person(b'Foo Bar ')
-'Foo Bar'
->>> person(b'"Foo Bar" ')
-'Foo Bar'
->>> person(b'"Foo \"buz\" Bar" ')
-'Foo "buz" Bar'
->>> # The following are invalid, but do exist in real-life
-...
->>> person(b'Foo "buz" Bar ')
-'Foo "buz" Bar'
->>> person(b'"Foo Bar ')
-'Foo Bar'
 """
-if '@' not in author:
-return author
-f = author.find('<')
-if f != -1:
-return author[:f].strip(' "').replace('\\"', '"')
-f = author.find('@')
-return author[:f].replace('.', ' ')
+return stringutil.person(author)
 
 @templatefilter('revescape')
 def revescape(text):



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


D2959: stringutil: add isauthorwellformed function

2018-03-30 Thread sheehan (Connor Sheehan)
This revision was automatically updated to reflect the committed changes.
Closed by commit rHGf8e1f48de118: stringutil: add isauthorwellformed function 
(authored by sheehan, committed by ).

CHANGED PRIOR TO COMMIT
  https://phab.mercurial-scm.org/D2959?vs=7359=7379#toc

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2959?vs=7359=7379

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -131,6 +131,29 @@
 r = None
 return author[author.find('<') + 1:r]
 
+_correctauthorformat = remod.compile(br'^[^<]+\s\<[^<>]+@[^<>]+\>$')
+
+def isauthorwellformed(author):
+'''Return True if the author field is well formed
+(ie "Contributor Name ")
+
+>>> isauthorwellformed(b'Good Author ')
+True
+>>> isauthorwellformed(b'Author ')
+True
+>>> isauthorwellformed(b'Bad Author')
+False
+>>> isauthorwellformed(b'Bad Author >> isauthorwellformed(b'Bad Author aut...@author.com')
+False
+>>> isauthorwellformed(b'')
+False
+>>> isauthorwellformed(b'Bad Author ')
+False
+'''
+return _correctauthorformat.match(author) is not None
+
 def ellipsis(text, maxlength=400):
 """Trim string to at most maxlength (default: 400) columns in display."""
 return encoding.trim(text, maxlength, ellipsis='...')



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


D2904: templatefuncs: add mailmap template function

2018-03-29 Thread sheehan (Connor Sheehan)
sheehan updated this revision to Diff 7361.
sheehan marked 3 inline comments as done.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2904?vs=7345=7361

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

AFFECTED FILES
  mercurial/templatefuncs.py
  mercurial/utils/stringutil.py
  tests/test-mailmap.t

CHANGE DETAILS

diff --git a/tests/test-mailmap.t b/tests/test-mailmap.t
new file mode 100644
--- /dev/null
+++ b/tests/test-mailmap.t
@@ -0,0 +1,67 @@
+Create a repo and add some commits
+
+  $ hg init mm
+  $ cd mm
+  $ echo "Test content" > testfile1
+  $ hg add testfile1
+  $ hg commit -m "First commit" -u "Proper "
+  $ echo "Test content 2" > testfile2
+  $ hg add testfile2
+  $ hg commit -m "Second commit" -u "Commit Name 2 "
+  $ echo "Test content 3" > testfile3
+  $ hg add testfile3
+  $ hg commit -m "Third commit" -u "Commit Name 3 "
+  $ echo "Test content 4" > testfile4
+  $ hg add testfile4
+  $ hg commit -m "Fourth commit" -u "Commit Name 4 "
+
+Add a .mailmap file with each possible entry type plus comments
+  $ cat > .mailmap << EOF
+  > # Comment shouldn't break anything
+  >   # Should update email only
+  > Proper Name 2  # Should update name only
+  > Proper Name 3   # Should update name, email due 
to email
+  > Proper Name 4  Commit Name 4  # Should update 
name, email due to name, email
+  > EOF
+  $ hg add .mailmap
+  $ hg commit -m "Add mailmap file" -u "Testuser "
+
+Output of commits should be normal without filter
+  $ hg log -T "{author}\n" -r "all()"
+  Proper 
+  Commit Name 2 
+  Commit Name 3 
+  Commit Name 4 
+  Testuser 
+
+Output of commits with filter shows their mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+Add new mailmap entry for testuser
+  $ cat >> .mailmap << EOF
+  >  
+  > EOF
+
+Output of commits with filter shows their updated mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+A commit with improperly formatted user field should not break the filter
+  $ echo "some more test content" > testfile1
+  $ hg commit -m "Commit with improper user field" -u "Improper user"
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+  Improper user
diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -14,6 +14,7 @@
 import textwrap
 
 from ..i18n import _
+from ..thirdparty import attr
 
 from .. import (
 encoding,
@@ -335,3 +336,129 @@
 return author[:f].strip(' "').replace('\\"', '"')
 f = author.find('@')
 return author[:f].replace('.', ' ')
+
+@attr.s(hash=True)
+class mailmapping(object):
+'''Represents a username/email key or value in
+a mailmap file'''
+email = attr.ib()
+name = attr.ib(default=None)
+
+def parsemailmap(mailmapcontent):
+"""Parses data in the .mailmap format
+
+>>> mmdata = b"\\n".join([
+... b'# Comment',
+... b'Name ',
+... b' ',
+... b'Name  ',
+... b'Name  Commit ',
+... ])
+>>> mm = parsemailmap(mmdata)
+>>> for key in sorted(mm.keys()):
+... print(key)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name='Commit')
+>>> for val in sorted(mm.values()):
+... print(val)
+mailmapping(email='comm...@email.xx', name='Name')
+mailmapping(email='n...@email.xx', name=None)
+mailmapping(email='pro...@email.xx', name='Name')
+mailmapping(email='pro...@email.xx', name='Name')
+"""
+mailmap = {}
+for line in mailmapcontent.splitlines():
+
+# Don't bother checking the line if it is a comment or
+# is an improperly formed author field
+if line.lstrip().startswith('#') or any(c not in line for c in '<>@'):
+continue
+
+# name, email hold the parsed emails and names for each line
+# name_builder holds the words in a persons name
+name, email = [], []
+namebuilder = []
+
+for element in line.split():
+if element.startswith('#'):
+# If we 

D2960: stringutil: move person function from templatefilters

2018-03-29 Thread sheehan (Connor Sheehan)
sheehan updated this revision to Diff 7360.
sheehan marked an inline comment as done.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2960?vs=7344=7360

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

AFFECTED FILES
  mercurial/templatefilters.py
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -308,3 +308,30 @@
 False
 '''
 return _correctauthorformat.match(author) is not None
+
+def person(author):
+"""Any text. Returns the name before an email address,
+interpreting it as per RFC 5322.
+
+>>> person(b'foo@bar')
+'foo'
+>>> person(b'Foo Bar ')
+'Foo Bar'
+>>> person(b'"Foo Bar" ')
+'Foo Bar'
+>>> person(b'"Foo \"buz\" Bar" ')
+'Foo "buz" Bar'
+>>> # The following are invalid, but do exist in real-life
+...
+>>> person(b'Foo "buz" Bar ')
+'Foo "buz" Bar'
+>>> person(b'"Foo Bar ')
+'Foo Bar'
+"""
+if '@' not in author:
+return author
+f = author.find('<')
+if f != -1:
+return author[:f].strip(' "').replace('\\"', '"')
+f = author.find('@')
+return author[:f].replace('.', ' ')
diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py
--- a/mercurial/templatefilters.py
+++ b/mercurial/templatefilters.py
@@ -292,29 +292,8 @@
 def person(author):
 """Any text. Returns the name before an email address,
 interpreting it as per RFC 5322.
-
->>> person(b'foo@bar')
-'foo'
->>> person(b'Foo Bar ')
-'Foo Bar'
->>> person(b'"Foo Bar" ')
-'Foo Bar'
->>> person(b'"Foo \"buz\" Bar" ')
-'Foo "buz" Bar'
->>> # The following are invalid, but do exist in real-life
-...
->>> person(b'Foo "buz" Bar ')
-'Foo "buz" Bar'
->>> person(b'"Foo Bar ')
-'Foo Bar'
 """
-if '@' not in author:
-return author
-f = author.find('<')
-if f != -1:
-return author[:f].strip(' "').replace('\\"', '"')
-f = author.find('@')
-return author[:f].replace('.', ' ')
+return stringutil.person(author)
 
 @templatefilter('revescape')
 def revescape(text):



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


D2959: stringutil: add isauthorwellformed function

2018-03-29 Thread sheehan (Connor Sheehan)
sheehan updated this revision to Diff 7359.
sheehan marked 3 inline comments as done.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2959?vs=7343=7359

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -286,3 +286,25 @@
 If s is not a valid boolean, returns None.
 """
 return _booleans.get(s.lower(), None)
+
+_correctauthorformat = remod.compile(br'^[^<]+\s\<[^<>]+@[^<>]+\>$')
+def isauthorwellformed(author):
+'''Return True if the author field is well formed
+(ie "Contributor Name ")
+
+>>> isauthorwellformed(b'Good Author ')
+True
+>>> isauthorwellformed(b'Author ')
+True
+>>> isauthorwellformed(b'Bad Author')
+False
+>>> isauthorwellformed(b'Bad Author >> isauthorwellformed(b'Bad Author aut...@author.com')
+False
+>>> isauthorwellformed(b'')
+False
+>>> isauthorwellformed(b'Bad Author ')
+False
+'''
+return _correctauthorformat.match(author) is not None



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


D2904: templatefuncs: add mailmap template function

2018-03-27 Thread sheehan (Connor Sheehan)
sheehan updated this revision to Diff 7345.
sheehan marked 5 inline comments as done.

REPOSITORY
  rHG Mercurial

CHANGES SINCE LAST UPDATE
  https://phab.mercurial-scm.org/D2904?vs=7163=7345

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

AFFECTED FILES
  mercurial/templatefuncs.py
  mercurial/utils/stringutil.py
  tests/test-mailmap.t

CHANGE DETAILS

diff --git a/tests/test-mailmap.t b/tests/test-mailmap.t
new file mode 100644
--- /dev/null
+++ b/tests/test-mailmap.t
@@ -0,0 +1,67 @@
+Create a repo and add some commits
+
+  $ hg init mm
+  $ cd mm
+  $ echo "Test content" > testfile1
+  $ hg add testfile1
+  $ hg commit -m "First commit" -u "Proper "
+  $ echo "Test content 2" > testfile2
+  $ hg add testfile2
+  $ hg commit -m "Second commit" -u "Commit Name 2 "
+  $ echo "Test content 3" > testfile3
+  $ hg add testfile3
+  $ hg commit -m "Third commit" -u "Commit Name 3 "
+  $ echo "Test content 4" > testfile4
+  $ hg add testfile4
+  $ hg commit -m "Fourth commit" -u "Commit Name 4 "
+
+Add a .mailmap file with each possible entry type plus comments
+  $ cat > .mailmap << EOF
+  > # Comment shouldn't break anything
+  >   # Should update email only
+  > Proper Name 2  # Should update name only
+  > Proper Name 3   # Should update name, email due 
to email
+  > Proper Name 4  Commit Name 4  # Should update 
name, email due to name, email
+  > EOF
+  $ hg add .mailmap
+  $ hg commit -m "Add mailmap file" -u "Testuser "
+
+Output of commits should be normal without filter
+  $ hg log -T "{author}\n" -r "all()"
+  Proper 
+  Commit Name 2 
+  Commit Name 3 
+  Commit Name 4 
+  Testuser 
+
+Output of commits with filter shows their mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+Add new mailmap entry for testuser
+  $ cat >> .mailmap << EOF
+  >  
+  > EOF
+
+Output of commits with filter shows their updated mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+A commit with improperly formatted user field should not break the filter
+  $ echo "some more test content" > testfile1
+  $ hg commit -m "Commit with improper user field" -u "Improper user"
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+  Improper user
diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -14,6 +14,7 @@
 import textwrap
 
 from ..i18n import _
+from ..thirdparty import attr
 
 from .. import (
 encoding,
@@ -312,6 +313,7 @@
 def person(author):
 """Any text. Returns the name before an email address,
 interpreting it as per RFC 5322.
+
 >>> person(b'foo@bar')
 'foo'
 >>> person(b'Foo Bar ')
@@ -334,3 +336,129 @@
 return author[:f].strip(' "').replace('\\"', '"')
 f = author.find('@')
 return author[:f].replace('.', ' ')
+
+@attr.s(hash=True)
+class mailmapping(object):
+'''Represents a username/email key or value in
+a mailmap file'''
+email = attr.ib()
+name = attr.ib(default=None)
+
+def parsemailmap(mailmapcontent):
+"""Parses data in the .mailmap format
+
+>>> mmdata = "\\n".join([
+... '# Comment',
+... 'Name ',
+... ' ',
+... 'Name  ',
+... 'Name  Commit ',
+... ])
+>>> mm = parsemailmap(mmdata)
+>>> for key in sorted(mm.keys()):
+... print(key)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name=None)
+mailmapping(email='comm...@email.xx', name='Commit')
+>>> for val in sorted(mm.values()):
+... print(val)
+mailmapping(email='comm...@email.xx', name='Name')
+mailmapping(email='n...@email.xx', name=None)
+mailmapping(email='pro...@email.xx', name='Name')
+mailmapping(email='pro...@email.xx', name='Name')
+"""
+mailmap = {}
+for line in mailmapcontent.splitlines():
+
+# Don't bother checking the line if it is a comment or
+# is an improperly formed author field
+if line.lstrip().startswith('#') or any(c not in line for c in '<>@'):
+continue
+
+# name, email hold the parsed emails and names for each line
+

D2959: stringutil: add isauthorwellformed function

2018-03-27 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The regular expression for this function formerly lived at
  
https://hg.mozilla.org/hgcustom/version-control-tools/file/tip/hghooks/mozhghooks/author_format.py#l13

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -286,3 +286,25 @@
 If s is not a valid boolean, returns None.
 """
 return _booleans.get(s.lower(), None)
+
+_correctauthorformat = remod.compile('^[^<]+\s\<[^<>]+@[^<>]+\>$')
+def isauthorwellformed(author):
+'''Return True if the author field is well formed
+(ie "Contributor Name ")
+
+>>> isauthorwellformed('Good Author ')
+True
+>>> isauthorwellformed('Author ')
+True
+>>> isauthorwellformed('Bad Author')
+False
+>>> isauthorwellformed('Bad Author >> isauthorwellformed('Bad Author aut...@author.com')
+False
+>>> isauthorwellformed('')
+False
+>>> isauthorwellformed('Bad Author ')
+False
+'''
+return bool(_correctauthorformat.match(author))



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


D2960: stringutil: move person function from templatefilters

2018-03-27 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Move the person function from template filters to the stringutil
  module, so it can be reused in the mailmap template function.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/templatefilters.py
  mercurial/utils/stringutil.py

CHANGE DETAILS

diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py
--- a/mercurial/utils/stringutil.py
+++ b/mercurial/utils/stringutil.py
@@ -308,3 +308,29 @@
 False
 '''
 return bool(_correctauthorformat.match(author))
+
+def person(author):
+"""Any text. Returns the name before an email address,
+interpreting it as per RFC 5322.
+>>> person(b'foo@bar')
+'foo'
+>>> person(b'Foo Bar ')
+'Foo Bar'
+>>> person(b'"Foo Bar" ')
+'Foo Bar'
+>>> person(b'"Foo \"buz\" Bar" ')
+'Foo "buz" Bar'
+>>> # The following are invalid, but do exist in real-life
+...
+>>> person(b'Foo "buz" Bar ')
+'Foo "buz" Bar'
+>>> person(b'"Foo Bar ')
+'Foo Bar'
+"""
+if '@' not in author:
+return author
+f = author.find('<')
+if f != -1:
+return author[:f].strip(' "').replace('\\"', '"')
+f = author.find('@')
+return author[:f].replace('.', ' ')
diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py
--- a/mercurial/templatefilters.py
+++ b/mercurial/templatefilters.py
@@ -290,31 +290,7 @@
 
 @templatefilter('person')
 def person(author):
-"""Any text. Returns the name before an email address,
-interpreting it as per RFC 5322.
-
->>> person(b'foo@bar')
-'foo'
->>> person(b'Foo Bar ')
-'Foo Bar'
->>> person(b'"Foo Bar" ')
-'Foo Bar'
->>> person(b'"Foo \"buz\" Bar" ')
-'Foo "buz" Bar'
->>> # The following are invalid, but do exist in real-life
-...
->>> person(b'Foo "buz" Bar ')
-'Foo "buz" Bar'
->>> person(b'"Foo Bar ')
-'Foo Bar'
-"""
-if '@' not in author:
-return author
-f = author.find('<')
-if f != -1:
-return author[:f].strip(' "').replace('\\"', '"')
-f = author.find('@')
-return author[:f].replace('.', ' ')
+return stringutil.person(author)
 
 @templatefilter('revescape')
 def revescape(text):



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


D2904: templatefuncs: add mailmap template function

2018-03-20 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  This commit adds a template function to support the .mailmap file
  in Mercurial repositories. The .mailmap file comes from git, and
  can be used to map new emails and names for old commits. The general
  use case is that someone may change their name or author commits
  under different emails and aliases, which would make these
  commits appear as though they came from different persons. The
  file allows you to specify the correct name that should be used
  in place of the author field specified in the commit.
  
  The mailmap file has 4 possible formats used to map old "commit"
  names to new "proper" names:
  
  1.  
  2. Proper Name 
  3. Proper Name  
  4. Proper Name  Commit Name 
  
  Essentially there is a commit email present in each mailmap entry,
  that maps to either an updated name, email, or both. The final
  possible format allows commits authored by a person who used
  both an old name and an old email to map to a new name and email.
  
  To parse the file, we split by spaces and build a name out
  of every element that does not start with "<". Once we find an element
  that does start with "<" we concatenate all the name elements that preceded
  and add that as a parsed name. We then add the email as the first
  parsed email. We repeat the process until the end of the line, or
  a comment is found. We will be left with all parsed names in a list,
  and all parsed emails in a list, with the 0 index being the proper
  values and the 1 index being the commit values (if they were specified
  in the entry).
  
  The commit values are added as the keys to a dict, and with the proper
  fields as the values. The mapname function takes the mapping object and
  the commit author field and attempts to look for a corresponding entry.
  To do so we try (commit name, commit email) first, and if no results are
  returned then (None, commit email) is also looked up. This is due to
  format 4 from above, where someone may have a mailmap entry with both
  name and email, and if they don't it is possible they have an entry that
  uses only the commit email.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/templatefuncs.py
  tests/test-mailmap.t

CHANGE DETAILS

diff --git a/tests/test-mailmap.t b/tests/test-mailmap.t
new file mode 100644
--- /dev/null
+++ b/tests/test-mailmap.t
@@ -0,0 +1,67 @@
+Create a repo and add some commits
+
+  $ hg init mm
+  $ cd mm
+  $ echo "Test content" > testfile1
+  $ hg add testfile1
+  $ HGUSER="Proper " hg commit -m "First commit"
+  $ echo "Test content 2" > testfile2
+  $ hg add testfile2
+  $ HGUSER="Commit Name 2 " hg commit -m "Second commit"
+  $ echo "Test content 3" > testfile3
+  $ hg add testfile3
+  $ HGUSER="Commit Name 3 " hg commit -m "Third commit"
+  $ echo "Test content 4" > testfile4
+  $ hg add testfile4
+  $ HGUSER="Commit Name 4 " hg commit -m "Fourth commit"
+
+Add a .mailmap file with each possible entry type plus comments
+  $ cat > .mailmap << EOF
+  > # Comment shouldn't break anything
+  >   # Should update email only
+  > Proper Name 2  # Should update name only
+  > Proper Name 3   # Should update name, email due 
to email
+  > Proper Name 4  Commit Name 4  # Should update 
name, email due to name, email
+  > EOF
+  $ hg add .mailmap
+  $ HGUSER="Testuser " hg commit -m "Add mailmap file"
+
+Output of commits should be normal without filter
+  $ hg log -T "{author}\n" -r "all()"
+  Proper 
+  Commit Name 2 
+  Commit Name 3 
+  Commit Name 4 
+  Testuser 
+
+Output of commits with filter shows their mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+Add new mailmap entry for testuser
+  $ cat >> .mailmap << EOF
+  >  
+  > EOF
+
+Output of commits with filter shows their updated mailmap values
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 
+  Testuser 
+
+A commit with improperly formatted user field should not break the filter
+  $ echo "some more test content" > testfile1
+  $ HGUSER="Improper user" hg commit -m "Commit with improper user field"
+  $ hg log -T "{mailmap(author)}\n" -r "all()"
+  Proper 
+  Proper Name 2 
+  Proper Name 3 
+  Proper Name 4 

D2903: utils: add isauthorwellformed function

2018-03-20 Thread sheehan (Connor Sheehan)
sheehan created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  Adds a function to determine if an author field is formatted
  correctly (ie "Contributor Name ")

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  mercurial/util.py

CHANGE DETAILS

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -2615,6 +2615,12 @@
 r = None
 return author[author.find('<') + 1:r]
 
+_correctauthorformat = re.compile('^[^<]+\s\<[^<>]+@[^<>]+\>$')
+def isauthorwellformed(author):
+'''Return True if the author field is well formed
+(ie "Contributor Name ")'''
+return bool(_correctauthorformat.match(author))
+
 def ellipsis(text, maxlength=400):
 """Trim string to at most maxlength (default: 400) columns in display."""
 return encoding.trim(text, maxlength, ellipsis='...')



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