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