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 | |||||