[PATCH] new command debugignore

Martin Geisler mg at lazybytes.net
Sun Jul 4 07:41:39 CDT 2010


Jason Harris <jason at jasonfharris.com> writes:

Hi Jason

> Here is the patch for adding the command debugignore. This is my
> second patch and my Mercurial coding foo is weak, and I am sure I have
> named something wrong, or put something in the wrong place, etc. Thus
> go easy on me with this patch :)
>
> (I raised this with a few people on IRC#mercurial and they thought it
> was a good idea...)
>
> Example syntax:
>
> [Bolt:MacHgDev/MacHg/LocalMercurial/mercurial] MacHg 372(372) $ hg debugignore
> (?:^\.hg|^\.mq|.*.DS_Store|.*.Trash|.*\.xcodeproj/.*\.pbxuser|.*\.xcodeproj/.*\.mode1v3|(?:|.*/)status(?:/|$)|(?:|.*/)guards(?:/|$)|(?:|.*/)[^/]*\.mode1v3(?:/|$))
>
> [Bolt:~] $ hg debugignore /Development/MacHgDev/MacHg/.hgignore
> (?:(?:|.*/)\.DS\_Store(?:/|$)|(?:|.*/)build(?:/|$))

Interesting and I guess this can be used to debug some cases where
people don't understand the regexp generated from their .hgignore files.

However, a more ambitious and interesting command would be one that
tells you exactly which line of which ignore file is responsible for
ignoring a particular file. Something that would allow me to do this:

  % hg debugignore foo/bar/x.c
  .hgignore:17 foo

> # HG changeset patch
> # User jfh <jason at jasonfharris.com>
> # Date 2010-07-03 15:25:52 +0200
> # Node ID 7ca04442899e3a8e745db00ee502450de7f22589
> # Parent  359483f43ffb2e0bd311f80531efe0aebb8f6293
> - Add command debugignore.
> - This will return the regular expression which mercurial uses to determine if a file or
>   folder should be ignored.  Mercurial internally generates this string from the .hgignore
>   files and this just exposes the generated regular expression.

The proper commit message format would be something like this:

  commands: add debugignore command

  This will return the regular expression which Mercurial uses to
  determine if a file or folder should be ignored. Mercurial internally
  generates this string from the .hgignore files and this just exposes
  the generated regular expression.

That is:

  <topic>: <one line summary>
  <blank line>
  <full description wrapped at max 80 characters>

> +def debugignore(ui, repo, *args):
> +    """return the regular expression corresponding to the .hgignore files
> +
> +    With no .hgignore file arguments, return the regular expression which
> +    represents all the .hgignore files which effect the repositories files.
> +
> +    With one or more .hgignore file arguments return the regular expression
> +    which represents the specified .hgignore files."""
> +    if len(args) == 0:
> +        if not repo:
> +            raise util.Abort(_("There is no Mercurial repository here "
> +                               "(.hg not found)"))
> +        files = [repo.join('.hgignore')]
> +        for name, path in ui.configitems("ui"):
> +            if name == 'ignore' or name.startswith('ignore.'):
> +                files.append(util.expandpath(path))

It seems like you should be able to reuse the logic from
dirstate._ignore, making it public first.

> diff --git a/mercurial/ignore.py b/mercurial/ignore.py
> --- a/mercurial/ignore.py
> +++ b/mercurial/ignore.py
> @@ -101,3 +101,24 @@
>                  raise util.Abort('%s: %s' % (f, inst[0]))
>  
>      return ignorefunc
> +
> +def ignoreregex(files, root, cwd):
> +    pats = {}
> +    for f in files:
> +        try:
> +            pats[f] = []
> +            fp = open(f)
> +            pats[f], warnings = ignorepats(fp)
> +            for warning in warnings:
> +                warn("%s: %s\n" % (f, warning))
> +        except IOError, inst:
> +            if f != files[0]:
> +                warn(_("skipping unreadable ignore file '%s': %s\n") %
> +                     (f, inst.strerror))

There is no warn function in scope here... you've obviously copied this
code from the ignore function just above.

It would make more sense if you changed the ignore function to use this
new function instead of copying code around.

> diff --git a/mercurial/match.py b/mercurial/match.py
> --- a/mercurial/match.py
> +++ b/mercurial/match.py
> @@ -175,6 +175,13 @@
>              res += escape(c)
>      return res
>  
> +def patregex(pats, root, cwd):
> +    """Create a combined regular expression for the given patterns."""
> +
> +    normalizedpats = _normalize(pats, 'glob', root, cwd)
> +    tail = '(?:/|$)'
> +    return '(?:%s)' % '|'.join([_regex(k, p, tail) for (k, p) in normalizedpats])

This comes from match._buildmatch? Again, it would be good to abstract
this into a function of its own.

-- 
Martin Geisler

Mercurial links: http://mercurial.ch/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20100704/5e64be01/attachment.pgp>


More information about the Mercurial-devel mailing list