1
# Copyright 2002 Ben Escoto
3
# This file is part of duplicity.
5
# duplicity is free software; you can redistribute it and/or modify it
6
# under the terms of the GNU General Public License as published by
7
# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA
8
# 02139, USA; either version 2 of the License, or (at your option) any
9
# later version; incorporated herein by reference.
11
"""Manage temporary files"""
14
import log, path, file_naming
18
def register_filename(filename):
19
"""Add filename to tempfile list"""
20
assert not filename in tempfile_names
21
tempfile_names.append(filename)
23
def unregister_filename(filename):
24
"""Remove filename from tempfile list"""
25
try: index = tempfile_names.index(filename)
26
except ValueError: log.Log("Warning, %s is not a registered tempfile" %
28
else: del tempfile_names[index]
31
"""Delete all existing tempfiles"""
32
for filename in tempfile_names:
33
log.Warn("%s still in tempfile list, deleting" % (filename,))
34
p = path.Path(filename)
35
if p.exists(): p.delete()
39
"""Return a new TempPath"""
40
filename = tempfile.mktemp()
41
register_filename(filename)
42
return TempPath(filename)
44
class TempPath(path.Path):
45
"""Path object used as a temporary file"""
47
"""Unregister and delete"""
48
path.Path.delete(self)
49
unregister_filename(self.name)
51
def open_with_delete(self, mode):
52
"""Returns a fileobj. When that is closed, delete file"""
53
fh = FileobjHooked(path.Path.open(self, mode))
54
fh.addhook(self.delete)
58
def get_fileobj_duppath(dirpath, filename):
59
"""Return a file object open for writing, will write to filename
61
Data will be processed and written to a temporary file. When the
62
return fileobject is closed, rename to final position. filename
63
must be a recognizable duplicity data file.
66
oldtempdir = tempfile.tempdir
67
tempfile.tempdir = dirpath.name
68
tdp = new_tempduppath(file_naming.parse(filename))
69
tempfile.tempdir = oldtempdir
70
fh = FileobjHooked(tdp.filtered_open("wb"))
71
fh.addhook(lambda: tdp.rename(dirpath.append(filename)))
74
def new_tempduppath(parseresults):
75
"""Return a new TempDupPath, using settings from parseresults"""
76
filename = tempfile.mktemp()
77
register_filename(filename)
78
return TempDupPath(filename, parseresults = parseresults)
80
class TempDupPath(path.DupPath):
81
"""Like TempPath, but build around DupPath"""
83
"""Unregister and delete"""
84
path.DupPath.delete(self)
85
unregister_filename(self.name)
87
def filtered_open_with_delete(self, mode):
88
"""Returns a filtered fileobj. When that is closed, delete file"""
89
fh = FileobjHooked(path.DupPath.filtered_open(self, mode))
90
fh.addhook(self.delete)
93
def open_with_delete(self, mode = "rb"):
94
"""Returns a fileobj. When that is closed, delete file"""
95
assert mode == "rb" # Why write a file and then close it immediately?
96
fh = FileobjHooked(path.DupPath.open(self, mode))
97
fh.addhook(self.delete)
101
"""Simulate a file, but add hook on close"""
102
def __init__(self, fileobj):
103
"""Initializer. fileobj is the file object to simulate"""
104
self.fileobj = fileobj
106
self.hooklist = [] # fill later with thunks to run on close
108
def write(self, buf): return self.fileobj.write(buf)
109
def read(self, length = -1): return self.fileobj.read(length)
112
"""Close fileobj, running hooks right afterwards"""
113
assert not self.fileobj.close()
114
for hook in self.hooklist: hook()
116
def addhook(self, hook):
117
"""Add hook (function taking no arguments) to run upon closing"""
118
self.hooklist.append(hook)