Extract makedate 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 makedate from util.py to utils/dateutil.py
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | contrib/synthrepo.py (4 lines) | |||
M | hgext/convert/common.py (2 lines) | |||
M | hgext/journal.py (3 lines) | |||
M | hgext/mq.py (3 lines) | |||
M | hgext/patchbomb.py (3 lines) | |||
M | hgext/shelve.py (4 lines) | |||
M | mercurial/changelog.py (3 lines) | |||
M | mercurial/commands.py (3 lines) | |||
M | mercurial/context.py (7 lines) | |||
M | mercurial/hgweb/hgwebdir_mod.py (5 lines) | |||
M | mercurial/obsolete.py (5 lines) | |||
M | mercurial/templater.py (3 lines) | |||
M | mercurial/util.py (29 lines) | |||
M | mercurial/utils/dateutil.py (22 lines) | |||
M | tests/test-journal.t (3 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 import ( | from mercurial import ( | ||||
context, | context, | ||||
error, | error, | ||||
hg, | hg, | ||||
patch, | patch, | ||||
registrar, | registrar, | ||||
scmutil, | scmutil, | ||||
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 = {} | ||||
def filectxfn(repo, memctx, path): | def filectxfn(repo, memctx, path): | ||||
return context.memfilectx(repo, memctx, path, files[path]) | return context.memfilectx(repo, memctx, path, files[path]) | ||||
ui.progress(_synthesizing, None) | ui.progress(_synthesizing, None) | ||||
message = 'synthesized wide repo with %d files' % (len(files),) | message = 'synthesized wide repo with %d files' % (len(files),) | ||||
mc = context.memctx(repo, [pctx.node(), nullid], message, | mc = context.memctx(repo, [pctx.node(), nullid], message, | ||||
files.iterkeys(), filectxfn, ui.username(), | files.iterkeys(), filectxfn, ui.username(), | ||||
'%d %d' % util.makedate()) | '%d %d' % dateutil.makedate()) | ||||
initnode = mc.commit() | initnode = mc.commit() | ||||
if ui.debugflag: | if ui.debugflag: | ||||
hexfn = hex | hexfn = hex | ||||
else: | else: | ||||
hexfn = short | hexfn = short | ||||
ui.status(_('added commit %s with %d files\n') | ui.status(_('added commit %s with %d files\n') | ||||
% (hexfn(initnode), len(files))) | % (hexfn(initnode), len(files))) | ||||
super(mapfile, self).__setitem__(key, value) | super(mapfile, self).__setitem__(key, value) | ||||
def close(self): | def close(self): | ||||
if self.fp: | if self.fp: | ||||
self.fp.close() | self.fp.close() | ||||
self.fp = None | self.fp = None | ||||
def makedatetimestamp(t): | def makedatetimestamp(t): | ||||
"""Like util.makedate() but for time t instead of current time""" | """Like dateutil.makedate() but for time t instead of current time""" | ||||
delta = (datetime.datetime.utcfromtimestamp(t) - | delta = (datetime.datetime.utcfromtimestamp(t) - | ||||
datetime.datetime.fromtimestamp(t)) | datetime.datetime.fromtimestamp(t)) | ||||
tz = delta.days * 86400 + delta.seconds | tz = delta.days * 86400 + delta.seconds | ||||
return t, tz | return t, tz |
hg, | hg, | ||||
localrepo, | localrepo, | ||||
lock, | lock, | ||||
node, | node, | ||||
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import share | from . import share | ||||
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 | ||||
""" | """ | ||||
if not isinstance(oldhashes, list): | if not isinstance(oldhashes, list): | ||||
oldhashes = [oldhashes] | oldhashes = [oldhashes] | ||||
if not isinstance(newhashes, list): | if not isinstance(newhashes, list): | ||||
newhashes = [newhashes] | newhashes = [newhashes] | ||||
entry = journalentry( | entry = journalentry( | ||||
util.makedate(), self.user, self.command, namespace, name, | dateutil.makedate(), self.user, self.command, namespace, name, | ||||
oldhashes, newhashes) | oldhashes, newhashes) | ||||
vfs = self.vfs | vfs = self.vfs | ||||
if self.sharedvfs is not None: | if self.sharedvfs is not None: | ||||
# write to the shared repository if this feature is being | # write to the shared repository if this feature is being | ||||
# shared between working copies. | # shared between working copies. | ||||
if sharednamespaces.get(namespace) in self.sharedfeatures: | if sharednamespaces.get(namespace) in self.sharedfeatures: | ||||
vfs = self.sharedvfs | vfs = self.sharedvfs |
registrar, | registrar, | ||||
revsetlang, | revsetlang, | ||||
scmutil, | scmutil, | ||||
smartset, | smartset, | ||||
subrepo, | subrepo, | ||||
util, | util, | ||||
vfs as vfsmod, | vfs as vfsmod, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
release = lockmod.release | release = lockmod.release | ||||
seriesopts = [('s', 'summary', None, _('print first line of patch header'))] | seriesopts = [('s', 'summary', None, _('print first line of patch header'))] | ||||
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 | ||||
idx = q.series.index(q.applied[-2].name) | idx = q.series.index(q.applied[-2].name) | ||||
q.qseries(repo, start=idx, length=1, status='A', | q.qseries(repo, start=idx, length=1, status='A', | ||||
summary=opts.get(r'summary')) | summary=opts.get(r'summary')) | ||||
def setupheaderopts(ui, opts): | def setupheaderopts(ui, opts): | ||||
if not opts.get('user') and opts.get('currentuser'): | if not opts.get('user') and opts.get('currentuser'): | ||||
opts['user'] = ui.username() | opts['user'] = ui.username() | ||||
if not opts.get('date') and opts.get('currentdate'): | if not opts.get('date') and opts.get('currentdate'): | ||||
opts['date'] = "%d %d" % util.makedate() | opts['date'] = "%d %d" % dateutil.makedate() | ||||
@command("^qnew", | @command("^qnew", | ||||
[('e', 'edit', None, _('invoke editor on commit messages')), | [('e', 'edit', None, _('invoke editor on commit messages')), | ||||
('f', 'force', None, _('import uncommitted changes (DEPRECATED)')), | ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')), | ||||
('g', 'git', None, _('use git extended diff format')), | ('g', 'git', None, _('use git extended diff format')), | ||||
('U', 'currentuser', None, _('add "From: <current user>" to patch')), | ('U', 'currentuser', None, _('add "From: <current user>" to patch')), | ||||
('u', 'user', '', | ('u', 'user', '', | ||||
_('add "From: <USER>" to patch'), _('USER')), | _('add "From: <USER>" to patch'), _('USER')), |
patch, | patch, | ||||
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
repair, | repair, | ||||
scmutil, | scmutil, | ||||
templater, | templater, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
stringio = util.stringio | stringio = util.stringio | ||||
cmdtable = {} | cmdtable = {} | ||||
command = registrar.command(cmdtable) | command = registrar.command(cmdtable) | ||||
configtable = {} | configtable = {} | ||||
configitem = registrar.configitem(configtable) | configitem = registrar.configitem(configtable) | ||||
for h in repo.set('heads(%ld)', missing)) | for h in repo.set('heads(%ld)', missing)) | ||||
hint = _("use 'hg push %s %s'") % (publicurl, revhint) | hint = _("use 'hg push %s %s'") % (publicurl, revhint) | ||||
raise error.Abort(msg, hint=hint) | raise error.Abort(msg, hint=hint) | ||||
# start | # start | ||||
if date: | if date: | ||||
start_time = util.parsedate(date) | start_time = util.parsedate(date) | ||||
else: | else: | ||||
start_time = util.makedate() | start_time = dateutil.makedate() | ||||
def genmsgid(id): | def genmsgid(id): | ||||
return '<%s.%s@%s>' % (id[:20], int(start_time[0]), socket.getfqdn()) | return '<%s.%s@%s>' % (id[:20], int(start_time[0]), socket.getfqdn()) | ||||
# deprecated config: patchbomb.from | # deprecated config: patchbomb.from | ||||
sender = (opts.get('from') or ui.config('email', 'from') or | sender = (opts.get('from') or ui.config('email', 'from') or | ||||
ui.config('patchbomb', 'from') or | ui.config('patchbomb', 'from') or | ||||
prompt(ui, 'From', ui.username())) | prompt(ui, 'From', ui.username())) |
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
repair, | repair, | ||||
scmutil, | scmutil, | ||||
templatefilters, | templatefilters, | ||||
util, | util, | ||||
vfs as vfsmod, | vfs as vfsmod, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import ( | from . import ( | ||||
rebase, | rebase, | ||||
) | ) | ||||
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 | ||||
continue | continue | ||||
ui.write(sname, label=namelabel) | ui.write(sname, label=namelabel) | ||||
namelabel = 'shelve.name' | namelabel = 'shelve.name' | ||||
if ui.quiet: | if ui.quiet: | ||||
ui.write('\n') | ui.write('\n') | ||||
continue | continue | ||||
ui.write(' ' * (16 - len(sname))) | ui.write(' ' * (16 - len(sname))) | ||||
used = 16 | used = 16 | ||||
age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True) | date = dateutil.makedate(mtime) | ||||
age = '(%s)' % templatefilters.age(date, abbrev=True) | |||||
ui.write(age, label='shelve.age') | ui.write(age, label='shelve.age') | ||||
ui.write(' ' * (12 - len(age))) | ui.write(' ' * (12 - len(age))) | ||||
used += 12 | used += 12 | ||||
with open(name + '.' + patchextension, 'rb') as fp: | with open(name + '.' + patchextension, 'rb') as fp: | ||||
while True: | while True: | ||||
line = fp.readline() | line = fp.readline() | ||||
if not line: | if not line: | ||||
break | break |
) | ) | ||||
from . import ( | from . import ( | ||||
encoding, | encoding, | ||||
error, | error, | ||||
revlog, | revlog, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
_defaultextra = {'branch': 'default'} | _defaultextra = {'branch': 'default'} | ||||
def _string_escape(text): | def _string_escape(text): | ||||
""" | """ | ||||
>>> from .pycompat import bytechr as chr | >>> from .pycompat import bytechr as chr | ||||
>>> d = {b'nl': chr(10), b'bs': chr(92), b'cr': chr(13), b'nul': chr(0)} | >>> d = {b'nl': chr(10), b'bs': chr(92), b'cr': chr(13), b'nul': chr(0)} | ||||
>>> s = b"ab%(nl)scd%(bs)s%(bs)sn%(nul)sab%(cr)scd%(bs)s%(nl)s" % d | >>> s = b"ab%(nl)scd%(bs)s%(bs)sn%(nul)sab%(cr)scd%(bs)s%(nl)s" % d | ||||
raise error.RevlogError(_("username %s contains a newline") | raise error.RevlogError(_("username %s contains a newline") | ||||
% repr(user)) | % repr(user)) | ||||
desc = stripdesc(desc) | desc = stripdesc(desc) | ||||
if date: | if date: | ||||
parseddate = "%d %d" % util.parsedate(date) | parseddate = "%d %d" % util.parsedate(date) | ||||
else: | else: | ||||
parseddate = "%d %d" % util.makedate() | parseddate = "%d %d" % dateutil.makedate() | ||||
if extra: | if extra: | ||||
branch = extra.get("branch") | branch = extra.get("branch") | ||||
if branch in ("default", ""): | if branch in ("default", ""): | ||||
del extra["branch"] | del extra["branch"] | ||||
elif branch in (".", "null", "tip"): | elif branch in (".", "null", "tip"): | ||||
raise error.RevlogError(_('the name \'%s\' is reserved') | raise error.RevlogError(_('the name \'%s\' is reserved') | ||||
% branch) | % branch) | ||||
if extra: | if extra: |
server, | server, | ||||
sshserver, | sshserver, | ||||
streamclone, | streamclone, | ||||
tags as tagsmod, | tags as tagsmod, | ||||
templatekw, | templatekw, | ||||
ui as uimod, | ui as uimod, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
release = lockmod.release | release = lockmod.release | ||||
table = {} | table = {} | ||||
table.update(debugcommandsmod.command._table) | table.update(debugcommandsmod.command._table) | ||||
command = registrar.command(table) | command = registrar.command(table) | ||||
readonly = registrar.command.readonly | readonly = registrar.command.readonly | ||||
'revision ordering!\n')) | 'revision ordering!\n')) | ||||
revs = list(revs) | revs = list(revs) | ||||
revs.extend(opts.get('rev')) | revs.extend(opts.get('rev')) | ||||
if not opts.get('user') and opts.get('currentuser'): | if not opts.get('user') and opts.get('currentuser'): | ||||
opts['user'] = ui.username() | opts['user'] = ui.username() | ||||
if not opts.get('date') and opts.get('currentdate'): | if not opts.get('date') and opts.get('currentdate'): | ||||
opts['date'] = "%d %d" % util.makedate() | opts['date'] = "%d %d" % dateutil.makedate() | ||||
editor = cmdutil.getcommiteditor(editform='graft', | editor = cmdutil.getcommiteditor(editform='graft', | ||||
**pycompat.strkwargs(opts)) | **pycompat.strkwargs(opts)) | ||||
cont = False | cont = False | ||||
if opts.get('continue'): | if opts.get('continue'): | ||||
cont = True | cont = True | ||||
if revs: | if revs: |
pycompat, | pycompat, | ||||
repoview, | repoview, | ||||
revlog, | revlog, | ||||
scmutil, | scmutil, | ||||
sparse, | sparse, | ||||
subrepo, | subrepo, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
propertycache = util.propertycache | propertycache = util.propertycache | ||||
nonascii = re.compile(r'[^\x21-\x7f]').search | nonascii = re.compile(r'[^\x21-\x7f]').search | ||||
class basectx(object): | class basectx(object): | ||||
"""A basectx object represents the common logic for its children: | """A basectx object represents the common logic for its children: | ||||
changectx: read-only context that is already present in the repo, | changectx: read-only context that is already present in the repo, | ||||
def _user(self): | def _user(self): | ||||
return self._repo.ui.username() | return self._repo.ui.username() | ||||
@propertycache | @propertycache | ||||
def _date(self): | def _date(self): | ||||
ui = self._repo.ui | ui = self._repo.ui | ||||
date = ui.configdate('devel', 'default-date') | date = ui.configdate('devel', 'default-date') | ||||
if date is None: | if date is None: | ||||
date = util.makedate() | date = dateutil.makedate() | ||||
return date | return date | ||||
def subrev(self, subpath): | def subrev(self, subpath): | ||||
return None | return None | ||||
def manifestnode(self): | def manifestnode(self): | ||||
return None | return None | ||||
def user(self): | def user(self): | ||||
"entries: %s)" | "entries: %s)" | ||||
% (path, path, self.p1(), len(matches), | % (path, path, self.p1(), len(matches), | ||||
', '.join(matches.keys()))) | ', '.join(matches.keys()))) | ||||
def write(self, path, data, flags='', **kwargs): | def write(self, path, data, flags='', **kwargs): | ||||
if data is None: | if data is None: | ||||
raise error.ProgrammingError("data must be non-None") | raise error.ProgrammingError("data must be non-None") | ||||
self._auditconflicts(path) | self._auditconflicts(path) | ||||
self._markdirty(path, exists=True, data=data, date=util.makedate(), | self._markdirty(path, exists=True, data=data, date=dateutil.makedate(), | ||||
flags=flags) | flags=flags) | ||||
def setflags(self, path, l, x): | def setflags(self, path, l, x): | ||||
self._markdirty(path, exists=True, date=util.makedate(), | self._markdirty(path, exists=True, date=dateutil.makedate(), | ||||
flags=(l and 'l' or '') + (x and 'x' or '')) | flags=(l and 'l' or '') + (x and 'x' or '')) | ||||
def remove(self, path): | def remove(self, path): | ||||
self._markdirty(path, exists=False) | self._markdirty(path, exists=False) | ||||
def exists(self, path): | def exists(self, path): | ||||
"""exists behaves like `lexists`, but needs to follow symlinks and | """exists behaves like `lexists`, but needs to follow symlinks and | ||||
return False if they are broken. | return False if they are broken. |
hg, | hg, | ||||
profiling, | profiling, | ||||
pycompat, | pycompat, | ||||
scmutil, | scmutil, | ||||
templater, | templater, | ||||
ui as uimod, | ui as uimod, | ||||
util, | util, | ||||
) | ) | ||||
from ..utils import dateutil | |||||
from . import ( | from . import ( | ||||
hgweb_mod, | hgweb_mod, | ||||
webutil, | webutil, | ||||
wsgicgi, | wsgicgi, | ||||
) | ) | ||||
def cleannames(items): | def cleannames(items): | ||||
if req.env['SCRIPT_NAME']: | if req.env['SCRIPT_NAME']: | ||||
parts.insert(0, req.env['SCRIPT_NAME']) | parts.insert(0, req.env['SCRIPT_NAME']) | ||||
url = re.sub(r'/+', '/', '/'.join(parts) + '/') | url = re.sub(r'/+', '/', '/'.join(parts) + '/') | ||||
# show either a directory entry or a repository | # show either a directory entry or a repository | ||||
if directory: | if directory: | ||||
# get the directory's time information | # get the directory's time information | ||||
try: | try: | ||||
d = (get_mtime(path), util.makedate()[1]) | d = (get_mtime(path), dateutil.makedate()[1]) | ||||
except OSError: | except OSError: | ||||
continue | continue | ||||
# add '/' to the name to make it obvious that | # add '/' to the name to make it obvious that | ||||
# the entry is a directory, not a regular repository | # the entry is a directory, not a regular repository | ||||
row = {'contact': "", | row = {'contact': "", | ||||
'contact_sort': "", | 'contact_sort': "", | ||||
'name': name + '/', | 'name': name + '/', | ||||
r = hg.repository(self.ui, path) | r = hg.repository(self.ui, path) | ||||
except IOError: | except IOError: | ||||
u.warn(_('error accessing repository at %s\n') % path) | u.warn(_('error accessing repository at %s\n') % path) | ||||
continue | continue | ||||
except error.RepoError: | except error.RepoError: | ||||
u.warn(_('error accessing repository at %s\n') % path) | u.warn(_('error accessing repository at %s\n') % path) | ||||
continue | continue | ||||
try: | try: | ||||
d = (get_mtime(r.spath), util.makedate()[1]) | d = (get_mtime(r.spath), dateutil.makedate()[1]) | ||||
except OSError: | except OSError: | ||||
continue | continue | ||||
contact = get_contact(get) | contact = get_contact(get) | ||||
description = get("web", "description") | description = get("web", "description") | ||||
seenrepos.add(name) | seenrepos.add(name) | ||||
name = get("web", "name", name) | name = get("web", "name", name) | ||||
row = {'contact': contact or "unknown", | row = {'contact': contact or "unknown", |
from . import ( | from . import ( | ||||
error, | error, | ||||
node, | node, | ||||
obsutil, | obsutil, | ||||
phases, | phases, | ||||
policy, | policy, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
parsers = policy.importmod(r'parsers') | parsers = policy.importmod(r'parsers') | ||||
_pack = struct.pack | _pack = struct.pack | ||||
_unpack = struct.unpack | _unpack = struct.unpack | ||||
_calcsize = struct.calcsize | _calcsize = struct.calcsize | ||||
propertycache = util.propertycache | propertycache = util.propertycache | ||||
metadata = {} | metadata = {} | ||||
if date is None: | if date is None: | ||||
if 'date' in metadata: | if 'date' in metadata: | ||||
# as a courtesy for out-of-tree extensions | # as a courtesy for out-of-tree extensions | ||||
date = util.parsedate(metadata.pop('date')) | date = util.parsedate(metadata.pop('date')) | ||||
elif ui is not None: | elif ui is not None: | ||||
date = ui.configdate('devel', 'default-date') | date = ui.configdate('devel', 'default-date') | ||||
if date is None: | if date is None: | ||||
date = util.makedate() | date = dateutil.makedate() | ||||
else: | else: | ||||
date = util.makedate() | date = dateutil.makedate() | ||||
if len(prec) != 20: | if len(prec) != 20: | ||||
raise ValueError(prec) | raise ValueError(prec) | ||||
for succ in succs: | for succ in succs: | ||||
if len(succ) != 20: | if len(succ) != 20: | ||||
raise ValueError(succ) | raise ValueError(succ) | ||||
if prec in succs: | if prec in succs: | ||||
raise ValueError(_('in-marker cycle with %s') % node.hex(prec)) | raise ValueError(_('in-marker cycle with %s') % node.hex(prec)) | ||||
registrar, | registrar, | ||||
revset as revsetmod, | revset as revsetmod, | ||||
revsetlang, | revsetlang, | ||||
scmutil, | scmutil, | ||||
templatefilters, | templatefilters, | ||||
templatekw, | templatekw, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
# template parsing | # template parsing | ||||
elements = { | elements = { | ||||
# token-type: binding-strength, primary, prefix, infix, suffix | # token-type: binding-strength, primary, prefix, infix, suffix | ||||
"(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None), | "(": (20, None, ("group", 1, ")"), ("func", 1, ")"), None), | ||||
".": (18, None, None, (".", 18), None), | ".": (18, None, None, (".", 18), None), | ||||
"%": (15, None, None, ("%", 15), None), | "%": (15, None, None, ("%", 15), None), | ||||
tzoffset = None | tzoffset = None | ||||
if tzoffset is None: | if tzoffset is None: | ||||
try: | try: | ||||
tzoffset = int(tz) | tzoffset = int(tz) | ||||
except (TypeError, ValueError): | except (TypeError, ValueError): | ||||
# i18n: "localdate" is a keyword | # i18n: "localdate" is a keyword | ||||
raise error.ParseError(_("localdate expects a timezone")) | raise error.ParseError(_("localdate expects a timezone")) | ||||
else: | else: | ||||
tzoffset = util.makedate()[1] | tzoffset = dateutil.makedate()[1] | ||||
return (date[0], tzoffset) | return (date[0], tzoffset) | ||||
@templatefunc('max(iterable)') | @templatefunc('max(iterable)') | ||||
def max_(context, mapping, args, **kwargs): | def max_(context, mapping, args, **kwargs): | ||||
"""Return the max of an iterable""" | """Return the max of an iterable""" | ||||
if len(args) != 1: | if len(args) != 1: | ||||
# i18n: "max" is a keyword | # i18n: "max" is a keyword | ||||
raise error.ParseError(_("max expects one argument")) | raise error.ParseError(_("max expects one argument")) |
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 makedate(timestamp=None): | |||||
'''Return a unix timestamp (or the current time) as a (unixtime, | |||||
offset) tuple based off the local timezone.''' | |||||
if timestamp is None: | |||||
timestamp = time.time() | |||||
if timestamp < 0: | |||||
hint = _("check your clock") | |||||
raise Abort(_("negative timestamp: %d") % timestamp, hint=hint) | |||||
delta = (datetime.datetime.utcfromtimestamp(timestamp) - | |||||
datetime.datetime.fromtimestamp(timestamp)) | |||||
tz = delta.days * 86400 + delta.seconds | |||||
return timestamp, tz | |||||
def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'): | def datestr(date=None, format='%a %b %d %H:%M:%S %Y %1%2'): | ||||
"""represent a (unixtime, offset) tuple as a localized time. | """represent a (unixtime, offset) tuple as a localized time. | ||||
unixtime is seconds since the epoch, and offset is the time zone's | unixtime is seconds since the epoch, and offset is the time zone's | ||||
number of seconds away from UTC. | number of seconds away from UTC. | ||||
>>> datestr((0, 0)) | >>> datestr((0, 0)) | ||||
'Thu Jan 01 00:00:00 1970 +0000' | 'Thu Jan 01 00:00:00 1970 +0000' | ||||
>>> datestr((42, 0)) | >>> datestr((42, 0)) | ||||
'Thu Jan 01 00:00:42 1970 +0000' | 'Thu Jan 01 00:00:42 1970 +0000' | ||||
>>> datestr((-42, 0)) | >>> datestr((-42, 0)) | ||||
'Wed Dec 31 23:59:18 1969 +0000' | 'Wed Dec 31 23:59:18 1969 +0000' | ||||
>>> datestr((0x7fffffff, 0)) | >>> datestr((0x7fffffff, 0)) | ||||
'Tue Jan 19 03:14:07 2038 +0000' | 'Tue Jan 19 03:14:07 2038 +0000' | ||||
>>> datestr((-0x80000000, 0)) | >>> datestr((-0x80000000, 0)) | ||||
'Fri Dec 13 20:45:52 1901 +0000' | 'Fri Dec 13 20:45:52 1901 +0000' | ||||
""" | """ | ||||
t, tz = date or makedate() | t, tz = date or dateutil.makedate() | ||||
if "%1" in format or "%2" in format or "%z" in format: | if "%1" in format or "%2" in format or "%z" in format: | ||||
sign = (tz > 0) and "-" or "+" | sign = (tz > 0) and "-" or "+" | ||||
minutes = abs(tz) // 60 | minutes = abs(tz) // 60 | ||||
q, r = divmod(minutes, 60) | q, r = divmod(minutes, 60) | ||||
format = format.replace("%z", "%1%2") | format = format.replace("%z", "%1%2") | ||||
format = format.replace("%1", "%c%02d" % (sign, q)) | format = format.replace("%1", "%c%02d" % (sign, q)) | ||||
format = format.replace("%2", "%02d" % r) | format = format.replace("%2", "%02d" % r) | ||||
d = t - tz | d = t - tz | ||||
>>> parsedate(b' today ') == parsedate( | >>> parsedate(b' today ') == parsedate( | ||||
... datetime.date.today().strftime('%b %d').encode('ascii')) | ... datetime.date.today().strftime('%b %d').encode('ascii')) | ||||
True | True | ||||
>>> parsedate(b'yesterday ') == parsedate( | >>> parsedate(b'yesterday ') == parsedate( | ||||
... (datetime.date.today() - datetime.timedelta(days=1) | ... (datetime.date.today() - datetime.timedelta(days=1) | ||||
... ).strftime('%b %d').encode('ascii')) | ... ).strftime('%b %d').encode('ascii')) | ||||
True | True | ||||
>>> now, tz = makedate() | >>> now, tz = dateutil.makedate() | ||||
>>> strnow, strtz = parsedate(b'now') | >>> strnow, strtz = parsedate(b'now') | ||||
>>> (strnow - now) < 1 | >>> (strnow - now) < 1 | ||||
True | True | ||||
>>> tz == strtz | >>> tz == strtz | ||||
True | True | ||||
""" | """ | ||||
if bias is None: | if bias is None: | ||||
bias = {} | bias = {} | ||||
if not date: | if not date: | ||||
return 0, 0 | return 0, 0 | ||||
if isinstance(date, tuple) and len(date) == 2: | if isinstance(date, tuple) and len(date) == 2: | ||||
return date | return date | ||||
if not formats: | if not formats: | ||||
formats = defaultdateformats | formats = defaultdateformats | ||||
date = date.strip() | date = date.strip() | ||||
if date == 'now' or date == _('now'): | if date == 'now' or date == _('now'): | ||||
return makedate() | return dateutil.makedate() | ||||
if date == 'today' or date == _('today'): | if date == 'today' or date == _('today'): | ||||
date = datetime.date.today().strftime(r'%b %d') | date = datetime.date.today().strftime(r'%b %d') | ||||
date = encoding.strtolocal(date) | date = encoding.strtolocal(date) | ||||
elif date == 'yesterday' or date == _('yesterday'): | elif date == 'yesterday' or date == _('yesterday'): | ||||
date = (datetime.date.today() - | date = (datetime.date.today() - | ||||
datetime.timedelta(days=1)).strftime(r'%b %d') | datetime.timedelta(days=1)).strftime(r'%b %d') | ||||
date = encoding.strtolocal(date) | date = encoding.strtolocal(date) | ||||
try: | try: | ||||
when, offset = map(int, date.split(' ')) | when, offset = map(int, date.split(' ')) | ||||
except ValueError: | except ValueError: | ||||
# fill out defaults | # fill out defaults | ||||
now = makedate() | now = dateutil.makedate() | ||||
defaults = {} | defaults = {} | ||||
for part in ("d", "mb", "yY", "HI", "M", "S"): | for part in ("d", "mb", "yY", "HI", "M", "S"): | ||||
# this piece is for rounding the specific end of unknowns | # this piece is for rounding the specific end of unknowns | ||||
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: | ||||
elif date[0] == "-": | elif date[0] == "-": | ||||
try: | try: | ||||
days = int(date[1:]) | days = int(date[1:]) | ||||
except ValueError: | except ValueError: | ||||
raise Abort(_("invalid day spec: %s") % date[1:]) | raise Abort(_("invalid day spec: %s") % date[1:]) | ||||
if days < 0: | if days < 0: | ||||
raise Abort(_("%s must be nonnegative (see 'hg help dates')") | raise Abort(_("%s must be nonnegative (see 'hg help dates')") | ||||
% date[1:]) | % date[1:]) | ||||
when = makedate()[0] - days * 3600 * 24 | when = dateutil.makedate()[0] - days * 3600 * 24 | ||||
return lambda x: x >= when | return lambda x: x >= when | ||||
elif " to " in date: | elif " to " in date: | ||||
a, b = date.split(" to ") | a, b = date.split(" to ") | ||||
start, stop = lower(a), upper(b) | start, stop = lower(a), upper(b) | ||||
return lambda x: x >= start and x <= stop | return lambda x: x >= start and x <= stop | ||||
else: | else: | ||||
start, stop = lower(date), upper(date) | start, stop = lower(date), upper(date) | ||||
return lambda x: x >= start and x <= stop | return lambda x: x >= start and x <= stop | ||||
### | ### | ||||
# Deprecation warnings for util.py splitting | # Deprecation warnings for util.py splitting | ||||
### | ### | ||||
defaultdateformats = dateutil.defaultdateformats | defaultdateformats = dateutil.defaultdateformats | ||||
extendeddateformats = dateutil.extendeddateformats | extendeddateformats = dateutil.extendeddateformats | ||||
def makedate(*args, **kwargs): | |||||
msg = ("'util.makedate' is deprecated, " | |||||
"use 'utils.dateutil.makedate'") | |||||
nouideprecwarn(msg, "4.6") | |||||
return dateutil.makedate(*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 time | |||||
from ..i18n import _ | |||||
from .. import ( | |||||
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 : | ||||
'%Y-%m-%dT%H%M', # without seconds | '%Y-%m-%dT%H%M', # without seconds | ||||
'%Y-%m-%d %H:%M:%S', # our common legal variant | '%Y-%m-%d %H:%M:%S', # our common legal variant | ||||
'%Y-%m-%d %H:%M', # without seconds | '%Y-%m-%d %H:%M', # without seconds | ||||
) | ) | ||||
extendeddateformats = defaultdateformats + ( | extendeddateformats = defaultdateformats + ( | ||||
"%Y", | "%Y", | ||||
"%Y-%m", | "%Y-%m", | ||||
"%b", | "%b", | ||||
"%b %Y", | "%b %Y", | ||||
) | ) | ||||
def makedate(timestamp=None): | |||||
'''Return a unix timestamp (or the current time) as a (unixtime, | |||||
offset) tuple based off the local timezone.''' | |||||
if timestamp is None: | |||||
timestamp = time.time() | |||||
if timestamp < 0: | |||||
hint = _("check your clock") | |||||
raise error.Abort(_("negative timestamp: %d") % timestamp, hint=hint) | |||||
delta = (datetime.datetime.utcfromtimestamp(timestamp) - | |||||
datetime.datetime.fromtimestamp(timestamp)) | |||||
tz = delta.days * 86400 + delta.seconds | |||||
return timestamp, tz | |||||
Tests for the journal extension; records bookmark locations. | Tests for the journal extension; records bookmark locations. | ||||
$ cat >> testmocks.py << EOF | $ cat >> testmocks.py << EOF | ||||
> # mock out util.getuser() and util.makedate() to supply testable values | > # mock out util.getuser() and util.makedate() to supply testable values | ||||
> import os | > import os | ||||
> from mercurial import util | > from mercurial import util | ||||
> from mercurial.utils import dateutil | |||||
> def mockgetuser(): | > def mockgetuser(): | ||||
> return 'foobar' | > return 'foobar' | ||||
> | > | ||||
> def mockmakedate(): | > def mockmakedate(): | ||||
> filename = os.path.join(os.environ['TESTTMP'], 'testtime') | > filename = os.path.join(os.environ['TESTTMP'], 'testtime') | ||||
> try: | > try: | ||||
> with open(filename, 'rb') as timef: | > with open(filename, 'rb') as timef: | ||||
> time = float(timef.read()) + 1 | > time = float(timef.read()) + 1 | ||||
> except IOError: | > except IOError: | ||||
> time = 0.0 | > time = 0.0 | ||||
> with open(filename, 'wb') as timef: | > with open(filename, 'wb') as timef: | ||||
> timef.write(str(time)) | > timef.write(str(time)) | ||||
> return (time, 0) | > return (time, 0) | ||||
> | > | ||||
> util.getuser = mockgetuser | > util.getuser = mockgetuser | ||||
> util.makedate = mockmakedate | > dateutil.makedate = mockmakedate | ||||
> EOF | > EOF | ||||
$ cat >> $HGRCPATH << EOF | $ cat >> $HGRCPATH << EOF | ||||
> [extensions] | > [extensions] | ||||
> journal= | > journal= | ||||
> testmocks=`pwd`/testmocks.py | > testmocks=`pwd`/testmocks.py | ||||
> EOF | > EOF | ||||