Show More
@@ -0,0 +1,89 b'' | |||
|
1 | #!/bin/sh | |
|
2 | # http://www.selenic.com/mercurial/bts/issue660 | |
|
3 | ||
|
4 | ||
|
5 | hg init a | |
|
6 | cd a | |
|
7 | echo a > a | |
|
8 | mkdir b | |
|
9 | echo b > b/b | |
|
10 | hg commit -A -m "a is file, b is dir" | |
|
11 | ||
|
12 | echo % file replaced with directory | |
|
13 | ||
|
14 | rm a | |
|
15 | mkdir a | |
|
16 | echo a > a/a | |
|
17 | ||
|
18 | echo % should fail - would corrupt dirstate | |
|
19 | hg add a/a | |
|
20 | ||
|
21 | echo % removing shadow | |
|
22 | hg rm --after a | |
|
23 | ||
|
24 | echo % should succeed - shadow removed | |
|
25 | hg add a/a | |
|
26 | ||
|
27 | echo % directory replaced with file | |
|
28 | ||
|
29 | rm -r b | |
|
30 | echo b > b | |
|
31 | ||
|
32 | echo % should fail - would corrupt dirstate | |
|
33 | hg add b | |
|
34 | ||
|
35 | echo % removing shadow | |
|
36 | hg rm --after b/b | |
|
37 | ||
|
38 | echo % should succeed - shadow removed | |
|
39 | hg add b | |
|
40 | ||
|
41 | echo % look what we got | |
|
42 | hg st | |
|
43 | ||
|
44 | echo % revert reintroducing shadow - should fail | |
|
45 | rm -r a b | |
|
46 | hg revert b/b | |
|
47 | ||
|
48 | echo % revert all - should succeed | |
|
49 | hg revert --all | |
|
50 | hg st | |
|
51 | ||
|
52 | echo % addremove | |
|
53 | ||
|
54 | rm -r a b | |
|
55 | mkdir a | |
|
56 | echo a > a/a | |
|
57 | echo b > b | |
|
58 | ||
|
59 | hg addremove | |
|
60 | hg st | |
|
61 | ||
|
62 | echo % commit | |
|
63 | hg ci -A -m "a is dir, b is file" | |
|
64 | hg st --all | |
|
65 | ||
|
66 | echo % long directory replaced with file | |
|
67 | ||
|
68 | mkdir d | |
|
69 | mkdir d/d | |
|
70 | echo d > d/d/d | |
|
71 | hg commit -A -m "d is long directory" | |
|
72 | rm -r d | |
|
73 | echo d > d | |
|
74 | ||
|
75 | echo % should fail - would corrupt dirstate | |
|
76 | hg add d | |
|
77 | ||
|
78 | echo % removing shadow | |
|
79 | hg rm --after d/d/d | |
|
80 | ||
|
81 | echo % should succeed - shadow removed | |
|
82 | hg add d | |
|
83 | ||
|
84 | #echo % update should work | |
|
85 | # | |
|
86 | #hg up -r 0 | |
|
87 | #hg up -r 1 | |
|
88 | ||
|
89 | exit 0 |
@@ -0,0 +1,42 b'' | |||
|
1 | adding a | |
|
2 | adding b/b | |
|
3 | % file replaced with directory | |
|
4 | % should fail - would corrupt dirstate | |
|
5 | abort: file 'a' in dirstate clashes with 'a/a' | |
|
6 | % removing shadow | |
|
7 | % should succeed - shadow removed | |
|
8 | % directory replaced with file | |
|
9 | % should fail - would corrupt dirstate | |
|
10 | abort: directory 'b' already in dirstate | |
|
11 | % removing shadow | |
|
12 | % should succeed - shadow removed | |
|
13 | % look what we got | |
|
14 | A a/a | |
|
15 | A b | |
|
16 | R a | |
|
17 | R b/b | |
|
18 | % revert reintroducing shadow - should fail | |
|
19 | abort: file 'b' in dirstate clashes with 'b/b' | |
|
20 | % revert all - should succeed | |
|
21 | undeleting a | |
|
22 | forgetting a/a | |
|
23 | forgetting b | |
|
24 | undeleting b/b | |
|
25 | % addremove | |
|
26 | removing a | |
|
27 | adding a/a | |
|
28 | adding b | |
|
29 | removing b/b | |
|
30 | A a/a | |
|
31 | A b | |
|
32 | R a | |
|
33 | R b/b | |
|
34 | % commit | |
|
35 | C a/a | |
|
36 | C b | |
|
37 | % long directory replaced with file | |
|
38 | adding d/d/d | |
|
39 | % should fail - would corrupt dirstate | |
|
40 | abort: directory 'd' already in dirstate | |
|
41 | % removing shadow | |
|
42 | % should succeed - shadow removed |
@@ -266,14 +266,15 b' def addremove(repo, pats=[], opts={}, dr' | |||
|
266 | 266 | mapping[abs] = rel, exact |
|
267 | 267 | if repo.ui.verbose or not exact: |
|
268 | 268 | repo.ui.status(_('adding %s\n') % ((pats and rel) or abs)) |
|
269 |
if repo.dirstate[abs] != 'r' and not util.lexists(target) |
|
|
269 | if repo.dirstate[abs] != 'r' and (not util.lexists(target) | |
|
270 | or (os.path.isdir(target) and not os.path.islink(target))): | |
|
270 | 271 | remove.append(abs) |
|
271 | 272 | mapping[abs] = rel, exact |
|
272 | 273 | if repo.ui.verbose or not exact: |
|
273 | 274 | repo.ui.status(_('removing %s\n') % ((pats and rel) or abs)) |
|
274 | 275 | if not dry_run: |
|
276 | repo.remove(remove) | |
|
275 | 277 | repo.add(add) |
|
276 | repo.remove(remove) | |
|
277 | 278 | if similarity > 0: |
|
278 | 279 | for old, new, score in findrenames(repo, add, remove, similarity): |
|
279 | 280 | oldrel, oldexact = mapping[old] |
@@ -50,6 +50,7 b' class dirstate(object):' | |||
|
50 | 50 | elif name == '_dirs': |
|
51 | 51 | self._dirs = {} |
|
52 | 52 | for f in self._map: |
|
53 | if self[f] != 'r': | |
|
53 | 54 | self._incpath(f) |
|
54 | 55 | return self._dirs |
|
55 | 56 | elif name == '_ignore': |
@@ -205,14 +206,25 b' class dirstate(object):' | |||
|
205 | 206 | d = f[:c] |
|
206 | 207 | if d in self._dirs: |
|
207 | 208 | break |
|
208 | if d in self._map: | |
|
209 | if d in self._map and self[d] != 'r': | |
|
209 | 210 | raise util.Abort(_('file %r in dirstate clashes with %r') % |
|
210 | 211 | (d, f)) |
|
211 | 212 | self._incpath(f) |
|
212 | 213 | |
|
214 | def _changepath(self, f, newstate): | |
|
215 | # handle upcoming path changes | |
|
216 | oldstate = self[f] | |
|
217 | if oldstate not in "?r" and newstate in "?r": | |
|
218 | self._decpath(f) | |
|
219 | return | |
|
220 | if oldstate in "?r" and newstate not in "?r": | |
|
221 | self._incpathcheck(f) | |
|
222 | return | |
|
223 | ||
|
213 | 224 | def normal(self, f): |
|
214 | 225 | 'mark a file normal and clean' |
|
215 | 226 | self._dirty = True |
|
227 | self._changepath(f, 'n') | |
|
216 | 228 | s = os.lstat(self._join(f)) |
|
217 | 229 | self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime, 0) |
|
218 | 230 | if self._copymap.has_key(f): |
@@ -221,6 +233,7 b' class dirstate(object):' | |||
|
221 | 233 | def normallookup(self, f): |
|
222 | 234 | 'mark a file normal, but possibly dirty' |
|
223 | 235 | self._dirty = True |
|
236 | self._changepath(f, 'n') | |
|
224 | 237 | self._map[f] = ('n', 0, -1, -1, 0) |
|
225 | 238 | if f in self._copymap: |
|
226 | 239 | del self._copymap[f] |
@@ -228,6 +241,7 b' class dirstate(object):' | |||
|
228 | 241 | def normaldirty(self, f): |
|
229 | 242 | 'mark a file normal, but dirty' |
|
230 | 243 | self._dirty = True |
|
244 | self._changepath(f, 'n') | |
|
231 | 245 | self._map[f] = ('n', 0, -2, -1, 0) |
|
232 | 246 | if f in self._copymap: |
|
233 | 247 | del self._copymap[f] |
@@ -235,7 +249,7 b' class dirstate(object):' | |||
|
235 | 249 | def add(self, f): |
|
236 | 250 | 'mark a file added' |
|
237 | 251 | self._dirty = True |
|
238 |
self._ |
|
|
252 | self._changepath(f, 'a') | |
|
239 | 253 | self._map[f] = ('a', 0, -1, -1, 0) |
|
240 | 254 | if f in self._copymap: |
|
241 | 255 | del self._copymap[f] |
@@ -243,8 +257,8 b' class dirstate(object):' | |||
|
243 | 257 | def remove(self, f): |
|
244 | 258 | 'mark a file removed' |
|
245 | 259 | self._dirty = True |
|
260 | self._changepath(f, 'r') | |
|
246 | 261 | self._map[f] = ('r', 0, 0, 0, 0) |
|
247 | self._decpath(f) | |
|
248 | 262 | if f in self._copymap: |
|
249 | 263 | del self._copymap[f] |
|
250 | 264 | |
@@ -252,6 +266,7 b' class dirstate(object):' | |||
|
252 | 266 | 'mark a file merged' |
|
253 | 267 | self._dirty = True |
|
254 | 268 | s = os.lstat(self._join(f)) |
|
269 | self._changepath(f, 'm') | |
|
255 | 270 | self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime, 0) |
|
256 | 271 | if f in self._copymap: |
|
257 | 272 | del self._copymap[f] |
@@ -260,13 +275,15 b' class dirstate(object):' | |||
|
260 | 275 | 'forget a file' |
|
261 | 276 | self._dirty = True |
|
262 | 277 | try: |
|
278 | self._changepath(f, '?') | |
|
263 | 279 | del self._map[f] |
|
264 | self._decpath(f) | |
|
265 | 280 | except KeyError: |
|
266 | 281 | self._ui.warn(_("not in dirstate: %s!\n") % f) |
|
267 | 282 | |
|
268 | 283 | def clear(self): |
|
269 | 284 | self._map = {} |
|
285 | if "_dirs" in self.__dict__: | |
|
286 | delattr(self, "_dirs"); | |
|
270 | 287 | self._copymap = {} |
|
271 | 288 | self._pl = [nullid, nullid] |
|
272 | 289 | self._dirty = True |
@@ -522,7 +539,7 b' class dirstate(object):' | |||
|
522 | 539 | try: |
|
523 | 540 | st = lstat(_join(fn)) |
|
524 | 541 | except OSError, inst: |
|
525 |
if inst.errno |
|
|
542 | if inst.errno not in (errno.ENOENT, errno.ENOTDIR): | |
|
526 | 543 | raise |
|
527 | 544 | st = None |
|
528 | 545 | # We need to re-check that it is a valid file |
@@ -720,7 +720,7 b' class path_auditor(object):' | |||
|
720 | 720 | except OSError, err: |
|
721 | 721 | # EINVAL can be raised as invalid path syntax under win32. |
|
722 | 722 | # They must be ignored for patterns can be checked too. |
|
723 | if err.errno not in (errno.ENOENT, errno.EINVAL): | |
|
723 | if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL): | |
|
724 | 724 | raise |
|
725 | 725 | else: |
|
726 | 726 | if stat.S_ISLNK(st.st_mode): |
General Comments 0
You need to be logged in to leave comments.
Login now