infocalypse
 
(Arne Babenhauserheide)
2013-05-03: added the exported patches for bug 4 (UTC). Not yet finished, but I

added the exported patches for bug 4 (UTC). Not yet finished, but I want to ensure that the patches stay available.

diff --git a/.bugs/details/4dfc4cc28a7fa69f040776a7138da78ee89ec819.txt b/.bugs/details/4dfc4cc28a7fa69f040776a7138da78ee89ec819.txt
new file mode 100644
--- /dev/null
+++ b/.bugs/details/4dfc4cc28a7fa69f040776a7138da78ee89ec819.txt
@@ -0,0 +1,564 @@
+# Lines starting with '#' and sections without content
+# are not displayed by a call to 'details'
+#
+[paths]
+# Paths related to this bug.
+# suggested format: REPO_PATH:LINENUMBERS
+
+
+[details]
+# Additional details
+
+
+[expected]
+# The expected result
+
+
+[actual]
+# What happened instead
+
+
+[reproduce]
+# Reproduction steps
+
+
+[comments]
+# Comments and updates - leave your name
+
+Potential patches (export of my experiments to ensure that the code does not get lost):
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1320398320 -3600
+# Node ID d9e348082e48f87c4ecb05f0930b754348168c1b
+# Parent  a708b65baeb92ce4971cccaee5b799b88595ddb2
+clone: get all bookmarks before updating
+* * *
+clone: FIX: also get the bookmarks for remote target repos which support pushkey.
+
+diff --git a/mercurial/hg.py b/mercurial/hg.py
+--- a/mercurial/hg.py
++++ b/mercurial/hg.py
+@@ -353,6 +353,21 @@ def clone(ui, peeropts, source, dest=Non
+         if dircleanup:
+             dircleanup.close()
+ 
++        # clone all bookmarks
++        if destrepo.local() and srcrepo.capable("pushkey"):
++            rb = srcrepo.listkeys('bookmarks')
++            for k, n in rb.iteritems():
++                try:
++                    m = destrepo.lookup(n)
++                    destrepo._bookmarks[k] = m
++                except error.RepoLookupError:
++                    pass
++            if rb:
++                bookmarks.write(destrepo)
++        elif srcrepo.local() and destrepo.capable("pushkey"):
++            for k, n in srcrepo._bookmarks.iteritems():
++                destrepo.pushkey('bookmarks', k, '', hex(n))
++
+         if destrepo.local():
+             fp = destrepo.opener("hgrc", "w", text=True)
+             fp.write("[paths]\n")
+@@ -378,21 +393,6 @@ def clone(ui, peeropts, source, dest=Non
+                 destrepo.ui.status(_("updating to branch %s\n") % bn)
+                 _update(destrepo, uprev)
+ 
+-        # clone all bookmarks
+-        if destrepo.local() and srcrepo.capable("pushkey"):
+-            rb = srcrepo.listkeys('bookmarks')
+-            for k, n in rb.iteritems():
+-                try:
+-                    m = destrepo.lookup(n)
+-                    destrepo._bookmarks[k] = m
+-                except error.RepoLookupError:
+-                    pass
+-            if rb:
+-                bookmarks.write(destrepo)
+-        elif srcrepo.local() and destrepo.capable("pushkey"):
+-            for k, n in srcrepo._bookmarks.iteritems():
+-                destrepo.pushkey('bookmarks', k, '', hex(n))
+-
+         return srcrepo, destrepo
+     finally:
+         release(srclock, destlock)
+
+# HG changeset patch
+# User bab@draketo.de
+# Date 1343931127 -7200
+# Branch stable
+# Node ID f5e211663739e31f2e476c43992ee5335f9d8146
+# Parent  00182b3d087909e3c3ae44761efecdde8f319ef3
+revsets: added branchpoint() for revisions with more than one child.
+
+Reason: Get very terse information via
+
+    hg glog --rev "head() or merge() or branchpoint()"
+
+diff --git a/mercurial/revset.py b/mercurial/revset.py
+--- a/mercurial/revset.py
++++ b/mercurial/revset.py
+@@ -710,6 +710,15 @@ def merge(repo, subset, x):
+     cl = repo.changelog
+     return [r for r in subset if cl.parentrevs(r)[1] != -1]
+ 
++def branchpoint(repo, subset, x):
++    """``branchpoint()``
++    Changeset has more than one child.
++    """
++    # i18n: "merge" is a keyword
++    getargs(x, 0, 0, _("branchpoint takes no arguments"))
++    cl = repo.changelog
++    return [r for r in subset if cl.children(repo[r].node())[1:]]
++
+ def minrev(repo, subset, x):
+     """``min(set)``
+     Changeset with lowest revision number in set.
+@@ -1137,6 +1146,7 @@ symbols = {
+     "bisected": bisected,
+     "bookmark": bookmark,
+     "branch": branch,
++    "branchpoint": branchpoint,
+     "children": children,
+     "closed": closed,
+     "contains": contains,
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1355793798 -3600
+# Node ID c4e74e535082cee18b73f09cf5b0c6b5ffbcd19d
+# Parent  7aa7380691b8815200dda268aa1af19fd56aa741
+Option to enforce using UTC for commit dates.
+
+The timezone entries in commit messages give away location information
+of the commiter, which can be dangerous when Mercurial is used
+anonymously.
+
+To mitigate that danger, this commit adds an rc-option to use UTC
+dates, except when the timezone is requested explicitely via a date
+string or by amending a commit without changing the date and time.
+
+To switch to UTC times, add
+
+    [ui]
+    datetimeutc = True
+
+to your ~/.hgrc or a .hg/hgrc.
+
+Extensions like infocalypse can also set this option when doing the
+initial clone from an anonymous source to ensure that the default
+behaviour of Mercurial is safe.
+
+diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
+--- a/mercurial/cmdutil.py
++++ b/mercurial/cmdutil.py
+@@ -1586,7 +1586,9 @@ def commit(ui, repo, commitfunc, pats, o
+     '''commit the specified files or all outstanding changes'''
+     date = opts.get('date')
+     if date:
+-        opts['date'] = util.parsedate(date)
++        opts['date'] = util.timezoneprivacy(ui.configbool('ui', 'datetimeutc'),
++                                            date)
++
+     message = logmessage(ui, opts)
+ 
+     # extract addremove carefully -- this function can be called from a command
+diff --git a/mercurial/commands.py b/mercurial/commands.py
+--- a/mercurial/commands.py
++++ b/mercurial/commands.py
+@@ -1304,9 +1304,12 @@ def commit(ui, repo, *pats, **opts):
+             if not message:
+                 message = old.description()
+                 editor = cmdutil.commitforceeditor
++            date = util.timezoneprivacy(ui.configbool('ui', 'datetimeutc'),
++                                        opts.get('date'),
++                                        old.date())
+             return repo.commit(message,
+                                opts.get('user') or old.user(),
+-                               opts.get('date') or old.date(),
++                               date,
+                                match,
+                                editor=editor,
+                                extra=extra)
+diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
+--- a/mercurial/help/config.txt
++++ b/mercurial/help/config.txt
+@@ -1128,6 +1128,10 @@ User interface controls.
+     changes, abort the commit.
+     Default is False.
+ 
++``datetimeutc``
++    Whether to always use Universal Time Coordinated (UTC) for date
++    entries when committing.
++
+ ``debug``
+     Print debugging information. True or False. Default is False.
+ 
+diff --git a/mercurial/util.py b/mercurial/util.py
+--- a/mercurial/util.py
++++ b/mercurial/util.py
+@@ -980,20 +980,20 @@ def shortdate(date=None):
+     """turn (timestamp, tzoff) tuple into iso 8631 date."""
+     return datestr(date, format='%Y-%m-%d')
+ 
++def timezone(string):
++    tz = string.split()[-1]
++    if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
++        sign = (tz[0] == "+") and 1 or -1
++        hours = int(tz[1:3])
++        minutes = int(tz[3:5])
++        return -sign * (hours * 60 + minutes) * 60
++    if tz == "GMT" or tz == "UTC":
++        return 0
++    return None
++
+ def strdate(string, format, defaults=[]):
+     """parse a localized time string and return a (unixtime, offset) tuple.
+     if the string cannot be parsed, ValueError is raised."""
+-    def timezone(string):
+-        tz = string.split()[-1]
+-        if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
+-            sign = (tz[0] == "+") and 1 or -1
+-            hours = int(tz[1:3])
+-            minutes = int(tz[3:5])
+-            return -sign * (hours * 60 + minutes) * 60
+-        if tz == "GMT" or tz == "UTC":
+-            return 0
+-        return None
+-
+     # NOTE: unixtime = localunixtime + offset
+     offset, date = timezone(string), string
+     if offset is not None:
+@@ -1151,6 +1151,35 @@ def matchdate(date):
+         start, stop = lower(date), upper(date)
+         return lambda x: x >= start and x <= stop
+ 
++def timezoneprivacy(privacy, datestring=None, date=None):
++    """Switch to UTC if the timezone could be a risk to
++    privacy and the timezone was not requested explicitly.
++
++    >>> withtz = parsedate("2012-12-23 10:04:23 +0300")
++    >>> localtz = makedate()[1]
++    >>> notz = timezoneprivacy(True, "2012-12-23 07:04:23")
++    >>> notz[1] == 0
++    True
++    >>> notz[0] - localtz == withtz[0]
++    True
++    >>> (notz[0], localtz) == timezoneprivacy(False, "2012-12-23 07:04:23")
++    True
++    >>> (withtz[0], -3600) == timezoneprivacy(True, "2012-12-23 08:04:23 +0100")
++    True
++    >>> (withtz[0], 18000) == timezoneprivacy(True, "2012-12-23 02:04:23 -0500")
++    True
++    """
++    when = parsedate(datestring or date or makedate())
++    if not privacy:
++        return when
++    hastimezone = timezone(datestring) is not None
++    if datestring and not hastimezone:
++        return when[0], 0
++    if datestring or date:
++        return when
++    # no explicit datestring or date: use current UTC
++    return when[0], 0
++
+ def shortuser(user):
+     """Return a short representation of a user name or email address."""
+     f = user.find('@')
+diff --git a/tests/test-commit.t b/tests/test-commit.t
+--- a/tests/test-commit.t
++++ b/tests/test-commit.t
+@@ -90,12 +90,20 @@ commit added file that has been deleted
+   dir/file
+   committed changeset 4:49176991390e
+ 
+-An empty date was interpreted as epoch origin
++date argument parsing
+ 
+   $ echo foo >> foo
+   $ hg commit -d '' -m commit-no-date
+   $ hg tip --template '{date|isodate}\n' | grep '1970'
+   [1]
++  $ echo foo >> foo
++  $ hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23' -m commit-utc
++  $ hg tip --template '{date|isodate}\n'
++  1982-04-23 14:23 +0000
++  $ echo foo >> foo
++  $ hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23 +0100' -m commit-utc
++  $ hg tip --template '{date|isodate}\n'
++  1982-04-23 14:23 +0100
+ 
+ Make sure we do not obscure unknown requires file entries (issue2649)
+ 
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1355924730 -3600
+# Node ID 790b40844560e268f9e12a61c313279718bb6f93
+# Parent  c4e74e535082cee18b73f09cf5b0c6b5ffbcd19d
+Simpler implementation of enforcing UTC for dates.
+
+diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
+--- a/mercurial/cmdutil.py
++++ b/mercurial/cmdutil.py
+@@ -1586,9 +1586,7 @@ def commit(ui, repo, commitfunc, pats, o
+     '''commit the specified files or all outstanding changes'''
+     date = opts.get('date')
+     if date:
+-        opts['date'] = util.timezoneprivacy(ui.configbool('ui', 'datetimeutc'),
+-                                            date)
+-
++        opts['date'] = util.parsedate(date)
+     message = logmessage(ui, opts)
+ 
+     # extract addremove carefully -- this function can be called from a command
+diff --git a/mercurial/commands.py b/mercurial/commands.py
+--- a/mercurial/commands.py
++++ b/mercurial/commands.py
+@@ -1276,6 +1276,9 @@ def commit(ui, repo, *pats, **opts):
+             raise util.Abort(_('can only close branch heads'))
+         extra['close'] = 1
+ 
++    if ui.configbool('ui', 'datetimeutc'):
++        pass #time.timezone = "UTC"
++
+     branch = repo[None].branch()
+     bheads = repo.branchheads(branch)
+ 
+@@ -1304,12 +1307,9 @@ def commit(ui, repo, *pats, **opts):
+             if not message:
+                 message = old.description()
+                 editor = cmdutil.commitforceeditor
+-            date = util.timezoneprivacy(ui.configbool('ui', 'datetimeutc'),
+-                                        opts.get('date'),
+-                                        old.date())
+             return repo.commit(message,
+                                opts.get('user') or old.user(),
+-                               date,
++                               opts.get('date') or old.date(),
+                                match,
+                                editor=editor,
+                                extra=extra)
+diff --git a/mercurial/util.py b/mercurial/util.py
+--- a/mercurial/util.py
++++ b/mercurial/util.py
+@@ -980,20 +980,20 @@ def shortdate(date=None):
+     """turn (timestamp, tzoff) tuple into iso 8631 date."""
+     return datestr(date, format='%Y-%m-%d')
+ 
+-def timezone(string):
+-    tz = string.split()[-1]
+-    if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
+-        sign = (tz[0] == "+") and 1 or -1
+-        hours = int(tz[1:3])
+-        minutes = int(tz[3:5])
+-        return -sign * (hours * 60 + minutes) * 60
+-    if tz == "GMT" or tz == "UTC":
+-        return 0
+-    return None
+-
+ def strdate(string, format, defaults=[]):
+     """parse a localized time string and return a (unixtime, offset) tuple.
+     if the string cannot be parsed, ValueError is raised."""
++    def timezone(string):
++        tz = string.split()[-1]
++        if tz[0] in "+-" and len(tz) == 5 and tz[1:].isdigit():
++            sign = (tz[0] == "+") and 1 or -1
++            hours = int(tz[1:3])
++            minutes = int(tz[3:5])
++            return -sign * (hours * 60 + minutes) * 60
++        if tz == "GMT" or tz == "UTC":
++            return 0
++        return None
++
+     # NOTE: unixtime = localunixtime + offset
+     offset, date = timezone(string), string
+     if offset is not None:
+@@ -1151,35 +1151,6 @@ def matchdate(date):
+         start, stop = lower(date), upper(date)
+         return lambda x: x >= start and x <= stop
+ 
+-def timezoneprivacy(privacy, datestring=None, date=None):
+-    """Switch to UTC if the timezone could be a risk to
+-    privacy and the timezone was not requested explicitly.
+-
+-    >>> withtz = parsedate("2012-12-23 10:04:23 +0300")
+-    >>> localtz = makedate()[1]
+-    >>> notz = timezoneprivacy(True, "2012-12-23 07:04:23")
+-    >>> notz[1] == 0
+-    True
+-    >>> notz[0] - localtz == withtz[0]
+-    True
+-    >>> (notz[0], localtz) == timezoneprivacy(False, "2012-12-23 07:04:23")
+-    True
+-    >>> (withtz[0], -3600) == timezoneprivacy(True, "2012-12-23 08:04:23 +0100")
+-    True
+-    >>> (withtz[0], 18000) == timezoneprivacy(True, "2012-12-23 02:04:23 -0500")
+-    True
+-    """
+-    when = parsedate(datestring or date or makedate())
+-    if not privacy:
+-        return when
+-    hastimezone = timezone(datestring) is not None
+-    if datestring and not hastimezone:
+-        return when[0], 0
+-    if datestring or date:
+-        return when
+-    # no explicit datestring or date: use current UTC
+-    return when[0], 0
+-
+ def shortuser(user):
+     """Return a short representation of a user name or email address."""
+     f = user.find('@')
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1355925188 -3600
+# Node ID 8070267ca30f22357f65f96ea0ed99569639f094
+# Parent  790b40844560e268f9e12a61c313279718bb6f93
+test.
+
+diff --git a/mercurial/commands.py b/mercurial/commands.py
+--- a/mercurial/commands.py
++++ b/mercurial/commands.py
+@@ -1277,7 +1277,7 @@ def commit(ui, repo, *pats, **opts):
+         extra['close'] = 1
+ 
+     if ui.configbool('ui', 'datetimeutc'):
+-        pass #time.timezone = "UTC"
++        time.timezone = "UTC"
+ 
+     branch = repo[None].branch()
+     bheads = repo.branchheads(branch)
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1355925219 -3600
+# Node ID 5e3231e4caf46c078a5c0c83f64648dca630f5f1
+# Parent  8070267ca30f22357f65f96ea0ed99569639f094
+test.
+
+diff --git a/mercurial/commands.py b/mercurial/commands.py
+--- a/mercurial/commands.py
++++ b/mercurial/commands.py
+@@ -1277,7 +1277,7 @@ def commit(ui, repo, *pats, **opts):
+         extra['close'] = 1
+ 
+     if ui.configbool('ui', 'datetimeutc'):
+-        time.timezone = "UTC"
++        time.timezone = "GMT+5"
+ 
+     branch = repo[None].branch()
+     bheads = repo.branchheads(branch)
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1355925239 -3600
+# Node ID ce47f904c4c735ad694c4047b674abf30cda0e77
+# Parent  5e3231e4caf46c078a5c0c83f64648dca630f5f1
+test.
+
+diff --git a/mercurial/commands.py b/mercurial/commands.py
+--- a/mercurial/commands.py
++++ b/mercurial/commands.py
+@@ -1278,6 +1278,7 @@ def commit(ui, repo, *pats, **opts):
+ 
+     if ui.configbool('ui', 'datetimeutc'):
+         time.timezone = "GMT+5"
++    print time.timezone
+ 
+     branch = repo[None].branch()
+     bheads = repo.branchheads(branch)
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1355945885 -3600
+# Node ID 5252b47c54bfde07dc8844e47bb33fc685de3ce8
+# Parent  ce47f904c4c735ad694c4047b674abf30cda0e77
+timezone: Fix test to always use a on-utc timezone.
+
+diff --git a/tests/test-commit.t b/tests/test-commit.t
+--- a/tests/test-commit.t
++++ b/tests/test-commit.t
+@@ -97,11 +97,11 @@ date argument parsing
+   $ hg tip --template '{date|isodate}\n' | grep '1970'
+   [1]
+   $ echo foo >> foo
+-  $ hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23' -m commit-utc
++  $ TZ="Europe/Berlin" hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23' -m commit-utc
+   $ hg tip --template '{date|isodate}\n'
+   1982-04-23 14:23 +0000
+   $ echo foo >> foo
+-  $ hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23 +0100' -m commit-utc
++  $ TZ="Europe/Berlin" hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23 +0100' -m commit-utc
+   $ hg tip --template '{date|isodate}\n'
+   1982-04-23 14:23 +0100
+ 
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1355945986 -3600
+# Node ID 909abca4327b214058989204a2afb7d32deb446b
+# Parent  5252b47c54bfde07dc8844e47bb33fc685de3ce8
+enforce UTC: time.timezone to 0
+
+diff --git a/mercurial/commands.py b/mercurial/commands.py
+--- a/mercurial/commands.py
++++ b/mercurial/commands.py
+@@ -1277,8 +1277,7 @@ def commit(ui, repo, *pats, **opts):
+         extra['close'] = 1
+ 
+     if ui.configbool('ui', 'datetimeutc'):
+-        time.timezone = "GMT+5"
+-    print time.timezone
++        time.timezone = 0
+ 
+     branch = repo[None].branch()
+     bheads = repo.branchheads(branch)
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1355945885 -3600
+# Node ID 0b0099e44145183560e7cc01c20e21cd3bea84d0
+# Parent  c4e74e535082cee18b73f09cf5b0c6b5ffbcd19d
+timezone: Fix test to always use a on-utc timezone.
+
+diff --git a/tests/test-commit.t b/tests/test-commit.t
+--- a/tests/test-commit.t
++++ b/tests/test-commit.t
+@@ -97,11 +97,11 @@ date argument parsing
+   $ hg tip --template '{date|isodate}\n' | grep '1970'
+   [1]
+   $ echo foo >> foo
+-  $ hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23' -m commit-utc
++  $ TZ="Europe/Berlin" hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23' -m commit-utc
+   $ hg tip --template '{date|isodate}\n'
+   1982-04-23 14:23 +0000
+   $ echo foo >> foo
+-  $ hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23 +0100' -m commit-utc
++  $ TZ="Europe/Berlin" hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23 +0100' -m commit-utc
+   $ hg tip --template '{date|isodate}\n'
+   1982-04-23 14:23 +0100
+ 
+
+# HG changeset patch
+# User Arne Babenhauserheide <bab@draketo.de>
+# Date 1357663148 -3600
+# Node ID 204a32c7c864f5b1db86c77e037bc895445201d7
+# Parent  0b0099e44145183560e7cc01c20e21cd3bea84d0
+Fix the timezoneprivacy test: You give the local time and it records the UTC according to that.
+
+diff --git a/tests/test-commit.t b/tests/test-commit.t
+--- a/tests/test-commit.t
++++ b/tests/test-commit.t
+@@ -99,7 +99,7 @@ date argument parsing
+   $ echo foo >> foo
+   $ TZ="Europe/Berlin" hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23' -m commit-utc
+   $ hg tip --template '{date|isodate}\n'
+-  1982-04-23 14:23 +0000
++  1982-04-23 12:23 +0000
+   $ echo foo >> foo
+   $ TZ="Europe/Berlin" hg --config ui.datetimeutc=True commit -d '1982-04-23 14:23 +0100' -m commit-utc
+   $ hg tip --template '{date|isodate}\n'
+