Mercurial > hg
annotate tests/test-copy2.t @ 14007:d764463b433e
atomictempfile: avoid infinite recursion in __del__().
The problem is that a programmer using atomictempfile directly can
make an innocent everyday mistake -- not enough args to the
constructor -- which escalates badly. You would expect a simple
TypeError crash in that case, but you actually get an infinite
recursion that is surprisingly difficult to kill: it happens between
__del__() and __getattr__(), and Python does not handle infinite
recursion from __del__() well.
The fix is to not implement __getattr__(), but instead assign instance
attributes for the methods we wish to delegate to the builtin file
type: write() and fileno(). I've audited mercurial.* and hgext.* and
found no users of atomictempfile using methods other than write() and
rename(). I audited third-party extensions and found one (snap)
passing an atomictempfile to util.fstat(), so I also threw in
fileno().
The last time I submitted a similar patch, Matt proposed that we make
atomictempfile a subclass of file instead of wrapping it. Rejected on
grounds of unnecessary complexity: for one thing, it would make the
Windows implementation of posixfile quite a bit more complex. It would
have to become a subclass of file rather than a simple function -- but
since it's written in C, this is non-obvious and non-trivial.
Furthermore, there's nothing wrong with wrapping objects and
delegating methods: it's a well-established pattern that works just
fine in many cases. Subclassing is not the answer to all of life's
problems.
author | Greg Ward <greg@gerg.ca> |
---|---|
date | Sun, 24 Apr 2011 19:25:10 -0400 |
parents | 92e30e135581 |
children | ec5886db9dc6 |
rev | line source |
---|---|
11940 | 1 $ hg init |
2 $ echo foo > foo | |
3 should fail - foo is not managed | |
4 $ hg mv foo bar | |
5 foo: not copying - file is not managed | |
6 abort: no files to copy | |
12316
4134686b83e1
tests: add exit codes to unified tests
Matt Mackall <mpm@selenic.com>
parents:
11940
diff
changeset
|
7 [255] |
11940 | 8 $ hg st -A |
9 ? foo | |
10 $ hg add foo | |
11 dry-run; print a warning that this is not a real copy; foo is added | |
12 $ hg mv --dry-run foo bar | |
13 foo has not been committed yet, so no copy data will be stored for bar. | |
14 $ hg st -A | |
15 A foo | |
16 should print a warning that this is not a real copy; bar is added | |
17 $ hg mv foo bar | |
18 foo has not been committed yet, so no copy data will be stored for bar. | |
19 $ hg st -A | |
20 A bar | |
21 should print a warning that this is not a real copy; foo is added | |
22 $ hg cp bar foo | |
23 bar has not been committed yet, so no copy data will be stored for foo. | |
24 $ hg rm -f bar | |
25 $ rm bar | |
26 $ hg st -A | |
27 A foo | |
28 $ hg commit -m1 | |
29 | |
30 copy --after to a nonexistant target filename | |
31 $ hg cp -A foo dummy | |
32 foo: not recording copy - dummy does not exist | |
33 | |
34 dry-run; should show that foo is clean | |
35 $ hg copy --dry-run foo bar | |
36 $ hg st -A | |
37 C foo | |
38 should show copy | |
39 $ hg copy foo bar | |
40 $ hg st -C | |
41 A bar | |
42 foo | |
43 | |
44 shouldn't show copy | |
45 $ hg commit -m2 | |
46 $ hg st -C | |
47 | |
48 should match | |
49 $ hg debugindex .hg/store/data/foo.i | |
50 rev offset length base linkrev nodeid p1 p2 | |
51 0 0 5 0 0 2ed2a3912a0b 000000000000 000000000000 | |
52 $ hg debugrename bar | |
53 bar renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd | |
54 | |
55 $ echo bleah > foo | |
56 $ echo quux > bar | |
57 $ hg commit -m3 | |
58 | |
59 should not be renamed | |
60 $ hg debugrename bar | |
61 bar not renamed | |
62 | |
63 $ hg copy -f foo bar | |
64 should show copy | |
65 $ hg st -C | |
66 M bar | |
67 foo | |
68 $ hg commit -m3 | |
69 | |
70 should show no parents for tip | |
71 $ hg debugindex .hg/store/data/bar.i | |
72 rev offset length base linkrev nodeid p1 p2 | |
73 0 0 69 0 1 7711d36246cc 000000000000 000000000000 | |
74 1 69 6 1 2 bdf70a2b8d03 7711d36246cc 000000000000 | |
75 2 75 81 1 3 b2558327ea8d 000000000000 000000000000 | |
76 should match | |
77 $ hg debugindex .hg/store/data/foo.i | |
78 rev offset length base linkrev nodeid p1 p2 | |
79 0 0 5 0 0 2ed2a3912a0b 000000000000 000000000000 | |
80 1 5 7 1 2 dd12c926cf16 2ed2a3912a0b 000000000000 | |
81 $ hg debugrename bar | |
82 bar renamed from foo:dd12c926cf165e3eb4cf87b084955cb617221c17 | |
83 | |
84 should show no copies | |
85 $ hg st -C | |
86 | |
87 copy --after on an added file | |
88 $ cp bar baz | |
89 $ hg add baz | |
90 $ hg cp -A bar baz | |
91 $ hg st -C | |
92 A baz | |
93 bar | |
94 | |
95 foo was clean: | |
96 $ hg st -AC foo | |
97 C foo | |
98 but it's considered modified after a copy --after --force | |
99 $ hg copy -Af bar foo | |
100 $ hg st -AC foo | |
101 M foo | |
102 bar |