[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Rdiff-backup-commits] rdiff-backup CHANGELOG rdiff_backup/FilenameMap..
From: |
Josh Nisly |
Subject: |
[Rdiff-backup-commits] rdiff-backup CHANGELOG rdiff_backup/FilenameMap... |
Date: |
Thu, 09 Apr 2009 13:59:20 +0000 |
CVSROOT: /sources/rdiff-backup
Module name: rdiff-backup
Changes by: Josh Nisly <joshn> 09/04/09 13:59:19
Modified files:
. : CHANGELOG
rdiff_backup : FilenameMapping.py eas_acls.py log.py
metadata.py rpath.py statistics.py win_acls.py
Log message:
Use Unicode for paths internally to add support for Unicode on Windows.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/rdiff-backup/CHANGELOG?cvsroot=rdiff-backup&r1=1.370&r2=1.371
http://cvs.savannah.gnu.org/viewcvs/rdiff-backup/rdiff_backup/FilenameMapping.py?cvsroot=rdiff-backup&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/rdiff-backup/rdiff_backup/eas_acls.py?cvsroot=rdiff-backup&r1=1.43&r2=1.44
http://cvs.savannah.gnu.org/viewcvs/rdiff-backup/rdiff_backup/log.py?cvsroot=rdiff-backup&r1=1.25&r2=1.26
http://cvs.savannah.gnu.org/viewcvs/rdiff-backup/rdiff_backup/metadata.py?cvsroot=rdiff-backup&r1=1.32&r2=1.33
http://cvs.savannah.gnu.org/viewcvs/rdiff-backup/rdiff_backup/rpath.py?cvsroot=rdiff-backup&r1=1.138&r2=1.139
http://cvs.savannah.gnu.org/viewcvs/rdiff-backup/rdiff_backup/statistics.py?cvsroot=rdiff-backup&r1=1.23&r2=1.24
http://cvs.savannah.gnu.org/viewcvs/rdiff-backup/rdiff_backup/win_acls.py?cvsroot=rdiff-backup&r1=1.4&r2=1.5
Patches:
Index: CHANGELOG
===================================================================
RCS file: /sources/rdiff-backup/rdiff-backup/CHANGELOG,v
retrieving revision 1.370
retrieving revision 1.371
diff -u -b -r1.370 -r1.371
--- CHANGELOG 31 Mar 2009 17:43:08 -0000 1.370
+++ CHANGELOG 9 Apr 2009 13:59:17 -0000 1.371
@@ -1,6 +1,9 @@
New in v1.3.4 (????/??/??)
---------------------------
+Start using Unicode internally for filenames. This fixes Unicode support
+on Windows (Josh Nisly)
+
Don't print "Fatal Error" if --check-destination-dir completed successfully.
Thanks to Serge Zub for the suggestion. (Andrew Ferguson)
Index: rdiff_backup/FilenameMapping.py
===================================================================
RCS file: /sources/rdiff-backup/rdiff-backup/rdiff_backup/FilenameMapping.py,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- rdiff_backup/FilenameMapping.py 3 Jan 2009 21:32:40 -0000 1.19
+++ rdiff_backup/FilenameMapping.py 9 Apr 2009 13:59:18 -0000 1.20
@@ -158,7 +158,10 @@
correctly and append()ed to the currect QuotedRPath.
"""
- return map(unquote, self.conn.os.listdir(self.path))
+ path = self.path
+ if type(path) != unicode:
+ path = unicode(path, 'utf-8')
+ return map(unquote, self.conn.os.listdir(path))
def __str__(self):
return "QuotedPath: %s\nIndex: %s\nData: %s" % \
Index: rdiff_backup/eas_acls.py
===================================================================
RCS file: /sources/rdiff-backup/rdiff-backup/rdiff_backup/eas_acls.py,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -b -r1.43 -r1.44
--- rdiff_backup/eas_acls.py 2 Mar 2009 18:02:58 -0000 1.43
+++ rdiff_backup/eas_acls.py 9 Apr 2009 13:59:18 -0000 1.44
@@ -57,7 +57,8 @@
def read_from_rp(self, rp):
"""Set the extended attributes from an rpath"""
try:
- attr_list = rp.conn.xattr.listxattr(rp.path, rp.issym())
+ attr_list =
rp.conn.xattr.listxattr(rp.path.encode('utf-8'),
+
rp.issym())
except IOError, exc:
if exc[0] in (errno.EOPNOTSUPP, errno.EPERM,
errno.ETXTBSY):
return # if not supported, consider empty
@@ -74,7 +75,8 @@
continue
try:
self.attr_dict[attr] = \
- rp.conn.xattr.getxattr(rp.path, attr,
rp.issym())
+
rp.conn.xattr.getxattr(rp.path.encode('utf-8'),
+
attr, rp.issym())
except IOError, exc:
# File probably modified while reading, just
continue
if exc[0] == errno.ENODATA: continue
@@ -86,9 +88,11 @@
def clear_rp(self, rp):
"""Delete all the extended attributes in rpath"""
try:
- for name in rp.conn.xattr.listxattr(rp.path,
rp.issym()):
+ for name in
rp.conn.xattr.listxattr(rp.path.encode('utf-8'),
+
rp.issym()):
try:
- rp.conn.xattr.removexattr(rp.path,
name, rp.issym())
+
rp.conn.xattr.removexattr(rp.path.encode('utf-8'),
+
name, rp.issym())
except IOError, exc:
# SELinux attributes cannot be removed,
and we don't want
# to bail out or be too noisy at low
log levels.
@@ -111,7 +115,8 @@
self.clear_rp(rp)
for (name, value) in self.attr_dict.iteritems():
try:
- rp.conn.xattr.setxattr(rp.path, name, value, 0,
rp.issym())
+ rp.conn.xattr.setxattr(rp.path.encode('utf-8'),
name,
+
value, 0, rp.issym())
except IOError, exc:
# Mac and Linux attributes have different
namespaces, so
# fail gracefully if can't call setxattr
@@ -149,13 +154,14 @@
def EA2Record(ea):
"""Convert ExtendedAttributes object to text record"""
- str_list = ['# file: %s' % C.acl_quote(ea.get_indexpath())]
+ str_list = ['# file: %s' %
C.acl_quote(ea.get_indexpath().encode('utf-8'))]
for (name, val) in ea.attr_dict.iteritems():
if not val: str_list.append(name)
else:
encoded_val = base64.encodestring(val).replace('\n', '')
try:
- str_list.append('%s=0s%s' % (C.acl_quote(name),
encoded_val))
+ str_list.append('%s=0s%s' %
(C.acl_quote(name.encode('utf-8')),
+
encoded_val))
except UnicodeEncodeError:
log.Log("Warning: unable to store Unicode
extended attribute %s"
% repr(name), 3)
@@ -169,7 +175,8 @@
raise metadata.ParsingError("Bad record beginning: " +
first[:8])
filename = first[8:]
if filename == '.': index = ()
- else: index = tuple(C.acl_unquote(filename).split('/'))
+ else: index = tuple(unicode(C.acl_unquote(filename.encode('utf-8')),
+
'utf-8').split('/'))
ea = ExtendedAttributes(index)
for line in lines:
@@ -194,7 +201,7 @@
def filename_to_index(self, filename):
"""Convert possibly quoted filename to index tuple"""
if filename == '.': return ()
- else: return tuple(C.acl_unquote(filename).split('/'))
+ else: return
tuple(C.acl_unquote(filename.encode('utf-8')).split('/'))
class ExtendedAttributesFile(metadata.FlatFile):
"""Store/retrieve EAs from extended_attributes file"""
@@ -379,7 +386,7 @@
else: acl = posix1e.ACL()
try:
- acl.applyto(rp.path)
+ acl.applyto(rp.path.encode('utf-8'))
except IOError, exc:
if exc[0] == errno.EOPNOTSUPP:
log.Log("Warning: unable to set ACL on %s: %s" %
@@ -391,12 +398,12 @@
if default_entry_list:
def_acl = list_to_acl(default_entry_list, map_names)
else: def_acl = posix1e.ACL()
- def_acl.applyto(rp.path, posix1e.ACL_TYPE_DEFAULT)
+ def_acl.applyto(rp.path.encode('utf-8'),
posix1e.ACL_TYPE_DEFAULT)
def get_acl_lists_from_rp(rp):
"""Returns (acl_list, def_acl_list) from an rpath. Call locally"""
assert rp.conn is Globals.local_connection
- try: acl = posix1e.ACL(file=rp.path)
+ try: acl = posix1e.ACL(file=rp.path.encode('utf-8'))
except IOError, exc:
if exc[0] == errno.EOPNOTSUPP:
acl = None
@@ -406,7 +413,7 @@
acl = None
else: raise
if rp.isdir():
- try: def_acl = posix1e.ACL(filedef=rp.path)
+ try: def_acl = posix1e.ACL(filedef=rp.path.encode('utf-8'))
except IOError, exc:
if exc[0] == errno.EOPNOTSUPP:
def_acl = None
@@ -533,7 +540,8 @@
def ACL2Record(acl):
"""Convert an AccessControlLists object into a text record"""
- return '# file: %s\n%s\n' % (C.acl_quote(acl.get_indexpath()), str(acl))
+ return '# file: %s\n%s\n' % \
+ (C.acl_quote(acl.get_indexpath().encode('utf-8')), str(acl))
def Record2ACL(record):
"""Convert text record to an AccessControlLists object"""
@@ -543,7 +551,8 @@
raise metadata.ParsingError("Bad record beginning: "+
first_line)
filename = first_line[8:]
if filename == '.': index = ()
- else: index = tuple(C.acl_unquote(filename).split('/'))
+ else: index = tuple(unicode(C.acl_unquote(filename.encode('utf-8')),
+ 'utf-8').split('/'))
return AccessControlLists(index, record[newline_pos:])
class ACLExtractor(EAExtractor):
Index: rdiff_backup/log.py
===================================================================
RCS file: /sources/rdiff-backup/rdiff-backup/rdiff_backup/log.py,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -b -r1.25 -r1.26
--- rdiff_backup/log.py 14 Aug 2007 02:58:20 -0000 1.25
+++ rdiff_backup/log.py 9 Apr 2009 13:59:19 -0000 1.26
@@ -125,7 +125,11 @@
"""Write the message to the log file, if possible"""
if self.log_file_open:
if self.log_file_local:
- self.logfp.write(self.format(message,
self.verbosity))
+ str = self.format(message, self.verbosity)
+ if type(str) != unicode:
+ str = unicode(str, 'utf-8')
+ str = str.encode('utf-8')
+ self.logfp.write(str)
self.logfp.flush()
else: self.log_file_conn.log.Log.log_to_file(message)
@@ -133,7 +137,14 @@
"""Write message to stdout/stderr"""
if verbosity <= 2 or Globals.server: termfp = sys.stderr
else: termfp = sys.stdout
- termfp.write(self.format(message, self.term_verbosity))
+ str = self.format(message, self.term_verbosity)
+ if type(str) != unicode:
+ str = unicode(str, 'utf-8')
+ try:
+ # Try to log as unicode, but fall back to ascii (for
Windows)
+ termfp.write(str.encode('utf-8'))
+ except UnicodeDecodeError:
+ termfp.write(str.encode('ascii', 'replace'))
def conn(self, direction, result, req_num):
"""Log some data on the connection
@@ -165,10 +176,17 @@
def exception_to_string(self, arglist = []):
"""Return string version of current exception plus what's in
arglist"""
type, value, tb = sys.exc_info()
- s = ("Exception '%s' raised of class '%s':\n%s" %
- (value, type, "".join(traceback.format_tb(tb))))
+ s = (u"Exception '%s' raised of class '%s':\n%s" %
+ (value, type, u"".join(traceback.format_tb(tb))))
+ s = s.encode('ascii', 'replace')
if arglist:
- s += "__Arguments:\n" + "\n".join(map(str, arglist))
+ s += "__Arguments:"
+ for arg in arglist:
+ s += "\n"
+ try:
+ s += str(arg)
+ except UnicodeError:
+ s += unicode(arg).encode('ascii',
'replace')
return s
def exception(self, only_terminal = 0, verbosity = 5):
@@ -259,7 +277,8 @@
"""Return log string to put in error log"""
assert (error_type == "ListError" or error_type ==
"UpdateError" or
error_type == "SpecialFileError"), "Unknown
type "+error_type
- return "%s %s %s" % (error_type, cls.get_indexpath(rp),
str(exc))
+ str = u"%s %s %s" % (error_type, cls.get_indexpath(rp),
unicode(exc))
+ return str.encode('utf-8')
def close(cls):
"""Close the error log file"""
Index: rdiff_backup/metadata.py
===================================================================
RCS file: /sources/rdiff-backup/rdiff-backup/rdiff_backup/metadata.py,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- rdiff_backup/metadata.py 27 Sep 2008 00:17:24 -0000 1.32
+++ rdiff_backup/metadata.py 9 Apr 2009 13:59:19 -0000 1.33
@@ -55,7 +55,7 @@
"""
from __future__ import generators
-import re, gzip, os, binascii
+import re, gzip, os, binascii, codecs
import log, Globals, rpath, Time, robust, increment, static, rorpiter
class ParsingError(Exception):
@@ -376,16 +376,18 @@
compress = 1
if mode == 'r':
self.rp = rp_base
- self.fileobj = self.rp.open("rb", compress)
+ self.fileobj = rpath.UnicodeFile(self.rp.open("rb",
compress))
else:
assert mode == 'w'
if compress and check_path and not
rp_base.isinccompressed():
def callback(rp): self.rp = rp
- self.fileobj = rpath.MaybeGzip(rp_base,
callback)
+ self.fileobj =
rpath.UnicodeFile(rpath.MaybeGzip(rp_base,
+
callback))
else:
self.rp = rp_base
assert not self.rp.lstat(), self.rp
- self.fileobj = self.rp.open("wb", compress =
compress)
+ self.fileobj =
rpath.UnicodeFile(self.rp.open("wb",
+
compress = compress))
def write_record(self, record):
"""Write a (text) record into the file"""
Index: rdiff_backup/rpath.py
===================================================================
RCS file: /sources/rdiff-backup/rdiff-backup/rdiff_backup/rpath.py,v
retrieving revision 1.138
retrieving revision 1.139
diff -u -b -r1.138 -r1.139
--- rdiff_backup/rpath.py 8 Mar 2009 17:20:16 -0000 1.138
+++ rdiff_backup/rpath.py 9 Apr 2009 13:59:19 -0000 1.139
@@ -35,7 +35,7 @@
"""
-import os, stat, re, sys, shutil, gzip, socket, time, errno
+import os, stat, re, sys, shutil, gzip, socket, time, errno, codecs
import Globals, Time, static, log, user_group, C
try:
@@ -284,6 +284,8 @@
"""
if os.name != 'nt':
try:
+ if type(filename) == unicode:
+ filename = filename.encode('utf-8')
return C.make_file_dict(filename)
except OSError, error:
# Unicode filenames should be process by the Python
version
@@ -333,7 +335,7 @@
data['nlink'] = statblock[stat.ST_NLINK]
if os.name == 'nt':
- attribs = win32file.GetFileAttributes(filename)
+ attribs = win32file.GetFileAttributesW(filename)
if attribs & winnt.FILE_ATTRIBUTE_REPARSE_POINT:
data['type'] = 'sym'
data['linkname'] = None
@@ -995,7 +997,12 @@
def listdir(self):
"""Return list of string paths returned by os.listdir"""
- return self.conn.os.listdir(self.path)
+ path = self.path
+ # Use pass in unicode to os.listdir, so that the returned
+ # entries are in unicode.
+ if type(path) != unicode:
+ path = unicode(path, 'utf-8')
+ return self.conn.os.listdir(path)
def symlink(self, linktext):
"""Make symlink at self.path pointing to linktext"""
@@ -1406,6 +1413,23 @@
write_win_acl(self, acl)
self.data['win_acl'] = acl
+class UnicodeFile:
+ """ Wraps a RPath and reads/writes unicode. """
+
+ def __init__(self, fileobj):
+ self.fileobj = fileobj
+
+ def read(self, length = -1):
+ return unicode(self.fileobj.read(length), 'utf-8')
+
+ def write(self, buf):
+ if type(buf) != unicode:
+ buf = unicode(buf, 'utf-8')
+ return self.fileobj.write(buf.encode('utf-8'))
+
+ def close(self):
+ return self.fileobj.close()
+
class RPathFileHook:
"""Look like a file, but add closing hook"""
def __init__(self, file, closing_thunk):
@@ -1429,6 +1453,18 @@
messages. Use this class instead to clean those up.
"""
+ def __init__(self, filename=None, mode=None):
+ """ This is needed because we need to write an
+ encoded filename to the file, but use normal
+ unicode with the filename."""
+ if mode and 'b' not in mode:
+ mode += 'b'
+ if type(filename) != unicode:
+ filename = unicode(filename, 'utf-8')
+ fileobj = open(filename, mode or 'rb')
+ gzip.GzipFile.__init__(self, filename.encode('utf-8'),
+ mode=mode,
fileobj=fileobj)
+
def __del__(self): pass
def __getattr__(self, name):
if name == 'fileno': return self.fileobj.fileno
Index: rdiff_backup/statistics.py
===================================================================
RCS file: /sources/rdiff-backup/rdiff-backup/rdiff_backup/statistics.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -b -r1.23 -r1.24
--- rdiff_backup/statistics.py 3 Jan 2009 21:35:59 -0000 1.23
+++ rdiff_backup/statistics.py 9 Apr 2009 13:59:19 -0000 1.24
@@ -20,7 +20,7 @@
"""Generate and process aggregated backup information"""
import re, os, time
-import Globals, Time, increment, log, static, metadata
+import Globals, Time, increment, log, static, metadata, rpath
class StatsException(Exception): pass
@@ -219,13 +219,13 @@
def write_stats_to_rp(self, rp):
"""Write statistics string to given rpath"""
- fp = rp.open("wb")
+ fp = rpath.UnicodeFile(rp.open("wb"))
fp.write(self.get_stats_string())
assert not fp.close()
def read_stats_from_rp(self, rp):
"""Set statistics from rpath, return self for convenience"""
- fp = rp.open("r")
+ fp = rpath.UnicodeFile(rp.open("r"))
self.set_stats_from_string(fp.read())
fp.close()
return self
@@ -364,7 +364,8 @@
suffix = Globals.compression and 'data.gz' or 'data'
cls._rp = increment.get_inc(rpbase, suffix, Time.curtime)
assert not cls._rp.lstat()
- cls._fileobj = cls._rp.open("wb", compress =
Globals.compression)
+ cls._fileobj = rpath.UnicodeFile(cls._rp.open("wb",
+ compress =
Globals.compression))
cls._line_sep = Globals.null_separator and '\0' or '\n'
cls.write_docstring()
Index: rdiff_backup/win_acls.py
===================================================================
RCS file: /sources/rdiff-backup/rdiff-backup/rdiff_backup/win_acls.py,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- rdiff_backup/win_acls.py 24 Nov 2008 22:07:32 -0000 1.4
+++ rdiff_backup/win_acls.py 9 Apr 2009 13:59:19 -0000 1.5
@@ -181,7 +181,7 @@
def __str__(self):
return '# file: %s\n%s\n' % \
- (C.acl_quote(self.get_indexpath()),
unicode(self.__acl))
+ (self.get_indexpath(),
unicode(self.__acl))
def from_string(self, acl_str):
lines = acl_str.splitlines()
@@ -189,7 +189,7 @@
raise metadata.ParsingError("Bad record beginning: " +
lines[0][:8])
filename = lines[0][8:]
if filename == '.': self.index = ()
- else: self.index = tuple(C.acl_unquote(filename).split('/'))
+ else: self.index = tuple(filename.split('/'))
self.__acl = lines[1]
def Record2WACL(record):
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Rdiff-backup-commits] rdiff-backup CHANGELOG rdiff_backup/FilenameMap...,
Josh Nisly <=