Patchwork [1,of,1] Option to enforce using UTC for commit dates

login
register
mail settings
Submitter arne_bab at web.de
Date Dec. 18, 2012, 1:24 a.m.
Message ID <c4e74e535082cee18b73.1355793893@fluss.Baez>
Download mbox | patch
Permalink /patch/180/
State Rejected
Headers show

Comments

arne_bab at web.de - Dec. 18, 2012, 1:24 a.m.
mercurial/cmdutil.py      |   4 ++-
 mercurial/commands.py     |   5 +++-
 mercurial/help/config.txt |   4 +++
 mercurial/util.py         |  51 ++++++++++++++++++++++++++++++++++++----------
 tests/test-commit.t       |  10 ++++++++-
 5 Dateien ver?ndert, 60 Zeilen hinzugef?gt(+), 14 Zeilen entfernt(-)


# HG changeset patch
# User Arne Babenhauserheide <bab at 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.
Pierre-Yves David - Dec. 18, 2012, 10:23 a.m.
On Tue, Dec 18, 2012 at 02:24:53AM +0100, arne_bab at web.de wrote:
>  mercurial/cmdutil.py      |   4 ++-
>  mercurial/commands.py     |   5 +++-
>  mercurial/help/config.txt |   4 +++
>  mercurial/util.py         |  51 ++++++++++++++++++++++++++++++++++++----------
>  tests/test-commit.t       |  10 ++++++++-
>  5 Dateien ver?ndert, 60 Zeilen hinzugef?gt(+), 14 Zeilen entfernt(-)
> 
> 
> # HG changeset patch
> # User Arne Babenhauserheide <bab at 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.

I do not get why so much code is altered.

Why don't you just alter `time.timezone` to be UTC ?
arne_bab at web.de - Dec. 19, 2012, 12:56 a.m.
Am Dienstag, 18. Dezember 2012, 11:23:06 schrieb Pierre-Yves David:
> I do not get why so much code is altered.
> 
> Why don't you just alter `time.timezone` to be UTC ?

In case that works: Because I did not think of that simple solution? :)

I?ll try it - thanks!

Best wishes,
Arne
--
Ich hab' nichts zu verbergen ? hab ich gedacht: 

- http://draketo.de/licht/lieder/ich-hab-nichts-zu-verbergen

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 316 bytes
Desc: This is a digitally signed message part.
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20121219/a15b4d8b/attachment.pgp>

Patch

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)