##// END OF EJS Templates
fix a bug in dirstate.changes when cwd != repo.root...
Benoit Boissinot -
r1491:91c0e8d7 default
parent child Browse files
Show More
@@ -1,411 +1,412 b''
1 """
1 """
2 dirstate.py - working directory tracking for mercurial
2 dirstate.py - working directory tracking for mercurial
3
3
4 Copyright 2005 Matt Mackall <mpm@selenic.com>
4 Copyright 2005 Matt Mackall <mpm@selenic.com>
5
5
6 This software may be used and distributed according to the terms
6 This software may be used and distributed according to the terms
7 of the GNU General Public License, incorporated herein by reference.
7 of the GNU General Public License, incorporated herein by reference.
8 """
8 """
9
9
10 import struct, os
10 import struct, os
11 from node import *
11 from node import *
12 from i18n import gettext as _
12 from i18n import gettext as _
13 from demandload import *
13 from demandload import *
14 demandload(globals(), "time bisect stat util re errno")
14 demandload(globals(), "time bisect stat util re errno")
15
15
16 class dirstate:
16 class dirstate:
17 def __init__(self, opener, ui, root):
17 def __init__(self, opener, ui, root):
18 self.opener = opener
18 self.opener = opener
19 self.root = root
19 self.root = root
20 self.dirty = 0
20 self.dirty = 0
21 self.ui = ui
21 self.ui = ui
22 self.map = None
22 self.map = None
23 self.pl = None
23 self.pl = None
24 self.copies = {}
24 self.copies = {}
25 self.ignorefunc = None
25 self.ignorefunc = None
26 self.blockignore = False
26 self.blockignore = False
27
27
28 def wjoin(self, f):
28 def wjoin(self, f):
29 return os.path.join(self.root, f)
29 return os.path.join(self.root, f)
30
30
31 def getcwd(self):
31 def getcwd(self):
32 cwd = os.getcwd()
32 cwd = os.getcwd()
33 if cwd == self.root: return ''
33 if cwd == self.root: return ''
34 return cwd[len(self.root) + 1:]
34 return cwd[len(self.root) + 1:]
35
35
36 def hgignore(self):
36 def hgignore(self):
37 '''return the contents of .hgignore as a list of patterns.
37 '''return the contents of .hgignore as a list of patterns.
38
38
39 trailing white space is dropped.
39 trailing white space is dropped.
40 the escape character is backslash.
40 the escape character is backslash.
41 comments start with #.
41 comments start with #.
42 empty lines are skipped.
42 empty lines are skipped.
43
43
44 lines can be of the following formats:
44 lines can be of the following formats:
45
45
46 syntax: regexp # defaults following lines to non-rooted regexps
46 syntax: regexp # defaults following lines to non-rooted regexps
47 syntax: glob # defaults following lines to non-rooted globs
47 syntax: glob # defaults following lines to non-rooted globs
48 re:pattern # non-rooted regular expression
48 re:pattern # non-rooted regular expression
49 glob:pattern # non-rooted glob
49 glob:pattern # non-rooted glob
50 pattern # pattern of the current default type'''
50 pattern # pattern of the current default type'''
51 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
51 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
52 def parselines(fp):
52 def parselines(fp):
53 for line in fp:
53 for line in fp:
54 escape = False
54 escape = False
55 for i in xrange(len(line)):
55 for i in xrange(len(line)):
56 if escape: escape = False
56 if escape: escape = False
57 elif line[i] == '\\': escape = True
57 elif line[i] == '\\': escape = True
58 elif line[i] == '#': break
58 elif line[i] == '#': break
59 line = line[:i].rstrip()
59 line = line[:i].rstrip()
60 if line: yield line
60 if line: yield line
61 pats = []
61 pats = []
62 try:
62 try:
63 fp = open(self.wjoin('.hgignore'))
63 fp = open(self.wjoin('.hgignore'))
64 syntax = 'relre:'
64 syntax = 'relre:'
65 for line in parselines(fp):
65 for line in parselines(fp):
66 if line.startswith('syntax:'):
66 if line.startswith('syntax:'):
67 s = line[7:].strip()
67 s = line[7:].strip()
68 try:
68 try:
69 syntax = syntaxes[s]
69 syntax = syntaxes[s]
70 except KeyError:
70 except KeyError:
71 self.ui.warn(_("ignoring invalid syntax '%s'\n") % s)
71 self.ui.warn(_("ignoring invalid syntax '%s'\n") % s)
72 continue
72 continue
73 pat = syntax + line
73 pat = syntax + line
74 for s in syntaxes.values():
74 for s in syntaxes.values():
75 if line.startswith(s):
75 if line.startswith(s):
76 pat = line
76 pat = line
77 break
77 break
78 pats.append(pat)
78 pats.append(pat)
79 except IOError: pass
79 except IOError: pass
80 return pats
80 return pats
81
81
82 def ignore(self, fn):
82 def ignore(self, fn):
83 '''default match function used by dirstate and localrepository.
83 '''default match function used by dirstate and localrepository.
84 this honours the .hgignore file, and nothing more.'''
84 this honours the .hgignore file, and nothing more.'''
85 if self.blockignore:
85 if self.blockignore:
86 return False
86 return False
87 if not self.ignorefunc:
87 if not self.ignorefunc:
88 ignore = self.hgignore()
88 ignore = self.hgignore()
89 if ignore:
89 if ignore:
90 files, self.ignorefunc, anypats = util.matcher(self.root,
90 files, self.ignorefunc, anypats = util.matcher(self.root,
91 inc=ignore)
91 inc=ignore)
92 else:
92 else:
93 self.ignorefunc = util.never
93 self.ignorefunc = util.never
94 return self.ignorefunc(fn)
94 return self.ignorefunc(fn)
95
95
96 def __del__(self):
96 def __del__(self):
97 if self.dirty:
97 if self.dirty:
98 self.write()
98 self.write()
99
99
100 def __getitem__(self, key):
100 def __getitem__(self, key):
101 try:
101 try:
102 return self.map[key]
102 return self.map[key]
103 except TypeError:
103 except TypeError:
104 self.read()
104 self.read()
105 return self[key]
105 return self[key]
106
106
107 def __contains__(self, key):
107 def __contains__(self, key):
108 if not self.map: self.read()
108 if not self.map: self.read()
109 return key in self.map
109 return key in self.map
110
110
111 def parents(self):
111 def parents(self):
112 if not self.pl:
112 if not self.pl:
113 self.read()
113 self.read()
114 return self.pl
114 return self.pl
115
115
116 def markdirty(self):
116 def markdirty(self):
117 if not self.dirty:
117 if not self.dirty:
118 self.dirty = 1
118 self.dirty = 1
119
119
120 def setparents(self, p1, p2=nullid):
120 def setparents(self, p1, p2=nullid):
121 if not self.pl:
121 if not self.pl:
122 self.read()
122 self.read()
123 self.markdirty()
123 self.markdirty()
124 self.pl = p1, p2
124 self.pl = p1, p2
125
125
126 def state(self, key):
126 def state(self, key):
127 try:
127 try:
128 return self[key][0]
128 return self[key][0]
129 except KeyError:
129 except KeyError:
130 return "?"
130 return "?"
131
131
132 def read(self):
132 def read(self):
133 if self.map is not None: return self.map
133 if self.map is not None: return self.map
134
134
135 self.map = {}
135 self.map = {}
136 self.pl = [nullid, nullid]
136 self.pl = [nullid, nullid]
137 try:
137 try:
138 st = self.opener("dirstate").read()
138 st = self.opener("dirstate").read()
139 if not st: return
139 if not st: return
140 except: return
140 except: return
141
141
142 self.pl = [st[:20], st[20: 40]]
142 self.pl = [st[:20], st[20: 40]]
143
143
144 pos = 40
144 pos = 40
145 while pos < len(st):
145 while pos < len(st):
146 e = struct.unpack(">cllll", st[pos:pos+17])
146 e = struct.unpack(">cllll", st[pos:pos+17])
147 l = e[4]
147 l = e[4]
148 pos += 17
148 pos += 17
149 f = st[pos:pos + l]
149 f = st[pos:pos + l]
150 if '\0' in f:
150 if '\0' in f:
151 f, c = f.split('\0')
151 f, c = f.split('\0')
152 self.copies[f] = c
152 self.copies[f] = c
153 self.map[f] = e[:4]
153 self.map[f] = e[:4]
154 pos += l
154 pos += l
155
155
156 def copy(self, source, dest):
156 def copy(self, source, dest):
157 self.read()
157 self.read()
158 self.markdirty()
158 self.markdirty()
159 self.copies[dest] = source
159 self.copies[dest] = source
160
160
161 def copied(self, file):
161 def copied(self, file):
162 return self.copies.get(file, None)
162 return self.copies.get(file, None)
163
163
164 def update(self, files, state, **kw):
164 def update(self, files, state, **kw):
165 ''' current states:
165 ''' current states:
166 n normal
166 n normal
167 m needs merging
167 m needs merging
168 r marked for removal
168 r marked for removal
169 a marked for addition'''
169 a marked for addition'''
170
170
171 if not files: return
171 if not files: return
172 self.read()
172 self.read()
173 self.markdirty()
173 self.markdirty()
174 for f in files:
174 for f in files:
175 if state == "r":
175 if state == "r":
176 self.map[f] = ('r', 0, 0, 0)
176 self.map[f] = ('r', 0, 0, 0)
177 else:
177 else:
178 s = os.lstat(os.path.join(self.root, f))
178 s = os.lstat(os.path.join(self.root, f))
179 st_size = kw.get('st_size', s.st_size)
179 st_size = kw.get('st_size', s.st_size)
180 st_mtime = kw.get('st_mtime', s.st_mtime)
180 st_mtime = kw.get('st_mtime', s.st_mtime)
181 self.map[f] = (state, s.st_mode, st_size, st_mtime)
181 self.map[f] = (state, s.st_mode, st_size, st_mtime)
182 if self.copies.has_key(f):
182 if self.copies.has_key(f):
183 del self.copies[f]
183 del self.copies[f]
184
184
185 def forget(self, files):
185 def forget(self, files):
186 if not files: return
186 if not files: return
187 self.read()
187 self.read()
188 self.markdirty()
188 self.markdirty()
189 for f in files:
189 for f in files:
190 try:
190 try:
191 del self.map[f]
191 del self.map[f]
192 except KeyError:
192 except KeyError:
193 self.ui.warn(_("not in dirstate: %s!\n") % f)
193 self.ui.warn(_("not in dirstate: %s!\n") % f)
194 pass
194 pass
195
195
196 def clear(self):
196 def clear(self):
197 self.map = {}
197 self.map = {}
198 self.markdirty()
198 self.markdirty()
199
199
200 def write(self):
200 def write(self):
201 st = self.opener("dirstate", "w")
201 st = self.opener("dirstate", "w")
202 st.write("".join(self.pl))
202 st.write("".join(self.pl))
203 for f, e in self.map.items():
203 for f, e in self.map.items():
204 c = self.copied(f)
204 c = self.copied(f)
205 if c:
205 if c:
206 f = f + "\0" + c
206 f = f + "\0" + c
207 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
207 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
208 st.write(e + f)
208 st.write(e + f)
209 self.dirty = 0
209 self.dirty = 0
210
210
211 def filterfiles(self, files):
211 def filterfiles(self, files):
212 ret = {}
212 ret = {}
213 unknown = []
213 unknown = []
214
214
215 for x in files:
215 for x in files:
216 if x is '.':
216 if x is '.':
217 return self.map.copy()
217 return self.map.copy()
218 if x not in self.map:
218 if x not in self.map:
219 unknown.append(x)
219 unknown.append(x)
220 else:
220 else:
221 ret[x] = self.map[x]
221 ret[x] = self.map[x]
222
222
223 if not unknown:
223 if not unknown:
224 return ret
224 return ret
225
225
226 b = self.map.keys()
226 b = self.map.keys()
227 b.sort()
227 b.sort()
228 blen = len(b)
228 blen = len(b)
229
229
230 for x in unknown:
230 for x in unknown:
231 bs = bisect.bisect(b, x)
231 bs = bisect.bisect(b, x)
232 if bs != 0 and b[bs-1] == x:
232 if bs != 0 and b[bs-1] == x:
233 ret[x] = self.map[x]
233 ret[x] = self.map[x]
234 continue
234 continue
235 while bs < blen:
235 while bs < blen:
236 s = b[bs]
236 s = b[bs]
237 if len(s) > len(x) and s.startswith(x) and s[len(x)] == '/':
237 if len(s) > len(x) and s.startswith(x) and s[len(x)] == '/':
238 ret[s] = self.map[s]
238 ret[s] = self.map[s]
239 else:
239 else:
240 break
240 break
241 bs += 1
241 bs += 1
242 return ret
242 return ret
243
243
244 def supported_type(self, f, st, verbose=True):
244 def supported_type(self, f, st, verbose=True):
245 if stat.S_ISREG(st.st_mode):
245 if stat.S_ISREG(st.st_mode):
246 return True
246 return True
247 if verbose:
247 if verbose:
248 kind = 'unknown'
248 kind = 'unknown'
249 if stat.S_ISCHR(st.st_mode): kind = _('character device')
249 if stat.S_ISCHR(st.st_mode): kind = _('character device')
250 elif stat.S_ISBLK(st.st_mode): kind = _('block device')
250 elif stat.S_ISBLK(st.st_mode): kind = _('block device')
251 elif stat.S_ISFIFO(st.st_mode): kind = _('fifo')
251 elif stat.S_ISFIFO(st.st_mode): kind = _('fifo')
252 elif stat.S_ISLNK(st.st_mode): kind = _('symbolic link')
252 elif stat.S_ISLNK(st.st_mode): kind = _('symbolic link')
253 elif stat.S_ISSOCK(st.st_mode): kind = _('socket')
253 elif stat.S_ISSOCK(st.st_mode): kind = _('socket')
254 elif stat.S_ISDIR(st.st_mode): kind = _('directory')
254 elif stat.S_ISDIR(st.st_mode): kind = _('directory')
255 self.ui.warn(_('%s: unsupported file type (type is %s)\n') % (
255 self.ui.warn(_('%s: unsupported file type (type is %s)\n') % (
256 util.pathto(self.getcwd(), f),
256 util.pathto(self.getcwd(), f),
257 kind))
257 kind))
258 return False
258 return False
259
259
260 def statwalk(self, files=None, match=util.always, dc=None):
260 def statwalk(self, files=None, match=util.always, dc=None):
261 self.read()
261 self.read()
262
262
263 # walk all files by default
263 # walk all files by default
264 if not files:
264 if not files:
265 files = [self.root]
265 files = [self.root]
266 if not dc:
266 if not dc:
267 dc = self.map.copy()
267 dc = self.map.copy()
268 elif not dc:
268 elif not dc:
269 dc = self.filterfiles(files)
269 dc = self.filterfiles(files)
270
270
271 def statmatch(file, stat):
271 def statmatch(file, stat):
272 file = util.pconvert(file)
272 file = util.pconvert(file)
273 if file not in dc and self.ignore(file):
273 if file not in dc and self.ignore(file):
274 return False
274 return False
275 return match(file)
275 return match(file)
276
276
277 return self.walkhelper(files=files, statmatch=statmatch, dc=dc)
277 return self.walkhelper(files=files, statmatch=statmatch, dc=dc)
278
278
279 def walk(self, files=None, match=util.always, dc=None):
279 def walk(self, files=None, match=util.always, dc=None):
280 # filter out the stat
280 # filter out the stat
281 for src, f, st in self.statwalk(files, match, dc):
281 for src, f, st in self.statwalk(files, match, dc):
282 yield src, f
282 yield src, f
283
283
284 # walk recursively through the directory tree, finding all files
284 # walk recursively through the directory tree, finding all files
285 # matched by the statmatch function
285 # matched by the statmatch function
286 #
286 #
287 # results are yielded in a tuple (src, filename, st), where src
287 # results are yielded in a tuple (src, filename, st), where src
288 # is one of:
288 # is one of:
289 # 'f' the file was found in the directory tree
289 # 'f' the file was found in the directory tree
290 # 'm' the file was only in the dirstate and not in the tree
290 # 'm' the file was only in the dirstate and not in the tree
291 # and st is the stat result if the file was found in the directory.
291 # and st is the stat result if the file was found in the directory.
292 #
292 #
293 # dc is an optional arg for the current dirstate. dc is not modified
293 # dc is an optional arg for the current dirstate. dc is not modified
294 # directly by this function, but might be modified by your statmatch call.
294 # directly by this function, but might be modified by your statmatch call.
295 #
295 #
296 def walkhelper(self, files, statmatch, dc):
296 def walkhelper(self, files, statmatch, dc):
297 # recursion free walker, faster than os.walk.
297 # recursion free walker, faster than os.walk.
298 def findfiles(s):
298 def findfiles(s):
299 retfiles = []
299 retfiles = []
300 work = [s]
300 work = [s]
301 while work:
301 while work:
302 top = work.pop()
302 top = work.pop()
303 names = os.listdir(top)
303 names = os.listdir(top)
304 names.sort()
304 names.sort()
305 # nd is the top of the repository dir tree
305 # nd is the top of the repository dir tree
306 nd = util.normpath(top[len(self.root) + 1:])
306 nd = util.normpath(top[len(self.root) + 1:])
307 if nd == '.': nd = ''
307 if nd == '.': nd = ''
308 for f in names:
308 for f in names:
309 np = os.path.join(nd, f)
309 np = os.path.join(nd, f)
310 if seen(np):
310 if seen(np):
311 continue
311 continue
312 p = os.path.join(top, f)
312 p = os.path.join(top, f)
313 # don't trip over symlinks
313 # don't trip over symlinks
314 st = os.lstat(p)
314 st = os.lstat(p)
315 if stat.S_ISDIR(st.st_mode):
315 if stat.S_ISDIR(st.st_mode):
316 ds = os.path.join(nd, f +'/')
316 ds = os.path.join(nd, f +'/')
317 if statmatch(ds, st):
317 if statmatch(ds, st):
318 work.append(p)
318 work.append(p)
319 if statmatch(np, st) and np in dc:
319 if statmatch(np, st) and np in dc:
320 yield 'm', util.pconvert(np), st
320 yield 'm', util.pconvert(np), st
321 elif statmatch(np, st):
321 elif statmatch(np, st):
322 if self.supported_type(np, st):
322 if self.supported_type(np, st):
323 yield 'f', util.pconvert(np), st
323 yield 'f', util.pconvert(np), st
324 elif np in dc:
324 elif np in dc:
325 yield 'm', util.pconvert(np), st
325 yield 'm', util.pconvert(np), st
326
326
327 known = {'.hg': 1}
327 known = {'.hg': 1}
328 def seen(fn):
328 def seen(fn):
329 if fn in known: return True
329 if fn in known: return True
330 known[fn] = 1
330 known[fn] = 1
331
331
332 # step one, find all files that match our criteria
332 # step one, find all files that match our criteria
333 files.sort()
333 files.sort()
334 for ff in util.unique(files):
334 for ff in util.unique(files):
335 f = os.path.join(self.root, ff)
335 f = os.path.join(self.root, ff)
336 try:
336 try:
337 st = os.lstat(f)
337 st = os.lstat(f)
338 except OSError, inst:
338 except OSError, inst:
339 if ff not in dc: self.ui.warn('%s: %s\n' % (
339 if ff not in dc: self.ui.warn('%s: %s\n' % (
340 util.pathto(self.getcwd(), ff),
340 util.pathto(self.getcwd(), ff),
341 inst.strerror))
341 inst.strerror))
342 continue
342 continue
343 if stat.S_ISDIR(st.st_mode):
343 if stat.S_ISDIR(st.st_mode):
344 cmp1 = (lambda x, y: cmp(x[1], y[1]))
344 cmp1 = (lambda x, y: cmp(x[1], y[1]))
345 sorted = [ x for x in findfiles(f) ]
345 sorted = [ x for x in findfiles(f) ]
346 sorted.sort(cmp1)
346 sorted.sort(cmp1)
347 for e in sorted:
347 for e in sorted:
348 yield e
348 yield e
349 else:
349 else:
350 ff = util.normpath(ff)
350 ff = util.normpath(ff)
351 if seen(ff):
351 if seen(ff):
352 continue
352 continue
353 self.blockignore = True
353 self.blockignore = True
354 if statmatch(ff, st):
354 if statmatch(ff, st):
355 if self.supported_type(ff, st):
355 if self.supported_type(ff, st):
356 yield 'f', ff, st
356 yield 'f', ff, st
357 elif ff in dc:
357 elif ff in dc:
358 yield 'm', ff, st
358 yield 'm', ff, st
359 self.blockignore = False
359 self.blockignore = False
360
360
361 # step two run through anything left in the dc hash and yield
361 # step two run through anything left in the dc hash and yield
362 # if we haven't already seen it
362 # if we haven't already seen it
363 ks = dc.keys()
363 ks = dc.keys()
364 ks.sort()
364 ks.sort()
365 for k in ks:
365 for k in ks:
366 if not seen(k) and (statmatch(k, None)):
366 if not seen(k) and (statmatch(k, None)):
367 yield 'm', k, None
367 yield 'm', k, None
368
368
369 def changes(self, files=None, match=util.always):
369 def changes(self, files=None, match=util.always):
370 lookup, modified, added, unknown = [], [], [], []
370 lookup, modified, added, unknown = [], [], [], []
371 removed, deleted = [], []
371 removed, deleted = [], []
372
372
373 for src, fn, st in self.statwalk(files, match):
373 for src, fn, st in self.statwalk(files, match):
374 try:
374 try:
375 type, mode, size, time = self[fn]
375 type, mode, size, time = self[fn]
376 except KeyError:
376 except KeyError:
377 unknown.append(fn)
377 unknown.append(fn)
378 continue
378 continue
379 if src == 'm':
379 if src == 'm':
380 nonexistent = True
380 nonexistent = True
381 if not st:
381 if not st:
382 try:
382 try:
383 st = os.lstat(fn)
383 f = os.path.join(self.root, fn)
384 st = os.lstat(f)
384 except OSError, inst:
385 except OSError, inst:
385 if inst.errno != errno.ENOENT:
386 if inst.errno != errno.ENOENT:
386 raise
387 raise
387 st = None
388 st = None
388 # We need to re-check that it is a valid file
389 # We need to re-check that it is a valid file
389 if st and self.supported_type(fn, st):
390 if st and self.supported_type(fn, st):
390 nonexistent = False
391 nonexistent = False
391 # XXX: what to do with file no longer present in the fs
392 # XXX: what to do with file no longer present in the fs
392 # who are not removed in the dirstate ?
393 # who are not removed in the dirstate ?
393 if nonexistent and type in "nm":
394 if nonexistent and type in "nm":
394 deleted.append(fn)
395 deleted.append(fn)
395 continue
396 continue
396 # check the common case first
397 # check the common case first
397 if type == 'n':
398 if type == 'n':
398 if not st:
399 if not st:
399 st = os.stat(fn)
400 st = os.stat(fn)
400 if size != st.st_size or (mode ^ st.st_mode) & 0100:
401 if size != st.st_size or (mode ^ st.st_mode) & 0100:
401 modified.append(fn)
402 modified.append(fn)
402 elif time != st.st_mtime:
403 elif time != st.st_mtime:
403 lookup.append(fn)
404 lookup.append(fn)
404 elif type == 'm':
405 elif type == 'm':
405 modified.append(fn)
406 modified.append(fn)
406 elif type == 'a':
407 elif type == 'a':
407 added.append(fn)
408 added.append(fn)
408 elif type == 'r':
409 elif type == 'r':
409 removed.append(fn)
410 removed.append(fn)
410
411
411 return (lookup, modified, added, removed + deleted, unknown)
412 return (lookup, modified, added, removed + deleted, unknown)
@@ -1,42 +1,45 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 hg init
3 hg init
4 touch a.o
4 touch a.o
5 touch a.c
5 touch a.c
6 touch syntax
6 touch syntax
7 mkdir dir
7 mkdir dir
8 touch dir/a.o
8 touch dir/a.o
9 touch dir/b.o
9 touch dir/b.o
10 touch dir/c.o
10 touch dir/c.o
11
11
12 hg add dir/a.o
12 hg add dir/a.o
13 hg commit -m 0
13 hg commit -m 0
14 hg add dir/b.o
14 hg add dir/b.o
15
15
16 echo "--" ; hg status
16 echo "--" ; hg status
17
17
18 echo "*.o" > .hgignore
18 echo "*.o" > .hgignore
19 echo "--" ; hg status
19 echo "--" ; hg status
20
20
21 echo ".*\.o" > .hgignore
21 echo ".*\.o" > .hgignore
22 echo "--" ; hg status
22 echo "--" ; hg status
23
23
24 # XXX: broken
24 # XXX: broken
25 #echo "glob:**.o" > .hgignore
25 #echo "glob:**.o" > .hgignore
26 #echo "--" ; hg status
26 #echo "--" ; hg status
27 #
27 #
28 #echo "glob:*.o" > .hgignore
28 #echo "glob:*.o" > .hgignore
29 #echo "--" ; hg status
29 #echo "--" ; hg status
30
30
31 echo "syntax: invalid" > .hgignore
31 echo "syntax: invalid" > .hgignore
32 echo "--" ; hg status
32 echo "--" ; hg status
33
33
34 echo "syntax: glob" > .hgignore
34 echo "syntax: glob" > .hgignore
35 echo "*.o" >> .hgignore
35 echo "*.o" >> .hgignore
36 echo "--" ; hg status
36 echo "--" ; hg status
37
37
38 echo "relglob:syntax*" > .hgignore
38 echo "relglob:syntax*" > .hgignore
39 echo "--" ; hg status
39 echo "--" ; hg status
40
40
41 echo "relglob:*" > .hgignore
41 echo "relglob:*" > .hgignore
42 echo "--" ; hg status
42 echo "--" ; hg status
43
44 cd dir
45 echo "--" ; hg status
@@ -1,34 +1,36 b''
1 --
1 --
2 A dir/b.o
2 A dir/b.o
3 ? a.c
3 ? a.c
4 ? a.o
4 ? a.o
5 ? dir/c.o
5 ? dir/c.o
6 ? syntax
6 ? syntax
7 --
7 --
8 abort: invalid pattern: relre:*.o
8 abort: invalid pattern: relre:*.o
9 --
9 --
10 A dir/b.o
10 A dir/b.o
11 ? .hgignore
11 ? .hgignore
12 ? a.c
12 ? a.c
13 ? syntax
13 ? syntax
14 --
14 --
15 ignoring invalid syntax 'invalid'
15 ignoring invalid syntax 'invalid'
16 A dir/b.o
16 A dir/b.o
17 ? .hgignore
17 ? .hgignore
18 ? a.c
18 ? a.c
19 ? a.o
19 ? a.o
20 ? dir/c.o
20 ? dir/c.o
21 ? syntax
21 ? syntax
22 --
22 --
23 A dir/b.o
23 A dir/b.o
24 ? .hgignore
24 ? .hgignore
25 ? a.c
25 ? a.c
26 ? syntax
26 ? syntax
27 --
27 --
28 A dir/b.o
28 A dir/b.o
29 ? .hgignore
29 ? .hgignore
30 ? a.c
30 ? a.c
31 ? a.o
31 ? a.o
32 ? dir/c.o
32 ? dir/c.o
33 --
33 --
34 A dir/b.o
34 A dir/b.o
35 --
36 A b.o
General Comments 0
You need to be logged in to leave comments. Login now