backupmgr.py
5.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
###############################################################################
# Name: backupmgr.py #
# Purpose: File Backup Manager #
# Author: Cody Precord <cprecord@editra.org> #
# Copyright: (c) 2009 Cody Precord <staff@editra.org> #
# Licence: wxWindows Licence #
###############################################################################
"""
Editra Business Model Library: FileBackupMgr
Helper class for managing and creating backups of files.
"""
__author__ = "Cody Precord <cprecord@editra.org>"
__cvsid__ = "$Id: backupmgr.py 67646 2011-04-29 03:07:20Z CJP $"
__revision__ = "$Revision: 67646 $"
__all__ = [ 'FileBackupMgr', ]
#-----------------------------------------------------------------------------#
# Imports
import os
import shutil
# Local Imports
import fileutil
import fchecker
#-----------------------------------------------------------------------------#
class FileBackupMgr(object):
"""File backup creator and manager"""
def __init__(self, header=None, template=u"%s~"):
"""Create a BackupManager
@keyword header: header to id backups with (Text files only!!)
@keyword template: template string for naming backup file with
"""
super(FileBackupMgr, self).__init__()
# Attributes
self.checker = fchecker.FileTypeChecker()
self.header = header # Backup id header
self.template = template # Filename template
self.bkupdir = u""
def _CheckHeader(self, fname):
"""Check if the backup file has a header that matches the
header used to identify backup files.
@param fname: name of file to check
@return: bool (True if header is ok, False otherwise)
"""
isok = False
handle = None
try:
handle = open(fname, 'r')
line = handle.readline()
handle.close()
isok = line.startswith(self.header)
except Exception, msg:
isok = False
if handle:
handle.close()
return isok
def GetBackupFilename(self, fname):
"""Get the unique name for the files backup copy
@param fname: string (file path)
@return: string
"""
if self.bkupdir:
tmp = fileutil.GetFileName(fname)
fname = os.path.join(self.bkupdir, tmp)
rname = self.template % fname
if self.header is not None and \
not self.checker.IsBinary(fname) and \
os.path.exists(rname):
# Make sure that the template backup name does not match
# an existing file that is not a backup file.
while os.path.exists(rname):
if not self._CheckHeader(rname):
rname = self.template % rname
else:
break
return rname
def GetBackupWriter(self, fileobj):
"""Create a backup filewriter method to backup a files contents
with.
@param fileobj: object implementing fileimpl.FileObjectImpl interface
@return: callable(text) to create backup with
"""
nfile = fileobj.Clone()
fname = self.GetBackupFilename(nfile.GetPath())
nfile.SetPath(fname)
# Write the header if it is enabled
if self.header and not self.checker.IsBinary(fname):
nfile.Write(self.header + os.linesep)
return nfile.Write
def HasBackup(self, fname):
"""Check if a given file has a backup file available or not
@param fname: string (file path)
"""
backup = self.GetBackupFilename(fname)
return os.path.exists(backup)
def IsBackupNewer(self, fname):
"""Is the backup of this file newer than the saved version
of the file?
@param fname: string (file path)
@return: bool
"""
backup = self.GetBackupFilename(fname)
if os.path.exists(fname) and os.path.exists(backup):
mod1 = fileutil.GetFileModTime(backup)
mod2 = fileutil.GetFileModTime(fname)
return mod1 > mod2
else:
return False
def MakeBackupCopy(self, fname):
"""Create a backup copy of the given filename
@param fname: string (file path)
@return: bool (True == Success)
"""
backup = self.GetBackupFilename(fname)
try:
if os.path.exists(backup):
os.remove(backup)
shutil.copy2(fname, backup)
if self.header:
handle = open(backup, 'r')
txt = handle.read()
handle.close()
handle = open(backup, 'w')
handle.write(self.header + os.linesep)
handle.write(txt)
handle.close()
except:
return False
else:
return True
def SetBackupDirectory(self, path):
"""Set the backup directory to use for all backups created by this
manager instance. Setting the path to an empty string will set the
default behavior to write the backup to the same directory as the
where the file that is being backedup is located.
"""
self.bkupdir = path
def SetBackupFileTemplate(self, tstr):
"""Set the filename template for generating the backupfile name
@param tstr: template string i.e) %s~
"""
assert tstr.count("%s") == 1, "Format statment must only have one arg"
self.template = tstr
def SetHeader(self, header):
"""Set the header string for identifying a file as a backup
@param header: string (single line only)
"""
assert '\n' not in header, "Header must only be a single line"
self.header = header