Extract datestr from util.py to utils/dateutil.py
Details
Details
Diff Detail
Diff Detail
- Repository
- rHG Mercurial
- Lint
Lint Skipped - Unit
Unit Tests Skipped
( )
lothiraldan |
hg-reviewers |
Extract datestr from util.py to utils/dateutil.py
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | hgext/blackbox.py (3 lines) | |||
M | hgext/convert/cvs.py (3 lines) | |||
M | hgext/convert/cvsps.py (5 lines) | |||
M | hgext/convert/darcs.py (4 lines) | |||
M | hgext/convert/gnuarch.py (5 lines) | |||
M | hgext/convert/hg.py (3 lines) | |||
M | hgext/convert/monotone.py (4 lines) | |||
M | hgext/convert/p4.py (3 lines) | |||
M | hgext/convert/subversion.py (3 lines) | |||
M | hgext/keyword.py (7 lines) | |||
M | hgext/notify.py (3 lines) | |||
M | mercurial/cmdutil.py (7 lines) | |||
M | mercurial/commands.py (2 lines) | |||
M | mercurial/debugcommands.py (3 lines) | |||
M | mercurial/formatter.py (3 lines) | |||
M | mercurial/mdiff.py (3 lines) | |||
M | mercurial/obsutil.py (7 lines) | |||
M | mercurial/patch.py (5 lines) | |||
M | mercurial/subrepo.py (3 lines) | |||
M | mercurial/templatefilters.py (9 lines) | |||
M | mercurial/templater.py (4 lines) | |||
M | mercurial/util.py (46 lines) | |||
M | mercurial/utils/dateutil.py (36 lines) |
Status | Author | Revision | |
---|---|---|---|
Abandoned | durin42 | D2056 util: extract matchdate | |
Abandoned | durin42 | D2055 util: extract parsedate | |
Abandoned | durin42 | D2054 util: extract strdate | |
Abandoned | durin42 | ||
Abandoned | durin42 | D2052 util: extract shortdate | |
Abandoned | durin42 | D2051 util: extract datestr | |
Abandoned | durin42 | D2050 util: extract makedate | |
Abandoned | durin42 | ||
Abandoned | lothiraldan | ||
Abandoned | lothiraldan | ||
Abandoned | durin42 |
from mercurial.node import hex | from mercurial.node import hex | ||||
from mercurial import ( | from mercurial import ( | ||||
encoding, | encoding, | ||||
registrar, | registrar, | ||||
ui as uimod, | ui as uimod, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | ||||
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | ||||
# be specifying the version(s) of Mercurial they are tested with, or | # be specifying the version(s) of Mercurial they are tested with, or | ||||
# leave the attribute unspecified. | # leave the attribute unspecified. | ||||
testedwith = 'ships-with-hg-core' | testedwith = 'ships-with-hg-core' | ||||
cmdtable = {} | cmdtable = {} | ||||
repo = getattr(ui, '_bbrepo', None) | repo = getattr(ui, '_bbrepo', None) | ||||
if not lastui or repo: | if not lastui or repo: | ||||
lastui = ui | lastui = ui | ||||
if getattr(ui, '_bbinlog', False): | if getattr(ui, '_bbinlog', False): | ||||
# recursion and failure guard | # recursion and failure guard | ||||
return | return | ||||
ui._bbinlog = True | ui._bbinlog = True | ||||
default = self.configdate('devel', 'default-date') | default = self.configdate('devel', 'default-date') | ||||
date = util.datestr(default, '%Y/%m/%d %H:%M:%S') | date = dateutil.datestr(default, '%Y/%m/%d %H:%M:%S') | ||||
user = util.getuser() | user = util.getuser() | ||||
pid = '%d' % util.getpid() | pid = '%d' % util.getpid() | ||||
formattedmsg = msg[0] % msg[1:] | formattedmsg = msg[0] % msg[1:] | ||||
rev = '(unknown)' | rev = '(unknown)' | ||||
changed = '' | changed = '' | ||||
if repo: | if repo: | ||||
ctx = repo[None] | ctx = repo[None] | ||||
parents = ctx.parents() | parents = ctx.parents() |
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
encoding, | encoding, | ||||
error, | error, | ||||
pycompat, | pycompat, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import ( | from . import ( | ||||
common, | common, | ||||
cvsps, | cvsps, | ||||
) | ) | ||||
stringio = util.stringio | stringio = util.stringio | ||||
checktool = common.checktool | checktool = common.checktool | ||||
if maxrev and cs.id > maxrev: | if maxrev and cs.id > maxrev: | ||||
break | break | ||||
id = str(cs.id) | id = str(cs.id) | ||||
cs.author = self.recode(cs.author) | cs.author = self.recode(cs.author) | ||||
self.lastbranch[cs.branch] = id | self.lastbranch[cs.branch] = id | ||||
cs.comment = self.recode(cs.comment) | cs.comment = self.recode(cs.comment) | ||||
if self.ui.configbool('convert', 'localtimezone'): | if self.ui.configbool('convert', 'localtimezone'): | ||||
cs.date = makedatetimestamp(cs.date[0]) | cs.date = makedatetimestamp(cs.date[0]) | ||||
date = util.datestr(cs.date, '%Y-%m-%d %H:%M:%S %1%2') | date = dateutil.datestr(cs.date, '%Y-%m-%d %H:%M:%S %1%2') | ||||
self.tags.update(dict.fromkeys(cs.tags, id)) | self.tags.update(dict.fromkeys(cs.tags, id)) | ||||
files = {} | files = {} | ||||
for f in cs.entries: | for f in cs.entries: | ||||
files[f.file] = "%s%s" % ('.'.join([str(x) | files[f.file] = "%s%s" % ('.'.join([str(x) | ||||
for x in f.revision]), | for x in f.revision]), | ||||
['', '(DEAD)'][f.dead]) | ['', '(DEAD)'][f.dead]) | ||||
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
encoding, | encoding, | ||||
error, | error, | ||||
hook, | hook, | ||||
pycompat, | pycompat, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
pickle = util.pickle | pickle = util.pickle | ||||
class logentry(object): | class logentry(object): | ||||
'''Class logentry has the following attributes: | '''Class logentry has the following attributes: | ||||
.author - author name as CVS knows it | .author - author name as CVS knows it | ||||
.branch - name of branch this revision is on | .branch - name of branch this revision is on | ||||
.branches - revision tuple of branches starting at this revision | .branches - revision tuple of branches starting at this revision | ||||
break | break | ||||
ui.note(_('cache has %d log entries\n') % len(oldlog)) | ui.note(_('cache has %d log entries\n') % len(oldlog)) | ||||
except Exception as e: | except Exception as e: | ||||
ui.note(_('error reading cache: %r\n') % e) | ui.note(_('error reading cache: %r\n') % e) | ||||
if oldlog: | if oldlog: | ||||
date = oldlog[-1].date # last commit date as a (time,tz) tuple | date = oldlog[-1].date # last commit date as a (time,tz) tuple | ||||
date = util.datestr(date, '%Y/%m/%d %H:%M:%S %1%2') | date = dateutil.datestr(date, '%Y/%m/%d %H:%M:%S %1%2') | ||||
# build the CVS commandline | # build the CVS commandline | ||||
cmd = ['cvs', '-q'] | cmd = ['cvs', '-q'] | ||||
if root: | if root: | ||||
cmd.append('-d%s' % root) | cmd.append('-d%s' % root) | ||||
p = util.normpath(getrepopath(root)) | p = util.normpath(getrepopath(root)) | ||||
if not p.endswith('/'): | if not p.endswith('/'): | ||||
p += '/' | p += '/' | ||||
if opts["branches"] and (cs.branch or 'HEAD') not in opts["branches"]: | if opts["branches"] and (cs.branch or 'HEAD') not in opts["branches"]: | ||||
continue | continue | ||||
if not off: | if not off: | ||||
# Note: trailing spaces on several lines here are needed to have | # Note: trailing spaces on several lines here are needed to have | ||||
# bug-for-bug compatibility with cvsps. | # bug-for-bug compatibility with cvsps. | ||||
ui.write('---------------------\n') | ui.write('---------------------\n') | ||||
ui.write(('PatchSet %d \n' % cs.id)) | ui.write(('PatchSet %d \n' % cs.id)) | ||||
ui.write(('Date: %s\n' % util.datestr(cs.date, | ui.write(('Date: %s\n' % dateutil.datestr(cs.date, | ||||
'%Y/%m/%d %H:%M:%S %1%2'))) | '%Y/%m/%d %H:%M:%S %1%2'))) | ||||
ui.write(('Author: %s\n' % cs.author)) | ui.write(('Author: %s\n' % cs.author)) | ||||
ui.write(('Branch: %s\n' % (cs.branch or 'HEAD'))) | ui.write(('Branch: %s\n' % (cs.branch or 'HEAD'))) | ||||
ui.write(('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1], | ui.write(('Tag%s: %s \n' % (['', 's'][len(cs.tags) > 1], | ||||
','.join(cs.tags) or '(none)'))) | ','.join(cs.tags) or '(none)'))) | ||||
if cs.branchpoints: | if cs.branchpoints: | ||||
ui.write(('Branchpoints: %s \n') % | ui.write(('Branchpoints: %s \n') % | ||||
', '.join(sorted(cs.branchpoints))) | ', '.join(sorted(cs.branchpoints))) |
import re | import re | ||||
import shutil | import shutil | ||||
import tempfile | import tempfile | ||||
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
error, | error, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import common | from . import common | ||||
NoRepo = common.NoRepo | NoRepo = common.NoRepo | ||||
# The naming drift of ElementTree is fun! | # The naming drift of ElementTree is fun! | ||||
try: | try: | ||||
import xml.etree.cElementTree.ElementTree as ElementTree | import xml.etree.cElementTree.ElementTree as ElementTree | ||||
import xml.etree.cElementTree.XMLParser as XMLParser | import xml.etree.cElementTree.XMLParser as XMLParser | ||||
return self.parents[None] | return self.parents[None] | ||||
def getcommit(self, rev): | def getcommit(self, rev): | ||||
elt = self.changes[rev] | elt = self.changes[rev] | ||||
date = util.strdate(elt.get('local_date'), '%a %b %d %H:%M:%S %Z %Y') | date = util.strdate(elt.get('local_date'), '%a %b %d %H:%M:%S %Z %Y') | ||||
desc = elt.findtext('name') + '\n' + elt.findtext('comment', '') | desc = elt.findtext('name') + '\n' + elt.findtext('comment', '') | ||||
# etree can return unicode objects for name, comment, and author, | # etree can return unicode objects for name, comment, and author, | ||||
# so recode() is used to ensure str objects are emitted. | # so recode() is used to ensure str objects are emitted. | ||||
newdateformat = '%Y-%m-%d %H:%M:%S %1%2' | |||||
return common.commit(author=self.recode(elt.get('author')), | return common.commit(author=self.recode(elt.get('author')), | ||||
date=util.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'), | date=dateutil.datestr(date, newdateformat), | ||||
desc=self.recode(desc).strip(), | desc=self.recode(desc).strip(), | ||||
parents=self.parents[rev]) | parents=self.parents[rev]) | ||||
def pull(self, rev): | def pull(self, rev): | ||||
output, status = self.run('pull', self.path, all=True, | output, status = self.run('pull', self.path, all=True, | ||||
match='hash %s' % rev, | match='hash %s' % rev, | ||||
no_test=True, no_posthook=True, | no_test=True, no_posthook=True, | ||||
external_merge='/bin/false', | external_merge='/bin/false', |
import tempfile | import tempfile | ||||
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
encoding, | encoding, | ||||
error, | error, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import common | from . import common | ||||
class gnuarch_source(common.converter_source, common.commandline): | class gnuarch_source(common.converter_source, common.commandline): | ||||
class gnuarch_rev(object): | class gnuarch_rev(object): | ||||
def __init__(self, rev): | def __init__(self, rev): | ||||
self.rev = rev | self.rev = rev | ||||
self.summary = '' | self.summary = '' | ||||
return path[2:] | return path[2:] | ||||
return path | return path | ||||
def _parsecatlog(self, data, rev): | def _parsecatlog(self, data, rev): | ||||
try: | try: | ||||
catlog = self.catlogparser.parsestr(data) | catlog = self.catlogparser.parsestr(data) | ||||
# Commit date | # Commit date | ||||
self.changes[rev].date = util.datestr( | self.changes[rev].date = dateutil.datestr( | ||||
util.strdate(catlog['Standard-date'], | dateutil.strdate(catlog['Standard-date'], | ||||
'%Y-%m-%d %H:%M:%S')) | '%Y-%m-%d %H:%M:%S')) | ||||
# Commit author | # Commit author | ||||
self.changes[rev].author = self.recode(catlog['Creator']) | self.changes[rev].author = self.recode(catlog['Creator']) | ||||
# Commit description | # Commit description | ||||
self.changes[rev].summary = '\n\n'.join((catlog['Summary'], | self.changes[rev].summary = '\n\n'.join((catlog['Summary'], | ||||
catlog.get_payload())) | catlog.get_payload())) |
hg, | hg, | ||||
lock as lockmod, | lock as lockmod, | ||||
merge as mergemod, | merge as mergemod, | ||||
node as nodemod, | node as nodemod, | ||||
phases, | phases, | ||||
scmutil, | scmutil, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
stringio = util.stringio | stringio = util.stringio | ||||
from . import common | from . import common | ||||
mapfile = common.mapfile | mapfile = common.mapfile | ||||
NoRepo = common.NoRepo | NoRepo = common.NoRepo | ||||
sha1re = re.compile(r'\b[0-9a-f]{12,40}\b') | sha1re = re.compile(r'\b[0-9a-f]{12,40}\b') | ||||
def getcommit(self, rev): | def getcommit(self, rev): | ||||
ctx = self._changectx(rev) | ctx = self._changectx(rev) | ||||
_parents = self._parents(ctx) | _parents = self._parents(ctx) | ||||
parents = [p.hex() for p in _parents] | parents = [p.hex() for p in _parents] | ||||
optparents = [p.hex() for p in ctx.parents() if p and p not in _parents] | optparents = [p.hex() for p in ctx.parents() if p and p not in _parents] | ||||
crev = rev | crev = rev | ||||
return common.commit(author=ctx.user(), | return common.commit(author=ctx.user(), | ||||
date=util.datestr(ctx.date(), | date=dateutil.datestr(ctx.date(), | ||||
'%Y-%m-%d %H:%M:%S %1%2'), | '%Y-%m-%d %H:%M:%S %1%2'), | ||||
desc=ctx.description(), | desc=ctx.description(), | ||||
rev=crev, | rev=crev, | ||||
parents=parents, | parents=parents, | ||||
optparents=optparents, | optparents=optparents, | ||||
branch=ctx.branch(), | branch=ctx.branch(), | ||||
extra=ctx.extra(), | extra=ctx.extra(), | ||||
sortkey=ctx.rev(), | sortkey=ctx.rev(), |
import os | import os | ||||
import re | import re | ||||
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
error, | error, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import common | from . import common | ||||
class monotone_source(common.converter_source, common.commandline): | class monotone_source(common.converter_source, common.commandline): | ||||
def __init__(self, ui, repotype, path=None, revs=None): | def __init__(self, ui, repotype, path=None, revs=None): | ||||
common.converter_source.__init__(self, ui, repotype, path, revs) | common.converter_source.__init__(self, ui, repotype, path, revs) | ||||
if revs and len(revs) > 1: | if revs and len(revs) > 1: | ||||
raise error.Abort(_('monotone source does not support specifying ' | raise error.Abort(_('monotone source does not support specifying ' | ||||
node, attr = self.files.get(name, (None, "")) | node, attr = self.files.get(name, (None, "")) | ||||
return data, attr | return data, attr | ||||
def getcommit(self, rev): | def getcommit(self, rev): | ||||
extra = {} | extra = {} | ||||
certs = self.mtngetcerts(rev) | certs = self.mtngetcerts(rev) | ||||
if certs.get('suspend') == certs["branch"]: | if certs.get('suspend') == certs["branch"]: | ||||
extra['close'] = 1 | extra['close'] = 1 | ||||
dateformat = "%Y-%m-%dT%H:%M:%S" | |||||
return common.commit( | return common.commit( | ||||
author=certs["author"], | author=certs["author"], | ||||
date=util.datestr(util.strdate(certs["date"], "%Y-%m-%dT%H:%M:%S")), | date=dateutil.datestr(util.strdate(certs["date"], dateformat)), | ||||
desc=certs["changelog"], | desc=certs["changelog"], | ||||
rev=rev, | rev=rev, | ||||
parents=self.mtnrun("parents", rev).splitlines(), | parents=self.mtnrun("parents", rev).splitlines(), | ||||
branch=certs["branch"], | branch=certs["branch"], | ||||
extra=extra) | extra=extra) | ||||
def gettags(self): | def gettags(self): | ||||
tags = {} | tags = {} |
# Perforce source for convert extension. | # Perforce source for convert extension. | ||||
# | # | ||||
# Copyright 2009, Frank Kingswood <frank@kingswood-consulting.co.uk> | # Copyright 2009, Frank Kingswood <frank@kingswood-consulting.co.uk> | ||||
# | # | ||||
# This software may be used and distributed according to the terms of the | # This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | # GNU General Public License version 2 or any later version. | ||||
from __future__ import absolute_import | from __future__ import absolute_import | ||||
import marshal | import marshal | ||||
import re | import re | ||||
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
error, | error, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import common | from . import common | ||||
def loaditer(f): | def loaditer(f): | ||||
"Yield the dictionary objects generated by p4" | "Yield the dictionary objects generated by p4" | ||||
try: | try: | ||||
while True: | while True: | ||||
d = marshal.load(f) | d = marshal.load(f) | ||||
`p4 describe` output | `p4 describe` output | ||||
""" | """ | ||||
desc = self.recode(obj.get("desc", "")) | desc = self.recode(obj.get("desc", "")) | ||||
date = (int(obj["time"]), 0) # timezone not set | date = (int(obj["time"]), 0) # timezone not set | ||||
if parents is None: | if parents is None: | ||||
parents = [] | parents = [] | ||||
return common.commit(author=self.recode(obj["user"]), | return common.commit(author=self.recode(obj["user"]), | ||||
date=util.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'), | date=dateutil.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'), | ||||
parents=parents, desc=desc, branch=None, rev=obj['change'], | parents=parents, desc=desc, branch=None, rev=obj['change'], | ||||
extra={"p4": obj['change'], "convert_revision": obj['change']}) | extra={"p4": obj['change'], "convert_revision": obj['change']}) | ||||
def _fetch_revision(self, rev): | def _fetch_revision(self, rev): | ||||
"""Return an output of `p4 describe` including author, commit date as | """Return an output of `p4 describe` including author, commit date as | ||||
a dictionary.""" | a dictionary.""" | ||||
cmd = "p4 -G describe -s %s" % rev | cmd = "p4 -G describe -s %s" % rev | ||||
stdout = util.popen(cmd, mode='rb') | stdout = util.popen(cmd, mode='rb') |
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
encoding, | encoding, | ||||
error, | error, | ||||
pycompat, | pycompat, | ||||
util, | util, | ||||
vfs as vfsmod, | vfs as vfsmod, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import common | from . import common | ||||
pickle = util.pickle | pickle = util.pickle | ||||
stringio = util.stringio | stringio = util.stringio | ||||
propertycache = util.propertycache | propertycache = util.propertycache | ||||
urlerr = util.urlerr | urlerr = util.urlerr | ||||
urlreq = util.urlreq | urlreq = util.urlreq | ||||
try: | try: | ||||
branch = self.module.split("/")[-1] | branch = self.module.split("/")[-1] | ||||
if branch == self.trunkname: | if branch == self.trunkname: | ||||
branch = None | branch = None | ||||
except IndexError: | except IndexError: | ||||
branch = None | branch = None | ||||
cset = commit(author=author, | cset = commit(author=author, | ||||
date=util.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'), | date=dateutil.datestr(date, '%Y-%m-%d %H:%M:%S %1%2'), | ||||
desc=log, | desc=log, | ||||
parents=parents, | parents=parents, | ||||
branch=branch, | branch=branch, | ||||
rev=rev) | rev=rev) | ||||
self.commits[rev] = cset | self.commits[rev] = cset | ||||
# The parents list is *shared* among self.paths and the | # The parents list is *shared* among self.paths and the | ||||
# commit object. Both will be updated below. | # commit object. Both will be updated below. |
patch, | patch, | ||||
pathutil, | pathutil, | ||||
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
scmutil, | scmutil, | ||||
templatefilters, | templatefilters, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
cmdtable = {} | cmdtable = {} | ||||
command = registrar.command(cmdtable) | command = registrar.command(cmdtable) | ||||
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | ||||
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | ||||
# be specifying the version(s) of Mercurial they are tested with, or | # be specifying the version(s) of Mercurial they are tested with, or | ||||
# leave the attribute unspecified. | # leave the attribute unspecified. | ||||
testedwith = 'ships-with-hg-core' | testedwith = 'ships-with-hg-core' | ||||
configitem('keywordset', 'svn', | configitem('keywordset', 'svn', | ||||
default=False, | default=False, | ||||
) | ) | ||||
# date like in cvs' $Date | # date like in cvs' $Date | ||||
@templatefilter('utcdate') | @templatefilter('utcdate') | ||||
def utcdate(text): | def utcdate(text): | ||||
'''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13". | '''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13". | ||||
''' | ''' | ||||
return util.datestr((util.parsedate(text)[0], 0), '%Y/%m/%d %H:%M:%S') | return dateutil.datestr((util.parsedate(text)[0], 0), '%Y/%m/%d %H:%M:%S') | ||||
# date like in svn's $Date | # date like in svn's $Date | ||||
@templatefilter('svnisodate') | @templatefilter('svnisodate') | ||||
def svnisodate(text): | def svnisodate(text): | ||||
'''Date. Returns a date in this format: "2009-08-18 13:00:13 | '''Date. Returns a date in this format: "2009-08-18 13:00:13 | ||||
+0200 (Tue, 18 Aug 2009)". | +0200 (Tue, 18 Aug 2009)". | ||||
''' | ''' | ||||
return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') | return dateutil.datestr(text, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') | ||||
# date like in svn's $Id | # date like in svn's $Id | ||||
@templatefilter('svnutcdate') | @templatefilter('svnutcdate') | ||||
def svnutcdate(text): | def svnutcdate(text): | ||||
'''Date. Returns a UTC-date in this format: "2009-08-18 | '''Date. Returns a UTC-date in this format: "2009-08-18 | ||||
11:00:13Z". | 11:00:13Z". | ||||
''' | ''' | ||||
return util.datestr((util.parsedate(text)[0], 0), '%Y-%m-%d %H:%M:%SZ') | return dateutil.datestr((util.parsedate(text)[0], 0), '%Y-%m-%d %H:%M:%SZ') | ||||
# make keyword tools accessible | # make keyword tools accessible | ||||
kwtools = {'hgcmd': ''} | kwtools = {'hgcmd': ''} | ||||
def _defaultkwmaps(ui): | def _defaultkwmaps(ui): | ||||
'''Returns default keywordmaps according to keywordset configuration.''' | '''Returns default keywordmaps according to keywordset configuration.''' | ||||
templates = { | templates = { | ||||
'Revision': '{node|short}', | 'Revision': '{node|short}', |
from mercurial import ( | from mercurial import ( | ||||
cmdutil, | cmdutil, | ||||
error, | error, | ||||
mail, | mail, | ||||
patch, | patch, | ||||
registrar, | registrar, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | ||||
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | ||||
# be specifying the version(s) of Mercurial they are tested with, or | # be specifying the version(s) of Mercurial they are tested with, or | ||||
# leave the attribute unspecified. | # leave the attribute unspecified. | ||||
testedwith = 'ships-with-hg-core' | testedwith = 'ships-with-hg-core' | ||||
configtable = {} | configtable = {} | ||||
headers = msg.items() | headers = msg.items() | ||||
payload = msg.get_payload() | payload = msg.get_payload() | ||||
# for notification prefer readability over data precision | # for notification prefer readability over data precision | ||||
msg = mail.mimeencode(self.ui, payload, self.charsets, self.test) | msg = mail.mimeencode(self.ui, payload, self.charsets, self.test) | ||||
# reinstate custom headers | # reinstate custom headers | ||||
for k, v in headers: | for k, v in headers: | ||||
msg[k] = v | msg[k] = v | ||||
msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2") | msg['Date'] = dateutil.datestr(format="%a, %d %b %Y %H:%M:%S %1%2") | ||||
# try to make subject line exist and be useful | # try to make subject line exist and be useful | ||||
if not subject: | if not subject: | ||||
if count > 1: | if count > 1: | ||||
subject = _('%s: %d new changesets') % (self.root, count) | subject = _('%s: %d new changesets') % (self.root, count) | ||||
else: | else: | ||||
s = ctx.description().lstrip().split('\n', 1)[0].rstrip() | s = ctx.description().lstrip().split('\n', 1)[0].rstrip() | ||||
subject = '%s: %s' % (self.root, s) | subject = '%s: %s' % (self.root, s) |
rewriteutil, | rewriteutil, | ||||
scmutil, | scmutil, | ||||
smartset, | smartset, | ||||
templatekw, | templatekw, | ||||
templater, | templater, | ||||
util, | util, | ||||
vfs as vfsmod, | vfs as vfsmod, | ||||
) | ) | ||||
from .utils import dateutil | |||||
stringio = util.stringio | stringio = util.stringio | ||||
# templates of common command options | # templates of common command options | ||||
dryrunopts = [ | dryrunopts = [ | ||||
('n', 'dry-run', None, | ('n', 'dry-run', None, | ||||
_('do not perform actions, just print output')), | _('do not perform actions, just print output')), | ||||
] | ] | ||||
if parents: | if parents: | ||||
prev = parents[0] | prev = parents[0] | ||||
else: | else: | ||||
prev = nullid | prev = nullid | ||||
write("# HG changeset patch\n") | write("# HG changeset patch\n") | ||||
write("# User %s\n" % ctx.user()) | write("# User %s\n" % ctx.user()) | ||||
write("# Date %d %d\n" % ctx.date()) | write("# Date %d %d\n" % ctx.date()) | ||||
write("# %s\n" % util.datestr(ctx.date())) | write("# %s\n" % dateutil.datestr(ctx.date())) | ||||
if branch and branch != 'default': | if branch and branch != 'default': | ||||
write("# Branch %s\n" % branch) | write("# Branch %s\n" % branch) | ||||
write("# Node ID %s\n" % hex(node)) | write("# Node ID %s\n" % hex(node)) | ||||
write("# Parent %s\n" % hex(prev)) | write("# Parent %s\n" % hex(prev)) | ||||
if len(parents) > 1: | if len(parents) > 1: | ||||
write("# Parent %s\n" % hex(parents[1])) | write("# Parent %s\n" % hex(parents[1])) | ||||
for headerid in extraexport: | for headerid in extraexport: | ||||
if self.ui.debugflag and rev is not None: | if self.ui.debugflag and rev is not None: | ||||
mnode = ctx.manifestnode() | mnode = ctx.manifestnode() | ||||
mrev = self.repo.manifestlog._revlog.rev(mnode) | mrev = self.repo.manifestlog._revlog.rev(mnode) | ||||
self.ui.write(columns['manifest'] | self.ui.write(columns['manifest'] | ||||
% scmutil.formatrevnode(self.ui, mrev, mnode), | % scmutil.formatrevnode(self.ui, mrev, mnode), | ||||
label='ui.debug log.manifest') | label='ui.debug log.manifest') | ||||
self.ui.write(columns['user'] % ctx.user(), label='log.user') | self.ui.write(columns['user'] % ctx.user(), label='log.user') | ||||
self.ui.write(columns['date'] % util.datestr(ctx.date()), | self.ui.write(columns['date'] % dateutil.datestr(ctx.date()), | ||||
label='log.date') | label='log.date') | ||||
if ctx.isunstable(): | if ctx.isunstable(): | ||||
instabilities = ctx.instabilities() | instabilities = ctx.instabilities() | ||||
self.ui.write(columns['instability'] % ', '.join(instabilities), | self.ui.write(columns['instability'] % ', '.join(instabilities), | ||||
label='log.instability') | label='log.instability') | ||||
elif ctx.obsolete(): | elif ctx.obsolete(): | ||||
d = ctx.date() | d = ctx.date() | ||||
if df(d[0]): | if df(d[0]): | ||||
results[ctx.rev()] = d | results[ctx.rev()] = d | ||||
for ctx in walkchangerevs(repo, m, {'rev': None}, prep): | for ctx in walkchangerevs(repo, m, {'rev': None}, prep): | ||||
rev = ctx.rev() | rev = ctx.rev() | ||||
if rev in results: | if rev in results: | ||||
ui.status(_("found revision %s from %s\n") % | ui.status(_("found revision %s from %s\n") % | ||||
(rev, util.datestr(results[rev]))) | (rev, dateutil.datestr(results[rev]))) | ||||
return '%d' % rev | return '%d' % rev | ||||
raise error.Abort(_("revision matching date not found")) | raise error.Abort(_("revision matching date not found")) | ||||
def increasingwindows(windowsize=8, sizelimit=512): | def increasingwindows(windowsize=8, sizelimit=512): | ||||
while True: | while True: | ||||
yield windowsize | yield windowsize | ||||
if windowsize < sizelimit: | if windowsize < sizelimit: |
if rev: | if rev: | ||||
repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn') | repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn') | ||||
ctx = scmutil.revsingle(repo, rev) | ctx = scmutil.revsingle(repo, rev) | ||||
rootfm = ui.formatter('annotate', opts) | rootfm = ui.formatter('annotate', opts) | ||||
if ui.quiet: | if ui.quiet: | ||||
datefunc = util.shortdate | datefunc = util.shortdate | ||||
else: | else: | ||||
datefunc = util.datestr | datefunc = dateutil.datestr | ||||
if ctx.rev() is None: | if ctx.rev() is None: | ||||
def hexfn(node): | def hexfn(node): | ||||
if node is None: | if node is None: | ||||
return None | return None | ||||
else: | else: | ||||
return rootfm.hexfunc(node) | return rootfm.hexfunc(node) | ||||
if opts.get('changeset'): | if opts.get('changeset'): | ||||
# omit "+" suffix which is appended to node hex | # omit "+" suffix which is appended to node hex |
streamclone, | streamclone, | ||||
templater, | templater, | ||||
treediscovery, | treediscovery, | ||||
upgrade, | upgrade, | ||||
url as urlmod, | url as urlmod, | ||||
util, | util, | ||||
vfs as vfsmod, | vfs as vfsmod, | ||||
) | ) | ||||
from .utils import dateutil | |||||
release = lockmod.release | release = lockmod.release | ||||
command = registrar.command() | command = registrar.command() | ||||
@command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True) | @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True) | ||||
def debugancestor(ui, repo, *args): | def debugancestor(ui, repo, *args): | ||||
"""find the ancestor revision of two revisions in a given index""" | """find the ancestor revision of two revisions in a given index""" | ||||
norepo=True, optionalrepo=True) | norepo=True, optionalrepo=True) | ||||
def debugdate(ui, date, range=None, **opts): | def debugdate(ui, date, range=None, **opts): | ||||
"""parse and display a date""" | """parse and display a date""" | ||||
if opts[r"extended"]: | if opts[r"extended"]: | ||||
d = util.parsedate(date, util.extendeddateformats) | d = util.parsedate(date, util.extendeddateformats) | ||||
else: | else: | ||||
d = util.parsedate(date) | d = util.parsedate(date) | ||||
ui.write(("internal: %s %s\n") % d) | ui.write(("internal: %s %s\n") % d) | ||||
ui.write(("standard: %s\n") % util.datestr(d)) | ui.write(("standard: %s\n") % dateutil.datestr(d)) | ||||
if range: | if range: | ||||
m = util.matchdate(range) | m = util.matchdate(range) | ||||
ui.write(("match: %s\n") % m(d[0])) | ui.write(("match: %s\n") % m(d[0])) | ||||
@command('debugdeltachain', | @command('debugdeltachain', | ||||
cmdutil.debugrevlogopts + cmdutil.formatteropts, | cmdutil.debugrevlogopts + cmdutil.formatteropts, | ||||
_('-c|-m|FILE'), | _('-c|-m|FILE'), | ||||
optionalrepo=True) | optionalrepo=True) |
from . import ( | from . import ( | ||||
error, | error, | ||||
pycompat, | pycompat, | ||||
templatefilters, | templatefilters, | ||||
templatekw, | templatekw, | ||||
templater, | templater, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
pickle = util.pickle | pickle = util.pickle | ||||
class _nullconverter(object): | class _nullconverter(object): | ||||
'''convert non-primitive data types to be processed by formatter''' | '''convert non-primitive data types to be processed by formatter''' | ||||
# set to True if context object should be stored as item | # set to True if context object should be stored as item | ||||
storecontext = False | storecontext = False | ||||
class _plainconverter(object): | class _plainconverter(object): | ||||
'''convert non-primitive data types to text''' | '''convert non-primitive data types to text''' | ||||
storecontext = False | storecontext = False | ||||
@staticmethod | @staticmethod | ||||
def formatdate(date, fmt): | def formatdate(date, fmt): | ||||
'''stringify date tuple in the given format''' | '''stringify date tuple in the given format''' | ||||
return util.datestr(date, fmt) | return dateutil.datestr(date, fmt) | ||||
@staticmethod | @staticmethod | ||||
def formatdict(data, key, value, fmt, sep): | def formatdict(data, key, value, fmt, sep): | ||||
'''stringify key-value pairs separated by sep''' | '''stringify key-value pairs separated by sep''' | ||||
return sep.join(fmt % (k, v) for k, v in _iteritems(data)) | return sep.join(fmt % (k, v) for k, v in _iteritems(data)) | ||||
@staticmethod | @staticmethod | ||||
def formatlist(data, name, fmt, sep): | def formatlist(data, name, fmt, sep): | ||||
'''stringify iterable separated by sep''' | '''stringify iterable separated by sep''' | ||||
return sep.join(fmt % e for e in data) | return sep.join(fmt % e for e in data) |
from .i18n import _ | from .i18n import _ | ||||
from . import ( | from . import ( | ||||
error, | error, | ||||
policy, | policy, | ||||
pycompat, | pycompat, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
bdiff = policy.importmod(r'bdiff') | bdiff = policy.importmod(r'bdiff') | ||||
mpatch = policy.importmod(r'mpatch') | mpatch = policy.importmod(r'mpatch') | ||||
blocks = bdiff.blocks | blocks = bdiff.blocks | ||||
fixws = bdiff.fixws | fixws = bdiff.fixws | ||||
patches = mpatch.patches | patches = mpatch.patches | ||||
patchedsize = mpatch.patchedsize | patchedsize = mpatch.patchedsize | ||||
return sentinel | return sentinel | ||||
if opts.noprefix: | if opts.noprefix: | ||||
aprefix = bprefix = '' | aprefix = bprefix = '' | ||||
else: | else: | ||||
aprefix = 'a/' | aprefix = 'a/' | ||||
bprefix = 'b/' | bprefix = 'b/' | ||||
epoch = util.datestr((0, 0)) | epoch = dateutil.datestr((0, 0)) | ||||
fn1 = util.pconvert(fn1) | fn1 = util.pconvert(fn1) | ||||
fn2 = util.pconvert(fn2) | fn2 = util.pconvert(fn2) | ||||
def checknonewline(lines): | def checknonewline(lines): | ||||
for text in lines: | for text in lines: | ||||
if text[-1:] != '\n': | if text[-1:] != '\n': | ||||
text += "\n\ No newline at end of file\n" | text += "\n\ No newline at end of file\n" |
import re | import re | ||||
from .i18n import _ | from .i18n import _ | ||||
from . import ( | from . import ( | ||||
node as nodemod, | node as nodemod, | ||||
phases, | phases, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
class marker(object): | class marker(object): | ||||
"""Wrap obsolete marker raw data""" | """Wrap obsolete marker raw data""" | ||||
def __init__(self, repo, data): | def __init__(self, repo, data): | ||||
# the repo argument will be used to create changectx in later version | # the repo argument will be used to create changectx in later version | ||||
self._repo = repo | self._repo = repo | ||||
self._data = data | self._data = data | ||||
# Date | # Date | ||||
dates = markersdates(markers) | dates = markersdates(markers) | ||||
if dates and verbose: | if dates and verbose: | ||||
min_date = min(dates) | min_date = min(dates) | ||||
max_date = max(dates) | max_date = max(dates) | ||||
if min_date == max_date: | if min_date == max_date: | ||||
fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2') | fmtmin_date = dateutil.datestr(min_date, '%Y-%m-%d %H:%M %1%2') | ||||
line.append(" (at %s)" % fmtmin_date) | line.append(" (at %s)" % fmtmin_date) | ||||
else: | else: | ||||
fmtmin_date = util.datestr(min_date, '%Y-%m-%d %H:%M %1%2') | fmtmin_date = dateutil.datestr(min_date, '%Y-%m-%d %H:%M %1%2') | ||||
fmtmax_date = util.datestr(max_date, '%Y-%m-%d %H:%M %1%2') | fmtmax_date = dateutil.datestr(max_date, '%Y-%m-%d %H:%M %1%2') | ||||
line.append(" (between %s and %s)" % (fmtmin_date, fmtmax_date)) | line.append(" (between %s and %s)" % (fmtmin_date, fmtmax_date)) | ||||
return "".join(line) | return "".join(line) | ||||
filteredmsgtable = { | filteredmsgtable = { | ||||
"pruned": _("hidden revision '%s' is pruned"), | "pruned": _("hidden revision '%s' is pruned"), | ||||
"diverged": _("hidden revision '%s' has diverged"), | "diverged": _("hidden revision '%s' has diverged"), |
pathutil, | pathutil, | ||||
policy, | policy, | ||||
pycompat, | pycompat, | ||||
scmutil, | scmutil, | ||||
similar, | similar, | ||||
util, | util, | ||||
vfs as vfsmod, | vfs as vfsmod, | ||||
) | ) | ||||
from .utils import dateutil | |||||
diffhelpers = policy.importmod(r'diffhelpers') | diffhelpers = policy.importmod(r'diffhelpers') | ||||
stringio = util.stringio | stringio = util.stringio | ||||
gitre = re.compile(br'diff --git a/(.*) b/(.*)') | gitre = re.compile(br'diff --git a/(.*) b/(.*)') | ||||
tabsplitter = re.compile(br'(\t+|[^\t]+)') | tabsplitter = re.compile(br'(\t+|[^\t]+)') | ||||
_nonwordre = re.compile(br'([^a-zA-Z0-9_\x80-\xff])') | _nonwordre = re.compile(br'([^a-zA-Z0-9_\x80-\xff])') | ||||
def diffline(f, revs): | def diffline(f, revs): | ||||
revinfo = ' '.join(["-r %s" % rev for rev in revs]) | revinfo = ' '.join(["-r %s" % rev for rev in revs]) | ||||
return 'diff %s %s' % (revinfo, f) | return 'diff %s %s' % (revinfo, f) | ||||
def isempty(fctx): | def isempty(fctx): | ||||
return fctx is None or fctx.size() == 0 | return fctx is None or fctx.size() == 0 | ||||
date1 = util.datestr(ctx1.date()) | date1 = dateutil.datestr(ctx1.date()) | ||||
date2 = util.datestr(ctx2.date()) | date2 = dateutil.datestr(ctx2.date()) | ||||
gitmode = {'l': '120000', 'x': '100755', '': '100644'} | gitmode = {'l': '120000', 'x': '100755', '': '100644'} | ||||
if relroot != '' and (repo.ui.configbool('devel', 'all-warnings') | if relroot != '' and (repo.ui.configbool('devel', 'all-warnings') | ||||
or repo.ui.configbool('devel', 'check-relroot')): | or repo.ui.configbool('devel', 'check-relroot')): | ||||
for f in modified + added + removed + list(copy) + list(copy.values()): | for f in modified + added + removed + list(copy) + list(copy.values()): | ||||
if f is not None and not f.startswith(relroot): | if f is not None and not f.startswith(relroot): | ||||
raise AssertionError( | raise AssertionError( |
node, | node, | ||||
pathutil, | pathutil, | ||||
phases, | phases, | ||||
pycompat, | pycompat, | ||||
scmutil, | scmutil, | ||||
util, | util, | ||||
vfs as vfsmod, | vfs as vfsmod, | ||||
) | ) | ||||
from .utils import dateutil | |||||
hg = None | hg = None | ||||
propertycache = util.propertycache | propertycache = util.propertycache | ||||
nullstate = ('', '', 'empty') | nullstate = ('', '', 'empty') | ||||
def _expandedabspath(path): | def _expandedabspath(path): | ||||
''' | ''' | ||||
raise error.Abort(_("subrepo %s is missing") % self._relpath) | raise error.Abort(_("subrepo %s is missing") % self._relpath) | ||||
cmd = ['commit', '-a', '-m', text] | cmd = ['commit', '-a', '-m', text] | ||||
env = encoding.environ.copy() | env = encoding.environ.copy() | ||||
if user: | if user: | ||||
cmd += ['--author', user] | cmd += ['--author', user] | ||||
if date: | if date: | ||||
# git's date parser silently ignores when seconds < 1e9 | # git's date parser silently ignores when seconds < 1e9 | ||||
# convert to ISO8601 | # convert to ISO8601 | ||||
env['GIT_AUTHOR_DATE'] = util.datestr(date, | env['GIT_AUTHOR_DATE'] = dateutil.datestr(date, | ||||
'%Y-%m-%dT%H:%M:%S %1%2') | '%Y-%m-%dT%H:%M:%S %1%2') | ||||
self._gitcommand(cmd, env=env) | self._gitcommand(cmd, env=env) | ||||
# make sure commit works otherwise HEAD might not exist under certain | # make sure commit works otherwise HEAD might not exist under certain | ||||
# circumstances | # circumstances | ||||
return self._gitstate() | return self._gitstate() | ||||
@annotatesubrepoerror | @annotatesubrepoerror | ||||
def merge(self, state): | def merge(self, state): |
hbisect, | hbisect, | ||||
node, | node, | ||||
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
templatekw, | templatekw, | ||||
url, | url, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
urlerr = util.urlerr | urlerr = util.urlerr | ||||
urlreq = util.urlreq | urlreq = util.urlreq | ||||
if pycompat.ispy3: | if pycompat.ispy3: | ||||
long = int | long = int | ||||
# filters are callables like: | # filters are callables like: | ||||
""" | """ | ||||
return "%d %d" % text | return "%d %d" % text | ||||
@templatefilter('isodate') | @templatefilter('isodate') | ||||
def isodate(text): | def isodate(text): | ||||
"""Date. Returns the date in ISO 8601 format: "2009-08-18 13:00 | """Date. Returns the date in ISO 8601 format: "2009-08-18 13:00 | ||||
+0200". | +0200". | ||||
""" | """ | ||||
return util.datestr(text, '%Y-%m-%d %H:%M %1%2') | return dateutil.datestr(text, '%Y-%m-%d %H:%M %1%2') | ||||
@templatefilter('isodatesec') | @templatefilter('isodatesec') | ||||
def isodatesec(text): | def isodatesec(text): | ||||
"""Date. Returns the date in ISO 8601 format, including | """Date. Returns the date in ISO 8601 format, including | ||||
seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date | seconds: "2009-08-18 13:00:13 +0200". See also the rfc3339date | ||||
filter. | filter. | ||||
""" | """ | ||||
return util.datestr(text, '%Y-%m-%d %H:%M:%S %1%2') | return dateutil.datestr(text, '%Y-%m-%d %H:%M:%S %1%2') | ||||
def indent(text, prefix): | def indent(text, prefix): | ||||
'''indent each non-empty line of text after first with prefix.''' | '''indent each non-empty line of text after first with prefix.''' | ||||
lines = text.splitlines() | lines = text.splitlines() | ||||
num_lines = len(lines) | num_lines = len(lines) | ||||
endswithnewline = text[-1:] == '\n' | endswithnewline = text[-1:] == '\n' | ||||
def indenter(): | def indenter(): | ||||
for i in xrange(num_lines): | for i in xrange(num_lines): | ||||
""" | """ | ||||
return urlreq.quote(text, safe='/@').replace('/', '%252F') | return urlreq.quote(text, safe='/@').replace('/', '%252F') | ||||
@templatefilter('rfc3339date') | @templatefilter('rfc3339date') | ||||
def rfc3339date(text): | def rfc3339date(text): | ||||
"""Date. Returns a date using the Internet date format | """Date. Returns a date using the Internet date format | ||||
specified in RFC 3339: "2009-08-18T13:00:13+02:00". | specified in RFC 3339: "2009-08-18T13:00:13+02:00". | ||||
""" | """ | ||||
return util.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2") | return dateutil.datestr(text, "%Y-%m-%dT%H:%M:%S%1:%2") | ||||
@templatefilter('rfc822date') | @templatefilter('rfc822date') | ||||
def rfc822date(text): | def rfc822date(text): | ||||
"""Date. Returns a date using the same format used in email | """Date. Returns a date using the same format used in email | ||||
headers: "Tue, 18 Aug 2009 13:00:13 +0200". | headers: "Tue, 18 Aug 2009 13:00:13 +0200". | ||||
""" | """ | ||||
return util.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2") | return dateutil.datestr(text, "%a, %d %b %Y %H:%M:%S %1%2") | ||||
@templatefilter('short') | @templatefilter('short') | ||||
def short(text): | def short(text): | ||||
"""Changeset hash. Returns the short form of a changeset hash, | """Changeset hash. Returns the short form of a changeset hash, | ||||
i.e. a 12 hexadecimal digit string. | i.e. a 12 hexadecimal digit string. | ||||
""" | """ | ||||
return text[:12] | return text[:12] | ||||
raise error.ParseError(_("date expects one or two arguments")) | raise error.ParseError(_("date expects one or two arguments")) | ||||
date = evalfuncarg(context, mapping, args[0]) | date = evalfuncarg(context, mapping, args[0]) | ||||
fmt = None | fmt = None | ||||
if len(args) == 2: | if len(args) == 2: | ||||
fmt = evalstring(context, mapping, args[1]) | fmt = evalstring(context, mapping, args[1]) | ||||
try: | try: | ||||
if fmt is None: | if fmt is None: | ||||
return util.datestr(date) | return dateutil.datestr(date) | ||||
else: | else: | ||||
return util.datestr(date, fmt) | return dateutil.datestr(date, fmt) | ||||
except (TypeError, ValueError): | except (TypeError, ValueError): | ||||
# i18n: "date" is a keyword | # i18n: "date" is a keyword | ||||
raise error.ParseError(_("date expects a date information")) | raise error.ParseError(_("date expects a date information")) | ||||
@templatefunc('dict([[key=]value...])', argspec='*args **kwargs') | @templatefunc('dict([[key=]value...])', argspec='*args **kwargs') | ||||
def dict_(context, mapping, args): | def dict_(context, mapping, args): | ||||
"""Construct a dict from key-value pairs. A key may be omitted if | """Construct a dict from key-value pairs. A key may be omitted if | ||||
a value expression can provide an unambiguous name.""" | a value expression can provide an unambiguous name.""" |
nbytes = min(limit, size) | nbytes = min(limit, size) | ||||
s = nbytes and f.read(nbytes) | s = nbytes and f.read(nbytes) | ||||
if not s: | if not s: | ||||
break | break | ||||
if limit: | if limit: | ||||
limit -= len(s) | limit -= len(s) | ||||
yield s | yield s | ||||
def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'): | |||||
"""represent a (unixtime, offset) tuple as a localized time. | |||||
unixtime is seconds since the epoch, and offset is the time zone's | |||||
number of seconds away from UTC. | |||||
>>> datestr((0, 0)) | |||||
'Thu Jan 01 00:00:00 1970 +0000' | |||||
>>> datestr((42, 0)) | |||||
'Thu Jan 01 00:00:42 1970 +0000' | |||||
>>> datestr((-42, 0)) | |||||
'Wed Dec 31 23:59:18 1969 +0000' | |||||
>>> datestr((0x7fffffff, 0)) | |||||
'Tue Jan 19 03:14:07 2038 +0000' | |||||
>>> datestr((-0x80000000, 0)) | |||||
'Fri Dec 13 20:45:52 1901 +0000' | |||||
""" | |||||
t, tz = date or dateutil.makedate() | |||||
if "%1" in format or "%2" in format or "%z" in format: | |||||
sign = (tz > 0) and "-" or "+" | |||||
minutes = abs(tz) // 60 | |||||
q, r = divmod(minutes, 60) | |||||
format = format.replace("%z", "%1%2") | |||||
format = format.replace("%1", "%c%02d" % (sign, q)) | |||||
format = format.replace("%2", "%02d" % r) | |||||
d = t - tz | |||||
if d > 0x7fffffff: | |||||
d = 0x7fffffff | |||||
elif d < -0x80000000: | |||||
d = -0x80000000 | |||||
# Never use time.gmtime() and datetime.datetime.fromtimestamp() | |||||
# because they use the gmtime() system call which is buggy on Windows | |||||
# for negative values. | |||||
t = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=d) | |||||
s = encoding.strtolocal(t.strftime(encoding.strfromlocal(format))) | |||||
return s | |||||
def shortdate(date=None): | def shortdate(date=None): | ||||
"""turn (timestamp, tzoff) tuple into iso 8631 date.""" | """turn (timestamp, tzoff) tuple into iso 8631 date.""" | ||||
return datestr(date, format='%Y-%m-%d') | return dateutil.datestr(date, format='%Y-%m-%d') | ||||
def parsetimezone(s): | def parsetimezone(s): | ||||
"""find a trailing timezone, if any, in string, and return a | """find a trailing timezone, if any, in string, and return a | ||||
(offset, remainder) pair""" | (offset, remainder) pair""" | ||||
if s.endswith("GMT") or s.endswith("UTC"): | if s.endswith("GMT") or s.endswith("UTC"): | ||||
return 0, s[:-3].rstrip() | return 0, s[:-3].rstrip() | ||||
b = bias.get(part) | b = bias.get(part) | ||||
if b is None: | if b is None: | ||||
if part[0:1] in "HMS": | if part[0:1] in "HMS": | ||||
b = "00" | b = "00" | ||||
else: | else: | ||||
b = "0" | b = "0" | ||||
# this piece is for matching the generic end to today's date | # this piece is for matching the generic end to today's date | ||||
n = datestr(now, "%" + part[0:1]) | n = dateutil.datestr(now, "%" + part[0:1]) | ||||
defaults[part] = (b, n) | defaults[part] = (b, n) | ||||
for format in formats: | for format in formats: | ||||
try: | try: | ||||
when, offset = strdate(date, format, defaults) | when, offset = strdate(date, format, defaults) | ||||
except (ValueError, OverflowError): | except (ValueError, OverflowError): | ||||
pass | pass | ||||
extendeddateformats = dateutil.extendeddateformats | extendeddateformats = dateutil.extendeddateformats | ||||
def makedate(*args, **kwargs): | def makedate(*args, **kwargs): | ||||
msg = ("'util.makedate' is deprecated, " | msg = ("'util.makedate' is deprecated, " | ||||
"use 'utils.dateutil.makedate'") | "use 'utils.dateutil.makedate'") | ||||
nouideprecwarn(msg, "4.6") | nouideprecwarn(msg, "4.6") | ||||
return dateutil.makedate(*args, **kwargs) | return dateutil.makedate(*args, **kwargs) | ||||
def datestr(*args, **kwargs): | |||||
msg = ("'util.datestr' is deprecated, " | |||||
"use 'utils.dateutil.datestr'") | |||||
nouideprecwarn(msg, "4.6") | |||||
return dateutil.datestr(*args, **kwargs) | |||||
# util.py - Mercurial utility functions relative to dates | # util.py - Mercurial utility functions relative to dates | ||||
# | # | ||||
# Copyright 2018 Boris Feld <boris.feld@octobus.net> | # Copyright 2018 Boris Feld <boris.feld@octobus.net> | ||||
# | # | ||||
# This software may be used and distributed according to the terms of the | # This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | # GNU General Public License version 2 or any later version. | ||||
from __future__ import absolute_import, print_function | from __future__ import absolute_import, print_function | ||||
import datetime | import datetime | ||||
import time | import time | ||||
from ..i18n import _ | from ..i18n import _ | ||||
from .. import ( | from .. import ( | ||||
encoding, | |||||
error, | error, | ||||
) | ) | ||||
# used by parsedate | # used by parsedate | ||||
defaultdateformats = ( | defaultdateformats = ( | ||||
'%Y-%m-%dT%H:%M:%S', # the 'real' ISO8601 | '%Y-%m-%dT%H:%M:%S', # the 'real' ISO8601 | ||||
'%Y-%m-%dT%H:%M', # without seconds | '%Y-%m-%dT%H:%M', # without seconds | ||||
'%Y-%m-%dT%H%M%S', # another awful but legal variant without : | '%Y-%m-%dT%H%M%S', # another awful but legal variant without : | ||||
if timestamp < 0: | if timestamp < 0: | ||||
hint = _("check your clock") | hint = _("check your clock") | ||||
raise error.Abort(_("negative timestamp: %d") % timestamp, hint=hint) | raise error.Abort(_("negative timestamp: %d") % timestamp, hint=hint) | ||||
delta = (datetime.datetime.utcfromtimestamp(timestamp) - | delta = (datetime.datetime.utcfromtimestamp(timestamp) - | ||||
datetime.datetime.fromtimestamp(timestamp)) | datetime.datetime.fromtimestamp(timestamp)) | ||||
tz = delta.days * 86400 + delta.seconds | tz = delta.days * 86400 + delta.seconds | ||||
return timestamp, tz | return timestamp, tz | ||||
def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'): | |||||
"""represent a (unixtime, offset) tuple as a localized time. | |||||
unixtime is seconds since the epoch, and offset is the time zone's | |||||
number of seconds away from UTC. | |||||
>>> datestr((0, 0)) | |||||
'Thu Jan 01 00:00:00 1970 +0000' | |||||
>>> datestr((42, 0)) | |||||
'Thu Jan 01 00:00:42 1970 +0000' | |||||
>>> datestr((-42, 0)) | |||||
'Wed Dec 31 23:59:18 1969 +0000' | |||||
>>> datestr((0x7fffffff, 0)) | |||||
'Tue Jan 19 03:14:07 2038 +0000' | |||||
>>> datestr((-0x80000000, 0)) | |||||
'Fri Dec 13 20:45:52 1901 +0000' | |||||
""" | |||||
t, tz = date or makedate() | |||||
if "%1" in format or "%2" in format or "%z" in format: | |||||
sign = (tz > 0) and "-" or "+" | |||||
minutes = abs(tz) // 60 | |||||
q, r = divmod(minutes, 60) | |||||
format = format.replace("%z", "%1%2") | |||||
format = format.replace("%1", "%c%02d" % (sign, q)) | |||||
format = format.replace("%2", "%02d" % r) | |||||
d = t - tz | |||||
if d > 0x7fffffff: | |||||
d = 0x7fffffff | |||||
elif d < -0x80000000: | |||||
d = -0x80000000 | |||||
# Never use time.gmtime() and datetime.datetime.fromtimestamp() | |||||
# because they use the gmtime() system call which is buggy on Windows | |||||
# for negative values. | |||||
t = datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=d) | |||||
s = encoding.strtolocal(t.strftime(encoding.strfromlocal(format))) | |||||
return s |