Extract parsedate 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 parsedate from util.py to utils/dateutil.py
Lint Skipped |
Unit Tests Skipped |
Path | Packages | |||
---|---|---|---|---|
M | hgext/convert/convcmd.py (3 lines) | |||
M | hgext/convert/cvsps.py (2 lines) | |||
M | hgext/convert/subversion.py (2 lines) | |||
M | hgext/fetch.py (3 lines) | |||
M | hgext/gpg.py (3 lines) | |||
M | hgext/keyword.py (6 lines) | |||
M | hgext/mq.py (4 lines) | |||
M | hgext/patchbomb.py (2 lines) | |||
M | mercurial/changelog.py (2 lines) | |||
M | mercurial/cmdutil.py (4 lines) | |||
M | mercurial/commands.py (6 lines) | |||
M | mercurial/context.py (6 lines) | |||
M | mercurial/debugcommands.py (6 lines) | |||
M | mercurial/obsolete.py (2 lines) | |||
M | mercurial/templater.py (2 lines) | |||
M | mercurial/ui.py (3 lines) | |||
M | mercurial/util.py (102 lines) | |||
M | mercurial/utils/dateutil.py (79 lines) | |||
M | tests/fakedirstatewritetime.py (4 lines) | |||
M | tests/fakepatchtime.py (4 lines) |
Status | Author | Revision | |
---|---|---|---|
Abandoned | lothiraldan | ||
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 | durin42 |
from mercurial.i18n import _ | from mercurial.i18n import _ | ||||
from mercurial import ( | from mercurial import ( | ||||
encoding, | encoding, | ||||
error, | error, | ||||
hg, | hg, | ||||
scmutil, | scmutil, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
from . import ( | from . import ( | ||||
bzr, | bzr, | ||||
common, | common, | ||||
cvs, | cvs, | ||||
darcs, | darcs, | ||||
filemap, | filemap, | ||||
git, | git, | ||||
return sorted(nodes, key=keyfn)[0] | return sorted(nodes, key=keyfn)[0] | ||||
return picknext | return picknext | ||||
def makedatesorter(): | def makedatesorter(): | ||||
"""Sort revisions by date.""" | """Sort revisions by date.""" | ||||
dates = {} | dates = {} | ||||
def getdate(n): | def getdate(n): | ||||
if n not in dates: | if n not in dates: | ||||
dates[n] = util.parsedate(self.commitcache[n].date) | dates[n] = dateutil.parsedate(self.commitcache[n].date) | ||||
return dates[n] | return dates[n] | ||||
def picknext(nodes): | def picknext(nodes): | ||||
return min([(getdate(n), n) for n in nodes])[1] | return min([(getdate(n), n) for n in nodes])[1] | ||||
return picknext | return picknext | ||||
if sortmode == 'branchsort': | if sortmode == 'branchsort': |
d = match.group(1) | d = match.group(1) | ||||
if d[2] == '/': | if d[2] == '/': | ||||
# Y2K | # Y2K | ||||
d = '19' + d | d = '19' + d | ||||
if len(d.split()) != 3: | if len(d.split()) != 3: | ||||
# cvs log dates always in GMT | # cvs log dates always in GMT | ||||
d = d + ' UTC' | d = d + ' UTC' | ||||
e.date = util.parsedate(d, ['%y/%m/%d %H:%M:%S', | e.date = dateutil.parsedate(d, ['%y/%m/%d %H:%M:%S', | ||||
'%Y/%m/%d %H:%M:%S', | '%Y/%m/%d %H:%M:%S', | ||||
'%Y-%m-%d %H:%M:%S']) | '%Y-%m-%d %H:%M:%S']) | ||||
e.author = scache(match.group(2)) | e.author = scache(match.group(2)) | ||||
e.dead = match.group(3).lower() == 'dead' | e.dead = match.group(3).lower() == 'dead' | ||||
if match.group(5): | if match.group(5): | ||||
if match.group(6): | if match.group(6): | ||||
e.lines = (int(match.group(5)), int(match.group(6))) | e.lines = (int(match.group(5)), int(match.group(6))) |
for path, ent in orig_paths: | for path, ent in orig_paths: | ||||
if self.getrelpath(path) is None: | if self.getrelpath(path) is None: | ||||
continue | continue | ||||
paths.append((path, ent)) | paths.append((path, ent)) | ||||
# Example SVN datetime. Includes microseconds. | # Example SVN datetime. Includes microseconds. | ||||
# ISO-8601 conformant | # ISO-8601 conformant | ||||
# '2007-01-04T17:35:00.902377Z' | # '2007-01-04T17:35:00.902377Z' | ||||
date = util.parsedate(date[:19] + " UTC", ["%Y-%m-%dT%H:%M:%S"]) | date = dateutil.parsedate(date[:19] + " UTC", ["%Y-%m-%dT%H:%M:%S"]) | ||||
if self.ui.configbool('convert', 'localtimezone'): | if self.ui.configbool('convert', 'localtimezone'): | ||||
date = makedatetimestamp(date[0]) | date = makedatetimestamp(date[0]) | ||||
if message: | if message: | ||||
log = self.recode(message) | log = self.recode(message) | ||||
else: | else: | ||||
log = '' | log = '' | ||||
error, | error, | ||||
exchange, | exchange, | ||||
hg, | hg, | ||||
lock, | lock, | ||||
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
util, | util, | ||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
release = lock.release | release = lock.release | ||||
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. | ||||
See :hg:`help dates` for a list of formats valid for -d/--date. | See :hg:`help dates` for a list of formats valid for -d/--date. | ||||
Returns 0 on success. | Returns 0 on success. | ||||
''' | ''' | ||||
opts = pycompat.byteskwargs(opts) | opts = pycompat.byteskwargs(opts) | ||||
date = opts.get('date') | date = opts.get('date') | ||||
if date: | if date: | ||||
opts['date'] = util.parsedate(date) | opts['date'] = dateutil.parsedate(date) | ||||
parent, _p2 = repo.dirstate.parents() | parent, _p2 = repo.dirstate.parents() | ||||
branch = repo.dirstate.branch() | branch = repo.dirstate.branch() | ||||
try: | try: | ||||
branchnode = repo.branchtip(branch) | branchnode = repo.branchtip(branch) | ||||
except error.RepoLookupError: | except error.RepoLookupError: | ||||
branchnode = None | branchnode = None | ||||
if parent != branchnode: | if parent != branchnode: |
cmdutil, | cmdutil, | ||||
error, | error, | ||||
match, | match, | ||||
node as hgnode, | node as hgnode, | ||||
pycompat, | pycompat, | ||||
registrar, | registrar, | ||||
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' | ||||
def _dosign(ui, repo, *revs, **opts): | def _dosign(ui, repo, *revs, **opts): | ||||
mygpg = newgpg(ui, **opts) | mygpg = newgpg(ui, **opts) | ||||
opts = pycompat.byteskwargs(opts) | opts = pycompat.byteskwargs(opts) | ||||
sigver = "0" | sigver = "0" | ||||
sigmessage = "" | sigmessage = "" | ||||
date = opts.get('date') | date = opts.get('date') | ||||
if date: | if date: | ||||
opts['date'] = util.parsedate(date) | opts['date'] = dateutil.parsedate(date) | ||||
if revs: | if revs: | ||||
nodes = [repo.lookup(n) for n in revs] | nodes = [repo.lookup(n) for n in revs] | ||||
else: | else: | ||||
nodes = [node for node in repo.dirstate.parents() | nodes = [node for node in repo.dirstate.parents() | ||||
if node != hgnode.nullid] | if node != hgnode.nullid] | ||||
if len(nodes) > 1: | if len(nodes) > 1: | ||||
raise error.Abort(_('uncommitted merge - please provide a ' | raise error.Abort(_('uncommitted merge - please provide a ' |
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 dateutil.datestr((util.parsedate(text)[0], 0), '%Y/%m/%d %H:%M:%S') | dateformat = '%Y/%m/%d %H:%M:%S' | ||||
return dateutil.datestr((dateutil.parsedate(text)[0], 0), dateformat) | |||||
# 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 dateutil.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 dateutil.datestr((util.parsedate(text)[0], 0), '%Y-%m-%d %H:%M:%SZ') | dateformat = '%Y-%m-%d %H:%M:%SZ' | ||||
return dateutil.datestr((dateutil.parsedate(text)[0], 0), dateformat) | |||||
# 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}', |
msg: a string or a no-argument function returning a string | msg: a string or a no-argument function returning a string | ||||
""" | """ | ||||
msg = opts.get('msg') | msg = opts.get('msg') | ||||
edit = opts.get('edit') | edit = opts.get('edit') | ||||
editform = opts.get('editform', 'mq.qnew') | editform = opts.get('editform', 'mq.qnew') | ||||
user = opts.get('user') | user = opts.get('user') | ||||
date = opts.get('date') | date = opts.get('date') | ||||
if date: | if date: | ||||
date = util.parsedate(date) | date = dateutil.parsedate(date) | ||||
diffopts = self.diffopts({'git': opts.get('git')}, plain=True) | diffopts = self.diffopts({'git': opts.get('git')}, plain=True) | ||||
if opts.get('checkname', True): | if opts.get('checkname', True): | ||||
self.checkpatchname(patchfn) | self.checkpatchname(patchfn) | ||||
inclsubs = checksubstate(repo) | inclsubs = checksubstate(repo) | ||||
if inclsubs: | if inclsubs: | ||||
substatestate = repo.dirstate['.hgsubstate'] | substatestate = repo.dirstate['.hgsubstate'] | ||||
if opts.get('include') or opts.get('exclude') or pats: | if opts.get('include') or opts.get('exclude') or pats: | ||||
# detect missing files in pats | # detect missing files in pats | ||||
self.ui.write(_("no patches applied\n")) | self.ui.write(_("no patches applied\n")) | ||||
return 1 | return 1 | ||||
msg = opts.get('msg', '').rstrip() | msg = opts.get('msg', '').rstrip() | ||||
edit = opts.get('edit') | edit = opts.get('edit') | ||||
editform = opts.get('editform', 'mq.qrefresh') | editform = opts.get('editform', 'mq.qrefresh') | ||||
newuser = opts.get('user') | newuser = opts.get('user') | ||||
newdate = opts.get('date') | newdate = opts.get('date') | ||||
if newdate: | if newdate: | ||||
newdate = '%d %d' % util.parsedate(newdate) | newdate = '%d %d' % dateutil.parsedate(newdate) | ||||
wlock = repo.wlock() | wlock = repo.wlock() | ||||
try: | try: | ||||
self.checktoppatch(repo) | self.checktoppatch(repo) | ||||
(top, patchfn) = (self.applied[-1].node, self.applied[-1].name) | (top, patchfn) = (self.applied[-1].node, self.applied[-1].name) | ||||
if repo.changelog.heads(top) != [top]: | if repo.changelog.heads(top) != [top]: | ||||
raise error.Abort(_("cannot qrefresh a revision with children")) | raise error.Abort(_("cannot qrefresh a revision with children")) | ||||
if not repo[top].mutable(): | if not repo[top].mutable(): |
msg %= (publicurl, missing[0]) | msg %= (publicurl, missing[0]) | ||||
revhint = ' '.join('-r %s' % h | revhint = ' '.join('-r %s' % h | ||||
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 = dateutil.parsedate(date) | ||||
else: | else: | ||||
start_time = dateutil.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 |
raise error.RevlogError(_("empty username")) | raise error.RevlogError(_("empty username")) | ||||
if "\n" in user: | if "\n" in user: | ||||
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" % dateutil.parsedate(date) | ||||
else: | else: | ||||
parseddate = "%d %d" % dateutil.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') |
% os.path.join(prefix, subpath)) | % os.path.join(prefix, subpath)) | ||||
return err | return err | ||||
def commit(ui, repo, commitfunc, pats, opts): | def commit(ui, repo, commitfunc, pats, opts): | ||||
'''commit the specified files or all outstanding changes''' | '''commit the specified files or all outstanding changes''' | ||||
date = opts.get('date') | date = opts.get('date') | ||||
if date: | if date: | ||||
opts['date'] = util.parsedate(date) | opts['date'] = dateutil.parsedate(date) | ||||
message = logmessage(ui, opts) | message = logmessage(ui, opts) | ||||
matcher = scmutil.match(repo[None], pats, opts) | matcher = scmutil.match(repo[None], pats, opts) | ||||
dsguard = None | dsguard = None | ||||
# extract addremove carefully -- this function can be called from a command | # extract addremove carefully -- this function can be called from a command | ||||
# that doesn't support addremove | # that doesn't support addremove | ||||
if opts.get('addremove'): | if opts.get('addremove'): | ||||
dsguard = dirstateguard.dirstateguard(repo, 'commit') | dsguard = dirstateguard.dirstateguard(repo, 'commit') | ||||
# Also update it from the from the wctx | # Also update it from the from the wctx | ||||
extra.update(wctx.extra()) | extra.update(wctx.extra()) | ||||
user = opts.get('user') or old.user() | user = opts.get('user') or old.user() | ||||
date = opts.get('date') or old.date() | date = opts.get('date') or old.date() | ||||
# Parse the date to allow comparison between date and old.date() | # Parse the date to allow comparison between date and old.date() | ||||
date = util.parsedate(date) | date = dateutil.parsedate(date) | ||||
if len(old.parents()) > 1: | if len(old.parents()) > 1: | ||||
# ctx.files() isn't reliable for merges, so fall back to the | # ctx.files() isn't reliable for merges, so fall back to the | ||||
# slower repo.status() method | # slower repo.status() method | ||||
files = set([fn for st in repo.status(base, old)[:3] | files = set([fn for st in repo.status(base, old)[:3] | ||||
for fn in st]) | for fn in st]) | ||||
else: | else: | ||||
files = set(old.files()) | files = set(old.files()) |
if not rev: | if not rev: | ||||
rev = node | rev = node | ||||
if not rev: | if not rev: | ||||
raise error.Abort(_("please specify a revision to backout")) | raise error.Abort(_("please specify a revision to backout")) | ||||
date = opts.get('date') | date = opts.get('date') | ||||
if date: | if date: | ||||
opts['date'] = util.parsedate(date) | opts['date'] = dateutil.parsedate(date) | ||||
cmdutil.checkunfinished(repo) | cmdutil.checkunfinished(repo) | ||||
cmdutil.bailifchanged(repo) | cmdutil.bailifchanged(repo) | ||||
node = scmutil.revsingle(repo, rev).node() | node = scmutil.revsingle(repo, rev).node() | ||||
op1, op2 = repo.dirstate.parents() | op1, op2 = repo.dirstate.parents() | ||||
if not repo.changelog.isancestor(node, op1): | if not repo.changelog.isancestor(node, op1): | ||||
raise error.Abort(_('cannot backout change that is not an ancestor')) | raise error.Abort(_('cannot backout change that is not an ancestor')) | ||||
opts = pycompat.byteskwargs(opts) | opts = pycompat.byteskwargs(opts) | ||||
if not patch1: | if not patch1: | ||||
raise error.Abort(_('need at least one patch to import')) | raise error.Abort(_('need at least one patch to import')) | ||||
patches = (patch1,) + patches | patches = (patch1,) + patches | ||||
date = opts.get('date') | date = opts.get('date') | ||||
if date: | if date: | ||||
opts['date'] = util.parsedate(date) | opts['date'] = dateutil.parsedate(date) | ||||
exact = opts.get('exact') | exact = opts.get('exact') | ||||
update = not opts.get('bypass') | update = not opts.get('bypass') | ||||
if not update and opts.get('no_commit'): | if not update and opts.get('no_commit'): | ||||
raise error.Abort(_('cannot use --no-commit with --bypass')) | raise error.Abort(_('cannot use --no-commit with --bypass')) | ||||
try: | try: | ||||
sim = float(opts.get('similarity') or 0) | sim = float(opts.get('similarity') or 0) | ||||
except ValueError: | except ValueError: | ||||
if not message: | if not message: | ||||
# we don't translate commit messages | # we don't translate commit messages | ||||
message = ('Added tag %s for changeset %s' % | message = ('Added tag %s for changeset %s' % | ||||
(', '.join(names), short(r))) | (', '.join(names), short(r))) | ||||
date = opts.get('date') | date = opts.get('date') | ||||
if date: | if date: | ||||
date = util.parsedate(date) | date = dateutil.parsedate(date) | ||||
if opts.get('remove'): | if opts.get('remove'): | ||||
editform = 'tag.remove' | editform = 'tag.remove' | ||||
else: | else: | ||||
editform = 'tag.add' | editform = 'tag.add' | ||||
editor = cmdutil.getcommiteditor(editform=editform, | editor = cmdutil.getcommiteditor(editform=editform, | ||||
**pycompat.strkwargs(opts)) | **pycompat.strkwargs(opts)) | ||||
wants the ability to commit, e.g. workingctx or memctx.""" | wants the ability to commit, e.g. workingctx or memctx.""" | ||||
def __init__(self, repo, text="", user=None, date=None, extra=None, | def __init__(self, repo, text="", user=None, date=None, extra=None, | ||||
changes=None): | changes=None): | ||||
self._repo = repo | self._repo = repo | ||||
self._rev = None | self._rev = None | ||||
self._node = None | self._node = None | ||||
self._text = text | self._text = text | ||||
if date: | if date: | ||||
self._date = util.parsedate(date) | self._date = dateutil.parsedate(date) | ||||
if user: | if user: | ||||
self._user = user | self._user = user | ||||
if changes: | if changes: | ||||
self._status = changes | self._status = changes | ||||
self._extra = {} | self._extra = {} | ||||
if extra: | if extra: | ||||
self._extra = extra.copy() | self._extra = extra.copy() | ||||
committed (updated or added), filectxfn returns a memfilectx | committed (updated or added), filectxfn returns a memfilectx | ||||
object. If the file was removed, filectxfn return None for recent | object. If the file was removed, filectxfn return None for recent | ||||
Mercurial. Moved files are represented by marking the source file | Mercurial. Moved files are represented by marking the source file | ||||
removed and the new file added with copy information (see | removed and the new file added with copy information (see | ||||
memfilectx). | memfilectx). | ||||
user receives the committer name and defaults to current | user receives the committer name and defaults to current | ||||
repository username, date is the commit date in any format | repository username, date is the commit date in any format | ||||
supported by util.parsedate() and defaults to current date, extra | supported by dateutil.parsedate() and defaults to current date, extra | ||||
is a dictionary of metadata or is left empty. | is a dictionary of metadata or is left empty. | ||||
""" | """ | ||||
# Mercurial <= 3.1 expects the filectxfn to raise IOError for missing files. | # Mercurial <= 3.1 expects the filectxfn to raise IOError for missing files. | ||||
# Extensions that need to retain compatibility across Mercurial 3.1 can use | # Extensions that need to retain compatibility across Mercurial 3.1 can use | ||||
# this field to determine what to do in filectxfn. | # this field to determine what to do in filectxfn. | ||||
_returnnoneformissingfiles = True | _returnnoneformissingfiles = True | ||||
Revision information is supplied at initialization time. 'repo' is the | Revision information is supplied at initialization time. 'repo' is the | ||||
current localrepo, 'ctx' is original revision which manifest we're reuisng | current localrepo, 'ctx' is original revision which manifest we're reuisng | ||||
'parents' is a sequence of two parent revisions identifiers (pass None for | 'parents' is a sequence of two parent revisions identifiers (pass None for | ||||
every missing parent), 'text' is the commit. | every missing parent), 'text' is the commit. | ||||
user receives the committer name and defaults to current repository | user receives the committer name and defaults to current repository | ||||
username, date is the commit date in any format supported by | username, date is the commit date in any format supported by | ||||
util.parsedate() and defaults to current date, extra is a dictionary of | dateutil.parsedate() and defaults to current date, extra is a dictionary of | ||||
metadata or is left empty. | metadata or is left empty. | ||||
""" | """ | ||||
def __new__(cls, repo, originalctx, *args, **kwargs): | def __new__(cls, repo, originalctx, *args, **kwargs): | ||||
return super(metadataonlyctx, cls).__new__(cls, repo) | return super(metadataonlyctx, cls).__new__(cls, repo) | ||||
def __init__(self, repo, originalctx, parents=None, text=None, user=None, | def __init__(self, repo, originalctx, parents=None, text=None, user=None, | ||||
date=None, extra=None, editor=False): | date=None, extra=None, editor=False): | ||||
if text is None: | if text is None: |
@command('debugdate', | @command('debugdate', | ||||
[('e', 'extended', None, _('try extended date formats'))], | [('e', 'extended', None, _('try extended date formats'))], | ||||
_('[-e] DATE [RANGE]'), | _('[-e] DATE [RANGE]'), | ||||
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 = dateutil.parsedate(date, util.extendeddateformats) | ||||
else: | else: | ||||
d = util.parsedate(date) | d = dateutil.parsedate(date) | ||||
ui.write(("internal: %s %s\n") % d) | ui.write(("internal: %s %s\n") % d) | ||||
ui.write(("standard: %s\n") % dateutil.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, | ||||
metadata['user'] = opts['user'] or ui.username() | metadata['user'] = opts['user'] or ui.username() | ||||
succs = tuple(parsenodeid(succ) for succ in successors) | succs = tuple(parsenodeid(succ) for succ in successors) | ||||
l = repo.lock() | l = repo.lock() | ||||
try: | try: | ||||
tr = repo.transaction('debugobsolete') | tr = repo.transaction('debugobsolete') | ||||
try: | try: | ||||
date = opts.get('date') | date = opts.get('date') | ||||
if date: | if date: | ||||
date = util.parsedate(date) | date = dateutil.parsedate(date) | ||||
else: | else: | ||||
date = None | date = None | ||||
prec = parsenodeid(precursor) | prec = parsenodeid(precursor) | ||||
parents = None | parents = None | ||||
if opts['record_parents']: | if opts['record_parents']: | ||||
if prec not in repo.unfiltered(): | if prec not in repo.unfiltered(): | ||||
raise error.Abort('cannot used --record-parents on ' | raise error.Abort('cannot used --record-parents on ' | ||||
'unknown changesets') | 'unknown changesets') |
return True if a new marker have been added, False if the markers | return True if a new marker have been added, False if the markers | ||||
already existed (no op). | already existed (no op). | ||||
""" | """ | ||||
if metadata is None: | if metadata is None: | ||||
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 = dateutil.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 = dateutil.makedate() | date = dateutil.makedate() | ||||
else: | else: | ||||
date = dateutil.makedate() | date = dateutil.makedate() | ||||
if len(prec) != 20: | if len(prec) != 20: | ||||
raise ValueError(prec) | raise ValueError(prec) |
"""Converts a date to the specified timezone. | """Converts a date to the specified timezone. | ||||
The default is local date.""" | The default is local date.""" | ||||
if not (1 <= len(args) <= 2): | if not (1 <= len(args) <= 2): | ||||
# i18n: "localdate" is a keyword | # i18n: "localdate" is a keyword | ||||
raise error.ParseError(_("localdate expects one or two arguments")) | raise error.ParseError(_("localdate expects one or two arguments")) | ||||
date = evalfuncarg(context, mapping, args[0]) | date = evalfuncarg(context, mapping, args[0]) | ||||
try: | try: | ||||
date = util.parsedate(date) | date = dateutil.parsedate(date) | ||||
except AttributeError: # not str nor date tuple | except AttributeError: # not str nor date tuple | ||||
# i18n: "localdate" is a keyword | # i18n: "localdate" is a keyword | ||||
raise error.ParseError(_("localdate expects a date information")) | raise error.ParseError(_("localdate expects a date information")) | ||||
if len(args) >= 2: | if len(args) >= 2: | ||||
tzoffset = None | tzoffset = None | ||||
tz = evalfuncarg(context, mapping, args[1]) | tz = evalfuncarg(context, mapping, args[1]) | ||||
if isinstance(tz, str): | if isinstance(tz, str): | ||||
tzoffset, remainder = dateutil.parsetimezone(tz) | tzoffset, remainder = dateutil.parsetimezone(tz) |
error, | error, | ||||
formatter, | formatter, | ||||
progress, | progress, | ||||
pycompat, | pycompat, | ||||
rcutil, | rcutil, | ||||
scmutil, | scmutil, | ||||
util, | util, | ||||
) | ) | ||||
from .utils import dateutil | |||||
urlreq = util.urlreq | urlreq = util.urlreq | ||||
# for use with str.translate(None, _keepalnum), to keep just alphanumerics | # for use with str.translate(None, _keepalnum), to keep just alphanumerics | ||||
_keepalnum = ''.join(c for c in map(pycompat.bytechr, range(256)) | _keepalnum = ''.join(c for c in map(pycompat.bytechr, range(256)) | ||||
if not c.isalnum()) | if not c.isalnum()) | ||||
# The config knobs that will be altered (if unset) by ui.tweakdefaults. | # The config knobs that will be altered (if unset) by ui.tweakdefaults. | ||||
"""parse a configuration element as a tuple of ints | """parse a configuration element as a tuple of ints | ||||
>>> u = ui(); s = b'foo' | >>> u = ui(); s = b'foo' | ||||
>>> u.setconfig(s, b'date', b'0 0') | >>> u.setconfig(s, b'date', b'0 0') | ||||
>>> u.configdate(s, b'date') | >>> u.configdate(s, b'date') | ||||
(0, 0) | (0, 0) | ||||
""" | """ | ||||
if self.config(section, name, default, untrusted): | if self.config(section, name, default, untrusted): | ||||
return self.configwith(util.parsedate, section, name, default, | return self.configwith(dateutil.parsedate, section, name, default, | ||||
'date', untrusted) | 'date', untrusted) | ||||
if default is _unset: | if default is _unset: | ||||
return None | return None | ||||
return default | return default | ||||
def hasconfig(self, section, name, untrusted=False): | def hasconfig(self, section, name, untrusted=False): | ||||
return self._data(untrusted).hasitem(section, name) | return self._data(untrusted).hasitem(section, name) | ||||
from __future__ import absolute_import, print_function | from __future__ import absolute_import, print_function | ||||
import abc | import abc | ||||
import bz2 | import bz2 | ||||
import codecs | import codecs | ||||
import collections | import collections | ||||
import contextlib | import contextlib | ||||
import datetime | |||||
import errno | import errno | ||||
import gc | import gc | ||||
import hashlib | import hashlib | ||||
import imp | import imp | ||||
import itertools | import itertools | ||||
import mmap | import mmap | ||||
import os | import os | ||||
import platform as pyplatform | import platform as pyplatform | ||||
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 parsedate(date, formats=None, bias=None): | |||||
"""parse a localized date/time and return a (unixtime, offset) tuple. | |||||
The date may be a "unixtime offset" string or in one of the specified | |||||
formats. If the date already is a (unixtime, offset) tuple, it is returned. | |||||
>>> parsedate(b' today ') == parsedate( | |||||
... datetime.date.today().strftime('%b %d').encode('ascii')) | |||||
True | |||||
>>> parsedate(b'yesterday ') == parsedate( | |||||
... (datetime.date.today() - datetime.timedelta(days=1) | |||||
... ).strftime('%b %d').encode('ascii')) | |||||
True | |||||
>>> now, tz = dateutil.makedate() | |||||
>>> strnow, strtz = parsedate(b'now') | |||||
>>> (strnow - now) < 1 | |||||
True | |||||
>>> tz == strtz | |||||
True | |||||
""" | |||||
if bias is None: | |||||
bias = {} | |||||
if not date: | |||||
return 0, 0 | |||||
if isinstance(date, tuple) and len(date) == 2: | |||||
return date | |||||
if not formats: | |||||
formats = defaultdateformats | |||||
date = date.strip() | |||||
if date == 'now' or date == _('now'): | |||||
return dateutil.makedate() | |||||
if date == 'today' or date == _('today'): | |||||
date = datetime.date.today().strftime(r'%b %d') | |||||
date = encoding.strtolocal(date) | |||||
elif date == 'yesterday' or date == _('yesterday'): | |||||
date = (datetime.date.today() - | |||||
datetime.timedelta(days=1)).strftime(r'%b %d') | |||||
date = encoding.strtolocal(date) | |||||
try: | |||||
when, offset = map(int, date.split(' ')) | |||||
except ValueError: | |||||
# fill out defaults | |||||
now = dateutil.makedate() | |||||
defaults = {} | |||||
for part in ("d", "mb", "yY", "HI", "M", "S"): | |||||
# this piece is for rounding the specific end of unknowns | |||||
b = bias.get(part) | |||||
if b is None: | |||||
if part[0:1] in "HMS": | |||||
b = "00" | |||||
else: | |||||
b = "0" | |||||
# this piece is for matching the generic end to today's date | |||||
n = dateutil.datestr(now, "%" + part[0:1]) | |||||
defaults[part] = (b, n) | |||||
for format in formats: | |||||
try: | |||||
when, offset = dateutil.strdate(date, format, defaults) | |||||
except (ValueError, OverflowError): | |||||
pass | |||||
else: | |||||
break | |||||
else: | |||||
raise error.ParseError(_('invalid date: %r') % date) | |||||
# validate explicit (probably user-specified) date and | |||||
# time zone offset. values must fit in signed 32 bits for | |||||
# current 32-bit linux runtimes. timezones go from UTC-12 | |||||
# to UTC+14 | |||||
if when < -0x80000000 or when > 0x7fffffff: | |||||
raise error.ParseError(_('date exceeds 32 bits: %d') % when) | |||||
if offset < -50400 or offset > 43200: | |||||
raise error.ParseError(_('impossible time zone offset: %d') % offset) | |||||
return when, offset | |||||
def matchdate(date): | def matchdate(date): | ||||
"""Return a function that matches a given date match specifier | """Return a function that matches a given date match specifier | ||||
Formats include: | Formats include: | ||||
'{date}' match a given date to the accuracy provided | '{date}' match a given date to the accuracy provided | ||||
'<{date}' on or before a given date | '<{date}' on or before a given date | ||||
'>{date}' on or after a given date | '>{date}' on or after a given date | ||||
>>> p1 = parsedate(b"10:29:59") | >>> p1 = dateutil.parsedate(b"10:29:59") | ||||
>>> p2 = parsedate(b"10:30:00") | >>> p2 = dateutil.parsedate(b"10:30:00") | ||||
>>> p3 = parsedate(b"10:30:59") | >>> p3 = dateutil.parsedate(b"10:30:59") | ||||
>>> p4 = parsedate(b"10:31:00") | >>> p4 = dateutil.parsedate(b"10:31:00") | ||||
>>> p5 = parsedate(b"Sep 15 10:30:00 1999") | >>> p5 = dateutil.parsedate(b"Sep 15 10:30:00 1999") | ||||
>>> f = matchdate(b"10:30") | >>> f = matchdate(b"10:30") | ||||
>>> f(p1[0]) | >>> f(p1[0]) | ||||
False | False | ||||
>>> f(p2[0]) | >>> f(p2[0]) | ||||
True | True | ||||
>>> f(p3[0]) | >>> f(p3[0]) | ||||
True | True | ||||
>>> f(p4[0]) | >>> f(p4[0]) | ||||
False | False | ||||
>>> f(p5[0]) | >>> f(p5[0]) | ||||
False | False | ||||
""" | """ | ||||
def lower(date): | def lower(date): | ||||
d = {'mb': "1", 'd': "1"} | d = {'mb': "1", 'd': "1"} | ||||
return parsedate(date, extendeddateformats, d)[0] | return dateutil.parsedate(date, extendeddateformats, d)[0] | ||||
def upper(date): | def upper(date): | ||||
d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"} | d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"} | ||||
for days in ("31", "30", "29"): | for days in ("31", "30", "29"): | ||||
try: | try: | ||||
d["d"] = days | d["d"] = days | ||||
return parsedate(date, extendeddateformats, d)[0] | return dateutil.parsedate(date, extendeddateformats, d)[0] | ||||
except Abort: | except Abort: | ||||
pass | pass | ||||
d["d"] = "28" | d["d"] = "28" | ||||
return parsedate(date, extendeddateformats, d)[0] | return dateutil.parsedate(date, extendeddateformats, d)[0] | ||||
date = date.strip() | date = date.strip() | ||||
if not date: | if not date: | ||||
raise Abort(_("dates cannot consist entirely of whitespace")) | raise Abort(_("dates cannot consist entirely of whitespace")) | ||||
elif date[0] == "<": | elif date[0] == "<": | ||||
if not date[1:]: | if not date[1:]: | ||||
raise Abort(_("invalid day spec, use '<DATE'")) | raise Abort(_("invalid day spec, use '<DATE'")) | ||||
return dateutil.parsetimezone(*args, **kwargs) | return dateutil.parsetimezone(*args, **kwargs) | ||||
def strdate(*args, **kwargs): | def strdate(*args, **kwargs): | ||||
msg = ("'util.strdate' is deprecated, " | msg = ("'util.strdate' is deprecated, " | ||||
"use 'utils.dateutil.strdate'") | "use 'utils.dateutil.strdate'") | ||||
nouideprecwarn(msg, "4.6") | nouideprecwarn(msg, "4.6") | ||||
return dateutil.strdate(*args, **kwargs) | return dateutil.strdate(*args, **kwargs) | ||||
def parsedate(*args, **kwargs): | |||||
msg = ("'util.parsedate' is deprecated, " | |||||
"use 'utils.dateutil.parsedate'") | |||||
nouideprecwarn(msg, "4.6") | |||||
return dateutil.parsedate(*args, **kwargs) | |||||
if offset is None: | if offset is None: | ||||
# local timezone | # local timezone | ||||
unixtime = int(time.mktime(timetuple)) | unixtime = int(time.mktime(timetuple)) | ||||
offset = unixtime - localunixtime | offset = unixtime - localunixtime | ||||
else: | else: | ||||
unixtime = localunixtime + offset | unixtime = localunixtime + offset | ||||
return unixtime, offset | return unixtime, offset | ||||
def parsedate(date, formats=None, bias=None): | |||||
"""parse a localized date/time and return a (unixtime, offset) tuple. | |||||
The date may be a "unixtime offset" string or in one of the specified | |||||
formats. If the date already is a (unixtime, offset) tuple, it is returned. | |||||
>>> parsedate(b' today ') == parsedate( | |||||
... datetime.date.today().strftime('%b %d').encode('ascii')) | |||||
True | |||||
>>> parsedate(b'yesterday ') == parsedate( | |||||
... (datetime.date.today() - datetime.timedelta(days=1) | |||||
... ).strftime('%b %d').encode('ascii')) | |||||
True | |||||
>>> now, tz = makedate() | |||||
>>> strnow, strtz = parsedate(b'now') | |||||
>>> (strnow - now) < 1 | |||||
True | |||||
>>> tz == strtz | |||||
True | |||||
""" | |||||
if bias is None: | |||||
bias = {} | |||||
if not date: | |||||
return 0, 0 | |||||
if isinstance(date, tuple) and len(date) == 2: | |||||
return date | |||||
if not formats: | |||||
formats = defaultdateformats | |||||
date = date.strip() | |||||
if date == 'now' or date == _('now'): | |||||
return makedate() | |||||
if date == 'today' or date == _('today'): | |||||
date = datetime.date.today().strftime(r'%b %d') | |||||
date = encoding.strtolocal(date) | |||||
elif date == 'yesterday' or date == _('yesterday'): | |||||
date = (datetime.date.today() - | |||||
datetime.timedelta(days=1)).strftime(r'%b %d') | |||||
date = encoding.strtolocal(date) | |||||
try: | |||||
when, offset = map(int, date.split(' ')) | |||||
except ValueError: | |||||
# fill out defaults | |||||
now = makedate() | |||||
defaults = {} | |||||
for part in ("d", "mb", "yY", "HI", "M", "S"): | |||||
# this piece is for rounding the specific end of unknowns | |||||
b = bias.get(part) | |||||
if b is None: | |||||
if part[0:1] in "HMS": | |||||
b = "00" | |||||
else: | |||||
b = "0" | |||||
# this piece is for matching the generic end to today's date | |||||
n = datestr(now, "%" + part[0:1]) | |||||
defaults[part] = (b, n) | |||||
for format in formats: | |||||
try: | |||||
when, offset = strdate(date, format, defaults) | |||||
except (ValueError, OverflowError): | |||||
pass | |||||
else: | |||||
break | |||||
else: | |||||
raise error.ParseError(_('invalid date: %r') % date) | |||||
# validate explicit (probably user-specified) date and | |||||
# time zone offset. values must fit in signed 32 bits for | |||||
# current 32-bit linux runtimes. timezones go from UTC-12 | |||||
# to UTC+14 | |||||
if when < -0x80000000 or when > 0x7fffffff: | |||||
raise error.ParseError(_('date exceeds 32 bits: %d') % when) | |||||
if offset < -50400 or offset > 43200: | |||||
raise error.ParseError(_('impossible time zone offset: %d') % offset) | |||||
return when, offset | |||||
# extension to emulate invoking 'dirstate.write()' at the time | # extension to emulate invoking 'dirstate.write()' at the time | ||||
# specified by '[fakedirstatewritetime] fakenow', only when | # specified by '[fakedirstatewritetime] fakenow', only when | ||||
# 'dirstate.write()' is invoked via functions below: | # 'dirstate.write()' is invoked via functions below: | ||||
# | # | ||||
# - 'workingctx._poststatusfixup()' (= 'repo.status()') | # - 'workingctx._poststatusfixup()' (= 'repo.status()') | ||||
# - 'committablectx.markcommitted()' | # - 'committablectx.markcommitted()' | ||||
from __future__ import absolute_import | from __future__ import absolute_import | ||||
from mercurial import ( | from mercurial import ( | ||||
context, | context, | ||||
dirstate, | dirstate, | ||||
extensions, | extensions, | ||||
policy, | policy, | ||||
registrar, | registrar, | ||||
util, | |||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
configtable = {} | configtable = {} | ||||
configitem = registrar.configitem(configtable) | configitem = registrar.configitem(configtable) | ||||
configitem('fakedirstatewritetime', 'fakenow', | configitem('fakedirstatewritetime', 'fakenow', | ||||
default=None, | default=None, | ||||
) | ) | ||||
# Execute original one, if fakenow isn't configured. This is | # Execute original one, if fakenow isn't configured. This is | ||||
# useful to prevent subrepos from executing replaced one, | # useful to prevent subrepos from executing replaced one, | ||||
# because replacing 'parsers.pack_dirstate' is also effective | # because replacing 'parsers.pack_dirstate' is also effective | ||||
# in subrepos. | # in subrepos. | ||||
return func() | return func() | ||||
# parsing 'fakenow' in YYYYmmddHHMM format makes comparison between | # parsing 'fakenow' in YYYYmmddHHMM format makes comparison between | ||||
# 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy | # 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy | ||||
fakenow = util.parsedate(fakenow, ['%Y%m%d%H%M'])[0] | fakenow = dateutil.parsedate(fakenow, ['%Y%m%d%H%M'])[0] | ||||
orig_pack_dirstate = parsers.pack_dirstate | orig_pack_dirstate = parsers.pack_dirstate | ||||
orig_dirstate_getfsnow = dirstate._getfsnow | orig_dirstate_getfsnow = dirstate._getfsnow | ||||
wrapper = lambda *args: pack_dirstate(fakenow, orig_pack_dirstate, *args) | wrapper = lambda *args: pack_dirstate(fakenow, orig_pack_dirstate, *args) | ||||
parsers.pack_dirstate = wrapper | parsers.pack_dirstate = wrapper | ||||
dirstate._getfsnow = lambda *args: fakenow | dirstate._getfsnow = lambda *args: fakenow | ||||
try: | try: |
# extension to emulate invoking 'patch.internalpatch()' at the time | # extension to emulate invoking 'patch.internalpatch()' at the time | ||||
# specified by '[fakepatchtime] fakenow' | # specified by '[fakepatchtime] fakenow' | ||||
from __future__ import absolute_import | from __future__ import absolute_import | ||||
from mercurial import ( | from mercurial import ( | ||||
extensions, | extensions, | ||||
patch as patchmod, | patch as patchmod, | ||||
registrar, | registrar, | ||||
util, | |||||
) | ) | ||||
from mercurial.utils import dateutil | |||||
configtable = {} | configtable = {} | ||||
configitem = registrar.configitem(configtable) | configitem = registrar.configitem(configtable) | ||||
configitem('fakepatchtime', 'fakenow', | configitem('fakepatchtime', 'fakenow', | ||||
default=None, | default=None, | ||||
) | ) | ||||
def internalpatch(orig, ui, repo, patchobj, strip, | def internalpatch(orig, ui, repo, patchobj, strip, | ||||
prefix='', files=None, | prefix='', files=None, | ||||
eolmode='strict', similarity=0): | eolmode='strict', similarity=0): | ||||
if files is None: | if files is None: | ||||
files = set() | files = set() | ||||
r = orig(ui, repo, patchobj, strip, | r = orig(ui, repo, patchobj, strip, | ||||
prefix=prefix, files=files, | prefix=prefix, files=files, | ||||
eolmode=eolmode, similarity=similarity) | eolmode=eolmode, similarity=similarity) | ||||
fakenow = ui.config('fakepatchtime', 'fakenow') | fakenow = ui.config('fakepatchtime', 'fakenow') | ||||
if fakenow: | if fakenow: | ||||
# parsing 'fakenow' in YYYYmmddHHMM format makes comparison between | # parsing 'fakenow' in YYYYmmddHHMM format makes comparison between | ||||
# 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy | # 'fakenow' value and 'touch -t YYYYmmddHHMM' argument easy | ||||
fakenow = util.parsedate(fakenow, ['%Y%m%d%H%M'])[0] | fakenow = dateutil.parsedate(fakenow, ['%Y%m%d%H%M'])[0] | ||||
for f in files: | for f in files: | ||||
repo.wvfs.utime(f, (fakenow, fakenow)) | repo.wvfs.utime(f, (fakenow, fakenow)) | ||||
return r | return r | ||||
def extsetup(ui): | def extsetup(ui): | ||||
extensions.wrapfunction(patchmod, 'internalpatch', internalpatch) | extensions.wrapfunction(patchmod, 'internalpatch', internalpatch) |