diff --git a/hgext/churn.py b/hgext/churn.py --- a/hgext/churn.py +++ b/hgext/churn.py @@ -22,8 +22,8 @@ pycompat, registrar, scmutil, - util, ) +from mercurial.utils import dateutil cmdtable = {} command = registrar.command(cmdtable) @@ -64,7 +64,7 @@ rate = {} df = False if opts.get('date'): - df = util.matchdate(opts['date']) + df = dateutil.matchdate(opts['date']) m = scmutil.match(repo[None], pats, opts) def prep(ctx, fns): diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -2102,7 +2102,7 @@ def finddate(ui, repo, date): """Find the tipmost changeset that matches the given date spec""" - df = util.matchdate(date) + df = dateutil.matchdate(date) m = scmutil.matchall(repo) results = {} diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -563,7 +563,7 @@ ui.write(("internal: %s %s\n") % d) ui.write(("standard: %s\n") % dateutil.datestr(d)) if range: - m = util.matchdate(range) + m = dateutil.matchdate(range) ui.write(("match: %s\n") % m(d[0])) @command('debugdeltachain', diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -30,6 +30,7 @@ smartset, util, ) +from .utils import dateutil # helpers for processing parsed tree getsymbol = revsetlang.getsymbol @@ -663,7 +664,7 @@ """ # i18n: "date" is a keyword ds = getstring(x, _("date requires a string")) - dm = util.matchdate(ds) + dm = dateutil.matchdate(ds) return subset.filter(lambda x: dm(repo[x].date()[0]), condrepr=('', ds)) diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1904,82 +1904,6 @@ limit -= len(s) yield s -def matchdate(date): - """Return a function that matches a given date match specifier - - Formats include: - - '{date}' match a given date to the accuracy provided - - '<{date}' on or before a given date - - '>{date}' on or after a given date - - >>> p1 = dateutil.parsedate(b"10:29:59") - >>> p2 = dateutil.parsedate(b"10:30:00") - >>> p3 = dateutil.parsedate(b"10:30:59") - >>> p4 = dateutil.parsedate(b"10:31:00") - >>> p5 = dateutil.parsedate(b"Sep 15 10:30:00 1999") - >>> f = matchdate(b"10:30") - >>> f(p1[0]) - False - >>> f(p2[0]) - True - >>> f(p3[0]) - True - >>> f(p4[0]) - False - >>> f(p5[0]) - False - """ - - def lower(date): - d = {'mb': "1", 'd': "1"} - return dateutil.parsedate(date, extendeddateformats, d)[0] - - def upper(date): - d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"} - for days in ("31", "30", "29"): - try: - d["d"] = days - return dateutil.parsedate(date, extendeddateformats, d)[0] - except Abort: - pass - d["d"] = "28" - return dateutil.parsedate(date, extendeddateformats, d)[0] - - date = date.strip() - - if not date: - raise Abort(_("dates cannot consist entirely of whitespace")) - elif date[0] == "<": - if not date[1:]: - raise Abort(_("invalid day spec, use '": - if not date[1:]: - raise Abort(_("invalid day spec, use '>DATE'")) - when = lower(date[1:]) - return lambda x: x >= when - elif date[0] == "-": - try: - days = int(date[1:]) - except ValueError: - raise Abort(_("invalid day spec: %s") % date[1:]) - if days < 0: - raise Abort(_("%s must be nonnegative (see 'hg help dates')") - % date[1:]) - when = dateutil.makedate()[0] - days * 3600 * 24 - return lambda x: x >= when - elif " to " in date: - a, b = date.split(" to ") - start, stop = lower(a), upper(b) - return lambda x: x >= start and x <= stop - else: - start, stop = lower(date), upper(date) - return lambda x: x >= start and x <= stop - def stringmatcher(pattern, casesensitive=True): """ accepts a string, possibly starting with 're:' or 'literal:' prefix. @@ -3753,3 +3677,8 @@ nouideprecwarn(msg, "4.6") return dateutil.parsedate(*args, **kwargs) +def matchdate(*args, **kwargs): + msg = ("'util.matchdate' is deprecated, " + "use 'utils.dateutil.matchdate'") + nouideprecwarn(msg, "4.6") + return dateutil.matchdate(*args, **kwargs) diff --git a/mercurial/utils/dateutil.py b/mercurial/utils/dateutil.py --- a/mercurial/utils/dateutil.py +++ b/mercurial/utils/dateutil.py @@ -253,3 +253,78 @@ raise error.ParseError(_('impossible time zone offset: %d') % offset) return when, offset +def matchdate(date): + """Return a function that matches a given date match specifier + + Formats include: + + '{date}' match a given date to the accuracy provided + + '<{date}' on or before a given date + + '>{date}' on or after a given date + + >>> p1 = parsedate(b"10:29:59") + >>> p2 = parsedate(b"10:30:00") + >>> p3 = parsedate(b"10:30:59") + >>> p4 = parsedate(b"10:31:00") + >>> p5 = parsedate(b"Sep 15 10:30:00 1999") + >>> f = matchdate(b"10:30") + >>> f(p1[0]) + False + >>> f(p2[0]) + True + >>> f(p3[0]) + True + >>> f(p4[0]) + False + >>> f(p5[0]) + False + """ + + def lower(date): + d = {'mb': "1", 'd': "1"} + return parsedate(date, extendeddateformats, d)[0] + + def upper(date): + d = {'mb': "12", 'HI': "23", 'M': "59", 'S': "59"} + for days in ("31", "30", "29"): + try: + d["d"] = days + return parsedate(date, extendeddateformats, d)[0] + except error.Abort: + pass + d["d"] = "28" + return parsedate(date, extendeddateformats, d)[0] + + date = date.strip() + + if not date: + raise error.Abort(_("dates cannot consist entirely of whitespace")) + elif date[0] == "<": + if not date[1:]: + raise error.Abort(_("invalid day spec, use '": + if not date[1:]: + raise error.Abort(_("invalid day spec, use '>DATE'")) + when = lower(date[1:]) + return lambda x: x >= when + elif date[0] == "-": + try: + days = int(date[1:]) + except ValueError: + raise error.Abort(_("invalid day spec: %s") % date[1:]) + if days < 0: + raise error.Abort(_("%s must be nonnegative (see 'hg help dates')") + % date[1:]) + when = makedate()[0] - days * 3600 * 24 + return lambda x: x >= when + elif " to " in date: + a, b = date.split(" to ") + start, stop = lower(a), upper(b) + return lambda x: x >= start and x <= stop + else: + start, stop = lower(date), upper(date) + return lambda x: x >= start and x <= stop