(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' +