annotate mercurial/ignore.py @ 25163:3139900f31b1

ignore: remove .hgignore from ignore list if nonexistent Previously we would always pass the root .hgignore path to the ignore parser. The parser then had to be aware that the first path was special, and not warn if it didn't exist. In preparation for making the ignore file parser more generically usable, let's make the parse logic not aware of this special case, and instead just not pass the root .hgignore in if it doesn't exist.
author Durham Goode <durham@fb.com>
date Sat, 16 May 2015 15:24:43 -0700
parents e91b32d3c67b
children 1e86bb282c71
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
1 # ignore.py - ignored file handling for mercurial
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
2 #
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
4 #
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7622
diff changeset
5 # This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9091
diff changeset
6 # GNU General Public License version 2 or any later version.
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
8 from i18n import _
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
9 import util, match
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8225
diff changeset
10 import re
5640
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
11
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
12 _commentre = None
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
13
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
14 def ignorepats(lines):
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
15 '''parse lines (iterable) of .hgignore text, returning a tuple of
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
16 (patterns, parse errors). These patterns should be given to compile()
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
17 to be validated and converted into a match function.'''
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
18 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
19 syntax = 'relre:'
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
20 patterns = []
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
21 warnings = []
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
22
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
23 for line in lines:
5640
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
24 if "#" in line:
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
25 global _commentre
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
26 if not _commentre:
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
27 _commentre = re.compile(r'((^|[^\\])(\\\\)*)#.*')
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
28 # remove comments prefixed by an even number of escapes
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
29 line = _commentre.sub(r'\1', line)
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
30 # fixup properly escaped comments that survived the above
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
31 line = line.replace("\\#", "#")
04c76f296ad6 ignore: fix up comment parsing
Matt Mackall <mpm@selenic.com>
parents: 5271
diff changeset
32 line = line.rstrip()
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
33 if not line:
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
34 continue
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
35
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
36 if line.startswith('syntax:'):
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
37 s = line[7:].strip()
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
38 try:
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
39 syntax = syntaxes[s]
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
40 except KeyError:
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
41 warnings.append(_("ignoring invalid syntax '%s'") % s)
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
42 continue
25066
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
43
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
44 linesyntax = syntax
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
45 for s, rels in syntaxes.iteritems():
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
46 if line.startswith(rels):
25066
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
47 linesyntax = rels
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
48 line = line[len(rels):]
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
49 break
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
50 elif line.startswith(s+':'):
25066
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
51 linesyntax = rels
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
52 line = line[len(s) + 1:]
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
53 break
25066
e91b32d3c67b ignore: refactor syntax concatenation
Durham Goode <durham@fb.com>
parents: 25065
diff changeset
54 patterns.append(linesyntax + line)
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
55
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
56 return patterns, warnings
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
57
25163
3139900f31b1 ignore: remove .hgignore from ignore list if nonexistent
Durham Goode <durham@fb.com>
parents: 25066
diff changeset
58 def readignorefile(filepath, warn):
25065
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
59 try:
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
60 pats = []
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
61 fp = open(filepath)
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
62 pats, warnings = ignorepats(fp)
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
63 fp.close()
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
64 for warning in warnings:
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
65 warn("%s: %s\n" % (filepath, warning))
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
66 except IOError, inst:
25163
3139900f31b1 ignore: remove .hgignore from ignore list if nonexistent
Durham Goode <durham@fb.com>
parents: 25066
diff changeset
67 warn(_("skipping unreadable ignore file '%s': %s\n") %
3139900f31b1 ignore: remove .hgignore from ignore list if nonexistent
Durham Goode <durham@fb.com>
parents: 25066
diff changeset
68 (filepath, inst.strerror))
25065
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
69 return pats
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
70
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
71 def readpats(root, files, warn):
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
72 '''return a dict mapping ignore-file-name to list-of-patterns'''
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
73
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
74 pats = {}
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
75 for f in files:
18088
52620e5db2f6 ignore: only read an ignore file once
Bryan O'Sullivan <bryano@fb.com>
parents: 18087
diff changeset
76 if f in pats:
52620e5db2f6 ignore: only read an ignore file once
Bryan O'Sullivan <bryano@fb.com>
parents: 18087
diff changeset
77 continue
25163
3139900f31b1 ignore: remove .hgignore from ignore list if nonexistent
Durham Goode <durham@fb.com>
parents: 25066
diff changeset
78 pats[f] = readignorefile(f, warn)
25065
8cf7f0c4cb14 ignore: refactor file read into a function
Durham Goode <durham@fb.com>
parents: 18089
diff changeset
79
18089
0127366df8fe ignore: process hgignore files in deterministic order
Bryan O'Sullivan <bryano@fb.com>
parents: 18088
diff changeset
80 return [(f, pats[f]) for f in files if f in pats]
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
81
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
82 def ignore(root, files, warn):
9091
79a886bcf461 ignore: separate pattern extraction from match compilation
Brendan Cully <brendan@kublai.com>
parents: 8567
diff changeset
83 '''return matcher covering patterns in 'files'.
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
84
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
85 the files parsed for patterns include:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
86 .hgignore in the repository root
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
87 any additional files specified in the [ui] section of ~/.hgrc
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
88
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
89 trailing white space is dropped.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
90 the escape character is backslash.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
91 comments start with #.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
92 empty lines are skipped.
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
93
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
94 lines can be of the following formats:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
95
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
96 syntax: regexp # defaults following lines to non-rooted regexps
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
97 syntax: glob # defaults following lines to non-rooted globs
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
98 re:pattern # non-rooted regular expression
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
99 glob:pattern # non-rooted glob
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
100 pattern # pattern of the current default type'''
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
101
18087
5712e3b12274 ignore: refactor ignore into two functions
Bryan O'Sullivan <bryano@fb.com>
parents: 18054
diff changeset
102 pats = readpats(root, files, warn)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
103
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
104 allpats = []
18089
0127366df8fe ignore: process hgignore files in deterministic order
Bryan O'Sullivan <bryano@fb.com>
parents: 18088
diff changeset
105 for f, patlist in pats:
13412
58c497d0e44d remove unnecessary list comprehensions
Martin Geisler <mg@aragost.com>
parents: 10263
diff changeset
106 allpats.extend(patlist)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
107 if not allpats:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
108 return util.never
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
109
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
110 try:
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
111 ignorefunc = match.match(root, '', [], allpats)
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
112 except util.Abort:
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
113 # Re-raise an exception where the src is the right file
18089
0127366df8fe ignore: process hgignore files in deterministic order
Bryan O'Sullivan <bryano@fb.com>
parents: 18088
diff changeset
114 for f, patlist in pats:
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
115 try:
8567
fea40a677d43 match: add some default args
Matt Mackall <mpm@selenic.com>
parents: 8566
diff changeset
116 match.match(root, '', [], patlist)
8566
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
117 except util.Abort, inst:
744d6322b05b match: change all users of util.matcher to match.match
Matt Mackall <mpm@selenic.com>
parents: 8312
diff changeset
118 raise util.Abort('%s: %s' % (f, inst[0]))
4609
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
119
b43f17691ae6 dirstate: move ignore to its own file
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
120 return ignorefunc