summaryrefslogtreecommitdiff
path: root/rdiff-backup/rdiff_backup/TempFile.py
diff options
context:
space:
mode:
authorbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2002-12-25 21:12:54 +0000
committerbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2002-12-25 21:12:54 +0000
commit77bf17a39b77dab86274ceb6e415c74ae6a2622f (patch)
treef6202382c3b7bf79c7525e2a1bf10a759706ac46 /rdiff-backup/rdiff_backup/TempFile.py
parent9a0da726e2172321cdc1dcd21441f4ffc41e7931 (diff)
downloadrdiff-backup-77bf17a39b77dab86274ceb6e415c74ae6a2622f.tar.gz
Still refactoring for 0.11.1 - prepare to rename highlevel
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/trunk@253 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
Diffstat (limited to 'rdiff-backup/rdiff_backup/TempFile.py')
-rw-r--r--rdiff-backup/rdiff_backup/TempFile.py100
1 files changed, 100 insertions, 0 deletions
diff --git a/rdiff-backup/rdiff_backup/TempFile.py b/rdiff-backup/rdiff_backup/TempFile.py
new file mode 100644
index 0000000..2b18920
--- /dev/null
+++ b/rdiff-backup/rdiff_backup/TempFile.py
@@ -0,0 +1,100 @@
+# Copyright 2002 Ben Escoto
+#
+# This file is part of rdiff-backup.
+#
+# rdiff-backup is free software; you can redistribute it and/or modify
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# rdiff-backup is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rdiff-backup; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+"""Manage temp files"""
+
+import os
+import Globals, rpath
+
+# This is a connection-specific list of temp files, to be cleaned
+# up before rdiff-backup exits.
+_tempfiles = []
+
+# To make collisions less likely, this gets put in the file name
+# and incremented whenever a new file is requested.
+_tfindex = 0
+
+def new(rp_base, same_dir = 1):
+ """Return new tempfile that isn't in use.
+
+ If same_dir, tempfile will be in same directory as rp_base.
+ Otherwise, use tempfile module to get filename.
+
+ """
+ conn = rp_base.conn
+ if conn is not Globals.local_connection:
+ return conn.TempFile.new(rp_base, same_dir)
+
+ def find_unused(conn, dir):
+ """Find an unused tempfile with connection conn in directory dir"""
+ global _tfindex, tempfiles
+ while 1:
+ if _tfindex > 100000000:
+ Log("Resetting index", 2)
+ _tfindex = 0
+ tf = TempFile(conn, os.path.join(dir,
+ "rdiff-backup.tmp.%d" % _tfindex))
+ _tfindex = _tfindex+1
+ if not tf.lstat(): return tf
+
+ if same_dir: tf = find_unused(conn, rp_base.dirsplit()[0])
+ else: tf = TempFile(conn, tempfile.mktemp())
+ _tempfiles.append(tf)
+ return tf
+
+def remove_listing(tempfile):
+ """Remove listing of tempfile"""
+ if Globals.local_connection is not tempfile.conn:
+ tempfile.conn.TempFile.remove_listing(tempfile)
+ elif tempfile in _tempfiles: _tempfiles.remove(tempfile)
+
+def delete_all():
+ """Delete all remaining tempfiles"""
+ for tf in _tempfiles[:]: tf.delete()
+
+
+class TempFile(rpath.RPath):
+ """Like an RPath, but keep track of which ones are still here"""
+ def rename(self, rp_dest):
+ """Rename temp file to permanent location, possibly overwriting"""
+ if not self.lstat(): # "Moving" empty file, so just delete
+ if rp_dest.lstat(): rp_dest.delete()
+ remove_listing(self)
+ return
+
+ if self.isdir() and not rp_dest.isdir():
+ # Cannot move a directory directly over another file
+ rp_dest.delete()
+ rpath.rename(self, rp_dest)
+
+ # Sometimes this just seems to fail silently, as in one
+ # hardlinked twin is moved over the other. So check to make
+ # sure below.
+ self.setdata()
+ if self.lstat():
+ rp_dest.delete()
+ rpath.rename(self, rp_dest)
+ self.setdata()
+ if self.lstat(): raise OSError("Cannot rename tmp file correctly")
+ remove_listing(self)
+
+ def delete(self):
+ rpath.RPath.delete(self)
+ remove_listing(self)
+