bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
|
409
by Martin Pool
- New AtomicFile class |
1 |
# Copyright (C) 2004, 2005 by Canonical Ltd
|
2 |
||
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
||
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
||
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16 |
||
17 |
||
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
18 |
import codecs |
19 |
import errno |
|
20 |
import os |
|
21 |
import socket |
|
22 |
import sys |
|
|
563
by Martin Pool
- AtomicFile emits a warning if it is gc'd without being closed |
23 |
from warnings import warn |
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
24 |
|
|
1185.31.58
by John Arbash Meinel
Updating for new transport tests so that they pass on win32 |
25 |
from bzrlib.osutils import rename |
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
26 |
|
27 |
# not forksafe - but we dont fork.
|
|
28 |
_pid = os.getpid() |
|
|
563
by Martin Pool
- AtomicFile emits a warning if it is gc'd without being closed |
29 |
|
|
558
by Martin Pool
- All top-level classes inherit from object |
30 |
class AtomicFile(object): |
|
409
by Martin Pool
- New AtomicFile class |
31 |
"""A file that does an atomic-rename to move into place. |
32 |
||
33 |
This also causes hardlinks to break when it's written out.
|
|
34 |
||
35 |
Open this as for a regular file, then use commit() to move into
|
|
36 |
place or abort() to cancel.
|
|
37 |
||
|
431
by Martin Pool
- stat cache is written in utf-8 to accomodate non-ascii |
38 |
An encoding can be specified; otherwise the default is ascii.
|
|
409
by Martin Pool
- New AtomicFile class |
39 |
"""
|
40 |
||
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
41 |
__slots__ = ['f', 'tmpfilename', 'realfilename', 'write'] |
42 |
||
43 |
def __init__(self, filename, mode='wb', new_mode=0666): |
|
44 |
self.f = None |
|
45 |
assert mode in ('wb', 'wt'), \ |
|
46 |
"invalid AtomicFile mode %r" % mode |
|
47 |
||
48 |
# old version:
|
|
49 |
#self.tmpfilename = '%s.%d.%s.tmp' % (filename, os.getpid(),
|
|
50 |
# socket.gethostname())
|
|
51 |
# new version:
|
|
52 |
# This is 'broken' on NFS: it wmay collide with another NFS client.
|
|
53 |
# however, we use this to write files within a directory that we have
|
|
54 |
# locked, so it being racy on NFS is not a concern. The only other
|
|
55 |
# files we use this for are .bzr.ignore, which can race anyhow.
|
|
56 |
self.tmpfilename = '%s.%d.tmp' % (filename, _pid) |
|
|
409
by Martin Pool
- New AtomicFile class |
57 |
self.realfilename = filename |
58 |
||
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
59 |
# Use a low level fd operation to avoid chmodding later.
|
60 |
fd = os.open(self.tmpfilename, os.O_EXCL | os.O_CREAT | os.O_WRONLY, |
|
61 |
new_mode) |
|
62 |
# open a normal python file to get the text vs binary support needed
|
|
63 |
# for windows.
|
|
64 |
try: |
|
65 |
self.f = os.fdopen(fd, mode) |
|
66 |
except: |
|
67 |
os.close(fd) |
|
68 |
raise
|
|
|
409
by Martin Pool
- New AtomicFile class |
69 |
self.write = self.f.write |
|
563
by Martin Pool
- AtomicFile emits a warning if it is gc'd without being closed |
70 |
|
71 |
def __repr__(self): |
|
72 |
return '%s(%r)' % (self.__class__.__name__, |
|
73 |
self.realfilename) |
|
|
409
by Martin Pool
- New AtomicFile class |
74 |
|
75 |
def commit(self): |
|
|
497
by Martin Pool
- new AtomicFile.close() aborts if appropriate |
76 |
"""Close the file and move to final name.""" |
|
410
by Martin Pool
- Fix ignore command and add tests |
77 |
|
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
78 |
if self.f is None: |
|
563
by Martin Pool
- AtomicFile emits a warning if it is gc'd without being closed |
79 |
raise Exception('%r is already closed' % self) |
80 |
||
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
81 |
f = self.f |
|
565
by Martin Pool
- more invariant checks in AtomicFile |
82 |
self.f = None |
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
83 |
f.close() |
|
1185.1.40
by Robert Collins
Merge what applied of Alexander Belchenko's win32 patch. |
84 |
rename(self.tmpfilename, self.realfilename) |
|
409
by Martin Pool
- New AtomicFile class |
85 |
|
86 |
def abort(self): |
|
|
497
by Martin Pool
- new AtomicFile.close() aborts if appropriate |
87 |
"""Discard temporary file without committing changes.""" |
|
563
by Martin Pool
- AtomicFile emits a warning if it is gc'd without being closed |
88 |
|
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
89 |
if self.f is None: |
|
563
by Martin Pool
- AtomicFile emits a warning if it is gc'd without being closed |
90 |
raise Exception('%r is already closed' % self) |
91 |
||
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
92 |
f = self.f |
|
565
by Martin Pool
- more invariant checks in AtomicFile |
93 |
self.f = None |
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
94 |
f.close() |
|
409
by Martin Pool
- New AtomicFile class |
95 |
os.remove(self.tmpfilename) |
|
497
by Martin Pool
- new AtomicFile.close() aborts if appropriate |
96 |
|
97 |
def close(self): |
|
98 |
"""Discard the file unless already committed.""" |
|
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
99 |
if self.f is not None: |
|
497
by Martin Pool
- new AtomicFile.close() aborts if appropriate |
100 |
self.abort() |
|
563
by Martin Pool
- AtomicFile emits a warning if it is gc'd without being closed |
101 |
|
102 |
def __del__(self): |
|
|
1755.3.1
by Robert Collins
Tune the time to build our kernel_like tree : make LocalTransport.put faster, AtomicFile faster, LocalTransport.append faster. |
103 |
if self.f is not None: |
|
563
by Martin Pool
- AtomicFile emits a warning if it is gc'd without being closed |
104 |
warn("%r leaked" % self) |