Merge lp:~aaron-whitehouse/duplicity/08-unicode into lp:~duplicity-team/duplicity/0.8-series

Proposed by Aaron Whitehouse
Status: Merged
Merged at revision: 1286
Proposed branch: lp:~aaron-whitehouse/duplicity/08-unicode
Merge into: lp:~duplicity-team/duplicity/0.8-series
Diff against target: 5231 lines (+1843/-1584)
26 files modified
bin/duplicity.1 (+5/-5)
debian/control (+2/-0)
duplicity/backend.py (+1/-1)
duplicity/commandline.py (+6/-6)
duplicity/globals.py (+1/-1)
duplicity/globmatch.py (+49/-39)
duplicity/path.py (+13/-0)
duplicity/selection.py (+54/-49)
duplicity/util.py (+34/-3)
requirements.txt (+1/-0)
setup.py (+1/-1)
testing/__init__.py (+6/-4)
testing/functional/__init__.py (+54/-26)
testing/functional/test_badupload.py (+1/-1)
testing/functional/test_cleanup.py (+14/-14)
testing/functional/test_final.py (+41/-41)
testing/functional/test_replicate.py (+10/-10)
testing/functional/test_restart.py (+63/-63)
testing/functional/test_selection.py (+660/-578)
testing/functional/test_verify.py (+20/-20)
testing/unit/test_diffdir.py (+0/-2)
testing/unit/test_globmatch.py (+118/-59)
testing/unit/test_gpg.py (+6/-6)
testing/unit/test_patchdir.py (+0/-1)
testing/unit/test_selection.py (+681/-654)
tox.ini (+2/-0)
To merge this branch: bzr merge lp:~aaron-whitehouse/duplicity/08-unicode
Reviewer Review Type Date Requested Status
duplicity-team Pending
Review via email: mp+334622@code.launchpad.net

Commit message

Many strings have been changed to unicode for better handling of international characters and to make the transition to Python 3 significantly easier, primarily on the 'local' side of duplicity (selection, commandline arguments etc) rather than any backends etc.

Description of the change

Many strings have been changed to unicode for better handling of international characters and to make the transition to Python 3 significantly easier.

In order to merge the changes back into trunk as soon as possible, this branch focuses on just the strings in the 'local' side of duplicity, i.e. those involved in interpreting the selection functions from the commandline arguments or include/exclude lists and reading each file from the local filesystem to compare to these selection functions.

Note:
* This branch introduces Path.uc_name with the filename in unicode, in addition to Path.name with the filename in bytes (i.e. each Path will have a .name and .uc_name). These are both created for each Path object and code throughout duplicity should move to using .uc_name where it needs the unicode name and .name where it needs the bytes name, rather than converting. Valid filenames on the disk in Linux can be invalid unicode, so for Python 2 support it is important that we keep the original bytes .name and use that rather than converting the unicode version. That said, for all internal purposes (e.g. string comparison) we should be using the unicode version. From Python 3.2, it looks as though this has been solved properly and os.fsencode/os.fsencode uses 'surrogateescape' characters (https://www.python.org/dev/peps/pep-0383/ ) to ensure you can always recreate the original bytes filename from the internal unicode representation. As I understand it, that should allow the more standard "decode/encode at the boundaries, use unicode everywhere internally" approach.
* Path.name may be renamed Path.b_name in the future: http://lists.nongnu.org/archive/html/duplicity-talk/2017-11/msg00017.html

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'bin/duplicity.1'
--- bin/duplicity.1 2017-09-06 14:57:00 +0000
+++ bin/duplicity.1 2017-12-01 23:01:42 +0000
@@ -1498,11 +1498,11 @@
1498and1498and
1499.BI --exclude-filelist ,1499.BI --exclude-filelist ,
1500options also introduce file selection conditions. They direct1500options also introduce file selection conditions. They direct
1501duplicity to read in a file, each line of which is a file1501duplicity to read in a text file (either ASCII or UTF-8), each line
1502specification, and to include or exclude the matching files. Lines1502of which is a file specification, and to include or exclude the
1503are separated by newlines or nulls, depending on whether the1503matching files. Lines are separated by newlines or nulls, depending
1504--null-separator switch was given. Each line in the filelist will be1504on whether the --null-separator switch was given. Each line in the
1505interpreted as a globbing pattern the way1505filelist will be interpreted as a globbing pattern the way
1506.BI --include1506.BI --include
1507and1507and
1508.BI --exclude1508.BI --exclude
15091509
=== modified file 'debian/control'
--- debian/control 2017-10-12 19:42:50 +0000
+++ debian/control 2017-12-01 23:01:42 +0000
@@ -11,6 +11,7 @@
11 pylint,11 pylint,
12 python-dev,12 python-dev,
13 python-fasteners,13 python-fasteners,
14 python-future,
14 python-mock,15 python-mock,
15 python-pexpect,16 python-pexpect,
16 python-setuptools,17 python-setuptools,
@@ -28,6 +29,7 @@
28 ${shlibs:Depends},29 ${shlibs:Depends},
29 gnupg,30 gnupg,
30 python-fasteners,31 python-fasteners,
32 python-future,
31 python-pexpect,33 python-pexpect,
32Suggests: ncftp,34Suggests: ncftp,
33 python-boto,35 python-boto,
3436
=== modified file 'duplicity/backend.py'
--- duplicity/backend.py 2017-11-23 13:02:23 +0000
+++ duplicity/backend.py 2017-12-01 23:01:42 +0000
@@ -383,7 +383,7 @@
383 if at_end and fatal:383 if at_end and fatal:
384 def make_filename(f):384 def make_filename(f):
385 if isinstance(f, path.ROPath):385 if isinstance(f, path.ROPath):
386 return util.escape(f.name)386 return util.escape(f.uc_name)
387 else:387 else:
388 return util.escape(f)388 return util.escape(f)
389 extra = ' '.join([operation] + [make_filename(x) for x in args if x])389 extra = ' '.join([operation] + [make_filename(x) for x in args if x])
390390
=== modified file 'duplicity/commandline.py'
--- duplicity/commandline.py 2017-09-01 11:46:59 +0000
+++ duplicity/commandline.py 2017-12-01 23:01:42 +0000
@@ -30,6 +30,7 @@
30import re30import re
31import sys31import sys
32import socket32import socket
33import io
3334
34try:35try:
35 from hashlib import md536 from hashlib import md5
@@ -251,14 +252,13 @@
251 globals.time_separator = sep252 globals.time_separator = sep
252 old_fn_deprecation(opt)253 old_fn_deprecation(opt)
253254
254 def add_selection(o, s, v, p):255 def add_selection(o, option, additional_arg, p):
255 select_opts.append((s, v))256 select_opts.append((util.fsdecode(option), util.fsdecode(additional_arg)))
256257
257 def add_filelist(o, s, v, p):258 def add_filelist(o, s, filename, p):
258 filename = v259 select_opts.append((util.fsdecode(s), util.fsdecode(filename)))
259 select_opts.append((s, filename))
260 try:260 try:
261 select_files.append(open(filename, "r"))261 select_files.append(io.open(filename, "rt", encoding="UTF-8"))
262 except IOError:262 except IOError:
263 log.FatalError(_("Error opening file %s") % filename,263 log.FatalError(_("Error opening file %s") % filename,
264 log.ErrorCode.cant_open_filelist)264 log.ErrorCode.cant_open_filelist)
265265
=== modified file 'duplicity/globals.py'
--- duplicity/globals.py 2017-11-23 13:02:23 +0000
+++ duplicity/globals.py 2017-12-01 23:01:42 +0000
@@ -321,4 +321,4 @@
321# 'utf-8' or some other sane encoding, but will sometimes fail and return321# 'utf-8' or some other sane encoding, but will sometimes fail and return
322# either 'ascii' or None. Both are bogus, so default to 'utf-8' if it does.322# either 'ascii' or None. Both are bogus, so default to 'utf-8' if it does.
323fsencoding = sys.getfilesystemencoding()323fsencoding = sys.getfilesystemencoding()
324fsencoding = fsencoding if fsencoding not in ['ascii', None] else 'utf-8'324fsencoding = fsencoding if fsencoding not in ['ascii', 'ANSI_X3.4-1968', None] else 'utf-8'
325325
=== modified file 'duplicity/globmatch.py'
--- duplicity/globmatch.py 2017-07-11 14:55:38 +0000
+++ duplicity/globmatch.py 2017-12-01 23:01:42 +0000
@@ -19,9 +19,15 @@
19# You should have received a copy of the GNU General Public License19# You should have received a copy of the GNU General Public License
20# along with duplicity; if not, write to the Free Software Foundation,20# along with duplicity; if not, write to the Free Software Foundation,
21# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA21# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22#
23# All functions in this module only accept unicode. Any byte strings should
24# be converted to unicode before sending them into this.
2225
23import re26import re
2427
28from builtins import map
29from builtins import range
30
2531
26class GlobbingError(Exception):32class GlobbingError(Exception):
27 """Something has gone wrong when parsing a glob string"""33 """Something has gone wrong when parsing a glob string"""
@@ -36,16 +42,16 @@
36def _glob_get_prefix_regexs(glob_str):42def _glob_get_prefix_regexs(glob_str):
37 """Return list of regexps equivalent to prefixes of glob_str"""43 """Return list of regexps equivalent to prefixes of glob_str"""
38 # Internal. Used by glob_get_normal_sf.44 # Internal. Used by glob_get_normal_sf.
39 glob_parts = glob_str.split("/")45 glob_parts = glob_str.split(u"/")
40 if "" in glob_parts[1:-1]:46 if u"" in glob_parts[1:-1]:
41 # "" OK if comes first or last, as in /foo/47 # "" OK if comes first or last, as in /foo/
42 raise GlobbingError("Consecutive '/'s found in globbing string " +48 raise GlobbingError(u"Consecutive '/'s found in globbing string " +
43 glob_str)49 glob_str)
4450
45 prefixes = ["/".join(glob_parts[:i + 1]) for i in range(len(glob_parts))]51 prefixes = [u"/".join(glob_parts[:i + 1]) for i in range(len(glob_parts))]
46 # we must make exception for root "/", only dir to end in slash52 # we must make exception for root "/", only dir to end in slash
47 if prefixes[0] == "":53 if prefixes[0] == u"":
48 prefixes[0] = "/"54 prefixes[0] = u"/"
49 return list(map(glob_to_regex, prefixes))55 return list(map(glob_to_regex, prefixes))
5056
5157
@@ -62,12 +68,13 @@
6268
63 Note: including a folder implicitly includes everything within it.69 Note: including a folder implicitly includes everything within it.
64 """70 """
71 assert isinstance(glob_str, unicode)
65 glob_ends_w_slash = False72 glob_ends_w_slash = False
6673
67 if glob_str == "/":74 if glob_str == u"/":
68 # If the glob string is '/', it implicitly includes everything75 # If the glob string is '/', it implicitly includes everything
69 glob_str = "/**"76 glob_str = u"/**"
70 elif glob_str[-1] == "/":77 elif glob_str[-1] == u"/":
71 glob_ends_w_slash = True78 glob_ends_w_slash = True
72 # Remove trailing / from directory name (unless that is the entire79 # Remove trailing / from directory name (unless that is the entire
73 # string)80 # string)
@@ -87,39 +94,39 @@
87 # Note that the "/" at the end of the regex means that it will match94 # Note that the "/" at the end of the regex means that it will match
88 # if the glob matches a parent folders of path, i.e. including a folder95 # if the glob matches a parent folders of path, i.e. including a folder
89 # includes everything within it.96 # includes everything within it.
90 glob_comp_re = re_comp("^%s($|/)" % glob_to_regex(glob_str))97 glob_comp_re = re_comp(u"^%s($|/)" % glob_to_regex(glob_str))
9198
92 if glob_ends_w_slash:99 if glob_ends_w_slash:
93 # Creates a version of glob_comp_re that does not match folder contents100 # Creates a version of glob_comp_re that does not match folder contents
94 # This can be used later to check that an exact match is actually a101 # This can be used later to check that an exact match is actually a
95 # folder, rather than a file.102 # folder, rather than a file.
96 glob_comp_re_exact = re_comp("^%s($)" % glob_to_regex(glob_str))103 glob_comp_re_exact = re_comp(u"^%s($)" % glob_to_regex(glob_str))
97104
98 if glob_str.find("**") != -1:105 if glob_str.find(u"**") != -1:
99 # glob_str has a ** in it106 # glob_str has a ** in it
100 glob_str = glob_str[:glob_str.find("**") + 2] # truncate after **107 glob_str = glob_str[:glob_str.find(u"**") + 2] # truncate after **
101108
102 # Below regex is translates to:109 # Below regex is translates to:
103 # ^ string must be at the beginning of path110 # ^ string must be at the beginning of path
104 # the regexs corresponding to the parent directories of glob_str111 # the regexs corresponding to the parent directories of glob_str
105 # $ nothing must follow except for the end of the string or newline112 # $ nothing must follow except for the end of the string or newline
106 scan_comp_re = re_comp("^(%s)$" %113 scan_comp_re = re_comp(u"^(%s)$" %
107 "|".join(_glob_get_prefix_regexs(glob_str)))114 u"|".join(_glob_get_prefix_regexs(glob_str)))
108115
109 def test_fn(path):116 def test_fn(path):
110 assert not path.name[-1] == "/" or path.name == "/", \117 assert not path.uc_name[-1] == u"/" or path.uc_name == u"/", \
111 "path.name should never end in '/' during normal operation for " \118 u"path.name should never end in '/' during normal operation for " \
112 "normal paths (except '/' alone)\n" \119 u"normal paths (except '/' alone)\n" \
113 "path.name here is " + path.name + " and glob is " + glob_str120 u"path.name here is " + path.uc_name + u" and glob is " + glob_str
114121
115 if glob_comp_re.match(path.name):122 if glob_comp_re.match(path.uc_name):
116 # Path matches glob, or is contained within a matching folder123 # Path matches glob, or is contained within a matching folder
117 if not glob_ends_w_slash:124 if not glob_ends_w_slash:
118 return include125 return include
119 else:126 else:
120 # Glob ended with a /, so we need to check any exact match was127 # Glob ended with a /, so we need to check any exact match was
121 # a folder128 # a folder
122 if glob_comp_re_exact.match(path.name):129 if glob_comp_re_exact.match(path.uc_name):
123 # Not an included file/folder, so must be a folder to match130 # Not an included file/folder, so must be a folder to match
124 if path.isdir():131 if path.isdir():
125 # Is a directory, so all is well132 # Is a directory, so all is well
@@ -131,7 +138,7 @@
131 # An included file/folder, so normal approach is fine138 # An included file/folder, so normal approach is fine
132 return include139 return include
133140
134 elif include == 1 and scan_comp_re.match(path.name):141 elif include == 1 and scan_comp_re.match(path.uc_name):
135 return 2142 return 2
136 else:143 else:
137 return None144 return None
@@ -151,34 +158,37 @@
151158
152 """159 """
153 # Internal. Used by glob_get_normal_sf, glob_get_prefix_res and unit tests.160 # Internal. Used by glob_get_normal_sf, glob_get_prefix_res and unit tests.
161
162 assert isinstance(pat, unicode)
163
154 i, n, res = 0, len(pat), ''164 i, n, res = 0, len(pat), ''
155 while i < n:165 while i < n:
156 c, s = pat[i], pat[i:i + 2]166 c, s = pat[i], pat[i:i + 2]
157 i = i + 1167 i = i + 1
158 if s == '**':168 if s == u'**':
159 res = res + '.*'169 res = res + u'.*'
160 i = i + 1170 i = i + 1
161 elif c == '*':171 elif c == u'*':
162 res = res + '[^/]*'172 res = res + u'[^/]*'
163 elif c == '?':173 elif c == u'?':
164 res = res + '[^/]'174 res = res + u'[^/]'
165 elif c == '[':175 elif c == u'[':
166 j = i176 j = i
167 if j < n and pat[j] in '!^':177 if j < n and pat[j] in u'!^':
168 j = j + 1178 j = j + 1
169 if j < n and pat[j] == ']':179 if j < n and pat[j] == u']':
170 j = j + 1180 j = j + 1
171 while j < n and pat[j] != ']':181 while j < n and pat[j] != u']':
172 j = j + 1182 j = j + 1
173 if j >= n:183 if j >= n:
174 res = res + '\\[' # interpret the [ literally184 res = res + u'\\[' # interpret the [ literally
175 else:185 else:
176 # Deal with inside of [..]186 # Deal with inside of [..]
177 stuff = pat[i:j].replace('\\', '\\\\')187 stuff = pat[i:j].replace(u'\\', u'\\\\')
178 i = j + 1188 i = j + 1
179 if stuff[0] in '!^':189 if stuff[0] in u'!^':
180 stuff = '^' + stuff[1:]190 stuff = u'^' + stuff[1:]
181 res = res + '[' + stuff + ']'191 res = res + u'[' + stuff + u']'
182 else:192 else:
183 res = res + re.escape(c)193 res = res + re.escape(c)
184 return res194 return res
185195
=== modified file 'duplicity/path.py'
--- duplicity/path.py 2017-07-11 14:55:38 +0000
+++ duplicity/path.py 2017-12-01 23:01:42 +0000
@@ -35,6 +35,7 @@
35import re35import re
36import gzip36import gzip
37import shutil37import shutil
38import sys
3839
39from duplicity import tarfile40from duplicity import tarfile
40from duplicity import file_naming41from duplicity import file_naming
@@ -511,9 +512,21 @@
511 # self.opened should be true if the file has been opened, and512 # self.opened should be true if the file has been opened, and
512 # self.fileobj can override returned fileobj513 # self.fileobj can override returned fileobj
513 self.opened, self.fileobj = None, None514 self.opened, self.fileobj = None, None
515 if isinstance(base, unicode):
516 # For now (Python 2), it is helpful to know that all paths
517 # are starting with bytes -- see note above util.fsencode definition
518 base = util.fsencode(base)
514 self.base = base519 self.base = base
520
521 # Create self.index, which is the path as a tuple
515 self.index = self.rename_index(index)522 self.index = self.rename_index(index)
523
516 self.name = os.path.join(base, *self.index)524 self.name = os.path.join(base, *self.index)
525
526 # We converted any unicode base to filesystem encoding, so self.name should
527 # be in filesystem encoding already and does not need to change
528 self.uc_name = util.fsdecode(self.name)
529
517 self.setdata()530 self.setdata()
518531
519 def setdata(self):532 def setdata(self):
520533
=== modified file 'duplicity/selection.py'
--- duplicity/selection.py 2017-07-11 14:55:38 +0000
+++ duplicity/selection.py 2017-12-01 23:01:42 +0000
@@ -90,7 +90,7 @@
90 assert isinstance(path, Path), str(path)90 assert isinstance(path, Path), str(path)
91 self.selection_functions = []91 self.selection_functions = []
92 self.rootpath = path92 self.rootpath = path
93 self.prefix = self.rootpath.name93 self.prefix = self.rootpath.uc_name
9494
95 def set_iter(self):95 def set_iter(self):
96 """Initialize generator, prepare to iterate."""96 """Initialize generator, prepare to iterate."""
@@ -164,10 +164,10 @@
164164
165 if not path.type:165 if not path.type:
166 # base doesn't exist166 # base doesn't exist
167 log.Warn(_("Warning: base %s doesn't exist, continuing") %167 log.Warn(_(u"Warning: base %s doesn't exist, continuing") %
168 util.ufn(path.name))168 path.uc_name)
169 return169 return
170 log.Debug(_("Selecting %s") % util.ufn(path.name))170 log.Debug(_(u"Selecting %s") % path.uc_name)
171 yield path171 yield path
172 if not path.isdir():172 if not path.isdir():
173 return173 return
@@ -185,10 +185,10 @@
185 if val == 0:185 if val == 0:
186 if delayed_path_stack:186 if delayed_path_stack:
187 for delayed_path in delayed_path_stack:187 for delayed_path in delayed_path_stack:
188 log.Log(_("Selecting %s") % util.ufn(delayed_path.name), 6)188 log.Log(_(u"Selecting %s") % delayed_path.uc_name, 6)
189 yield delayed_path189 yield delayed_path
190 del delayed_path_stack[:]190 del delayed_path_stack[:]
191 log.Debug(_("Selecting %s") % util.ufn(subpath.name))191 log.Debug(_(u"Selecting %s") % subpath.uc_name)
192 yield subpath192 yield subpath
193 if subpath.isdir():193 if subpath.isdir():
194 diryield_stack.append(diryield(subpath))194 diryield_stack.append(diryield(subpath))
@@ -199,14 +199,14 @@
199 def Select(self, path):199 def Select(self, path):
200 """Run through the selection functions and return dominant val 0/1/2"""200 """Run through the selection functions and return dominant val 0/1/2"""
201 # Only used by diryield and tests. Internal.201 # Only used by diryield and tests. Internal.
202 log.Debug("Selection: examining path %s" % util.ufn(path.name))202 log.Debug(u"Selection: examining path %s" % path.uc_name)
203 if not self.selection_functions:203 if not self.selection_functions:
204 log.Debug("Selection: + no selection functions found. Including")204 log.Debug(u"Selection: + no selection functions found. Including")
205 return 1205 return 1
206 scan_pending = False206 scan_pending = False
207 for sf in self.selection_functions:207 for sf in self.selection_functions:
208 result = sf(path)208 result = sf(path)
209 log.Debug("Selection: result: %4s from function: %s" %209 log.Debug(u"Selection: result: %4s from function: %s" %
210 (str(result), sf.name))210 (str(result), sf.name))
211 if result is 2:211 if result is 2:
212 # Selection function says that the path should be scanned for matching files, but keep going212 # Selection function says that the path should be scanned for matching files, but keep going
@@ -224,12 +224,12 @@
224 result = 1224 result = 1
225225
226 if result == 0:226 if result == 0:
227 log.Debug("Selection: - excluding file")227 log.Debug(u"Selection: - excluding file")
228 elif result == 1:228 elif result == 1:
229 log.Debug("Selection: + including file")229 log.Debug(u"Selection: + including file")
230 else:230 else:
231 assert result == 2231 assert result == 2
232 log.Debug("Selection: ? scanning directory for matches")232 log.Debug(u"Selection: ? scanning directory for matches")
233233
234 return result234 return result
235235
@@ -246,36 +246,41 @@
246 filelists_index = 0246 filelists_index = 0
247 try:247 try:
248 for opt, arg in argtuples:248 for opt, arg in argtuples:
249 if opt == "--exclude":249 assert isinstance(opt, unicode), u"option " + opt.decode(sys.getfilesystemencoding(), "ignore") + \
250 u" is not unicode"
251 assert isinstance(arg, unicode), u"option " + arg.decode(sys.getfilesystemencoding(), "ignore") + \
252 u" is not unicode"
253
254 if opt == u"--exclude":
250 self.add_selection_func(self.glob_get_sf(arg, 0))255 self.add_selection_func(self.glob_get_sf(arg, 0))
251 elif opt == "--exclude-if-present":256 elif opt == u"--exclude-if-present":
252 self.add_selection_func(self.present_get_sf(arg, 0))257 self.add_selection_func(self.present_get_sf(arg, 0))
253 elif opt == "--exclude-device-files":258 elif opt == u"--exclude-device-files":
254 self.add_selection_func(self.devfiles_get_sf())259 self.add_selection_func(self.devfiles_get_sf())
255 elif (opt == "--exclude-filelist") or (opt == "--exclude-globbing-filelist"):260 elif (opt == u"--exclude-filelist") or (opt == u"--exclude-globbing-filelist"):
256 # --exclude-globbing-filelist is now deprecated, as all filelists are globbing261 # --exclude-globbing-filelist is now deprecated, as all filelists are globbing
257 # but keep this here for the short term for backwards-compatibility262 # but keep this here for the short term for backwards-compatibility
258 for sf in self.filelist_globbing_get_sfs(filelists[filelists_index], 0, arg):263 for sf in self.filelist_globbing_get_sfs(filelists[filelists_index], 0, arg):
259 self.add_selection_func(sf)264 self.add_selection_func(sf)
260 filelists_index += 1265 filelists_index += 1
261 elif opt == "--exclude-other-filesystems":266 elif opt == u"--exclude-other-filesystems":
262 self.add_selection_func(self.other_filesystems_get_sf(0))267 self.add_selection_func(self.other_filesystems_get_sf(0))
263 elif opt == "--exclude-regexp":268 elif opt == u"--exclude-regexp":
264 self.add_selection_func(self.regexp_get_sf(arg, 0))269 self.add_selection_func(self.regexp_get_sf(arg, 0))
265 elif opt == "--exclude-older-than":270 elif opt == u"--exclude-older-than":
266 self.add_selection_func(self.exclude_older_get_sf(arg))271 self.add_selection_func(self.exclude_older_get_sf(arg))
267 elif opt == "--include":272 elif opt == u"--include":
268 self.add_selection_func(self.glob_get_sf(arg, 1))273 self.add_selection_func(self.glob_get_sf(arg, 1))
269 elif (opt == "--include-filelist") or (opt == "--include-globbing-filelist"):274 elif (opt == u"--include-filelist") or (opt == u"--include-globbing-filelist"):
270 # --include-globbing-filelist is now deprecated, as all filelists are globbing275 # --include-globbing-filelist is now deprecated, as all filelists are globbing
271 # but keep this here for the short term for backwards-compatibility276 # but keep this here for the short term for backwards-compatibility
272 for sf in self.filelist_globbing_get_sfs(filelists[filelists_index], 1, arg):277 for sf in self.filelist_globbing_get_sfs(filelists[filelists_index], 1, arg):
273 self.add_selection_func(sf)278 self.add_selection_func(sf)
274 filelists_index += 1279 filelists_index += 1
275 elif opt == "--include-regexp":280 elif opt == u"--include-regexp":
276 self.add_selection_func(self.regexp_get_sf(arg, 1))281 self.add_selection_func(self.regexp_get_sf(arg, 1))
277 else:282 else:
278 assert 0, "Bad selection option %s" % opt283 assert 0, u"Bad selection option %s" % opt
279 except SelectError as e:284 except SelectError as e:
280 self.parse_catch_error(e)285 self.parse_catch_error(e)
281 assert filelists_index == len(filelists)286 assert filelists_index == len(filelists)
@@ -285,16 +290,16 @@
285 """Deal with selection error exc"""290 """Deal with selection error exc"""
286 # Internal, used by ParseArgs.291 # Internal, used by ParseArgs.
287 if isinstance(exc, FilePrefixError):292 if isinstance(exc, FilePrefixError):
288 log.FatalError(_("""\293 log.FatalError(_(u"""\
289Fatal Error: The file specification294Fatal Error: The file specification
290 %s295 %s
291cannot match any files in the base directory296cannot match any files in the base directory
292 %s297 %s
293Useful file specifications begin with the base directory or some298Useful file specifications begin with the base directory or some
294pattern (such as '**') which matches the base directory.""") %299pattern (such as '**') which matches the base directory.""") %
295 (exc, util.ufn(self.prefix)), log.ErrorCode.file_prefix_error)300 (exc, self.prefix), log.ErrorCode.file_prefix_error)
296 elif isinstance(exc, GlobbingError):301 elif isinstance(exc, GlobbingError):
297 log.FatalError(_("Fatal Error while processing expression\n"302 log.FatalError(_(u"Fatal Error while processing expression\n"
298 "%s") % exc, log.ErrorCode.globbing_error)303 "%s") % exc, log.ErrorCode.globbing_error)
299 else:304 else:
300 raise # pylint: disable=misplaced-bare-raise305 raise # pylint: disable=misplaced-bare-raise
@@ -304,7 +309,7 @@
304 # Internal. Used by ParseArgs.309 # Internal. Used by ParseArgs.
305 if (self.selection_functions and310 if (self.selection_functions and
306 not self.selection_functions[-1].exclude):311 not self.selection_functions[-1].exclude):
307 log.FatalError(_("""\312 log.FatalError(_(u"""\
308Last selection expression:313Last selection expression:
309 %s314 %s
310only specifies that files be included. Because the default is to315only specifies that files be included. Because the default is to
@@ -333,19 +338,19 @@
333 line = line.strip()338 line = line.strip()
334 if not line: # skip blanks339 if not line: # skip blanks
335 return None, include_default340 return None, include_default
336 if line[0] == "#": # skip full-line comments341 if line.startswith(u"#"): # skip full-line comments
337 return None, include_default342 return None, include_default
338343
339 include = include_default344 include = include_default
340 if line[:2] == "+ ":345 if line.startswith(u"+ "):
341 # Check for "+ " or "- " syntax346 # Check for "+ " or "- " syntax
342 include = 1347 include = 1
343 line = line[2:]348 line = line[2:]
344 elif line[:2] == "- ":349 elif line.startswith(u"- "):
345 include = 0350 include = 0
346 line = line[2:]351 line = line[2:]
347352
348 if (line[:1] == "'" and line[-1:] == "'") or (line[:1] == '"' and line[-1:] == '"'):353 if (line.startswith(u"'") and line.endswith(u"'")) or (line.startswith(u'"') and line.endswith(u'"')):
349 line = line[1:-1]354 line = line[1:-1]
350355
351 return line, include356 return line, include
@@ -360,8 +365,8 @@
360365
361 """366 """
362 # Internal. Used by ParseArgs.367 # Internal. Used by ParseArgs.
363 log.Notice(_("Reading globbing filelist %s") % list_name)368 log.Notice(_(u"Reading globbing filelist %s") % list_name)
364 separator = globals.null_separator and "\0" or "\n"369 separator = globals.null_separator and u"\0" or u"\n"
365 filelist_fp.seek(0)370 filelist_fp.seek(0)
366 for line in filelist_fp.read().split(separator):371 for line in filelist_fp.read().split(separator):
367 line, include = self.filelist_sanitise_line(line, inc_default)372 line, include = self.filelist_sanitise_line(line, inc_default)
@@ -383,7 +388,7 @@
383 return None388 return None
384389
385 sel_func.exclude = not include390 sel_func.exclude = not include
386 sel_func.name = "Match other filesystems"391 sel_func.name = u"Match other filesystems"
387 return sel_func392 return sel_func
388393
389 def regexp_get_sf(self, regexp_string, include):394 def regexp_get_sf(self, regexp_string, include):
@@ -393,24 +398,24 @@
393 try:398 try:
394 regexp = re.compile(regexp_string)399 regexp = re.compile(regexp_string)
395 except Exception:400 except Exception:
396 log.Warn(_("Error compiling regular expression %s") % regexp_string)401 log.Warn(_(u"Error compiling regular expression %s") % regexp_string)
397 raise402 raise
398403
399 def sel_func(path):404 def sel_func(path):
400 if regexp.search(path.name):405 if regexp.search(path.uc_name):
401 return include406 return include
402 else:407 else:
403 return None408 return None
404409
405 sel_func.exclude = not include410 sel_func.exclude = not include
406 sel_func.name = "Regular expression: %s" % regexp_string411 sel_func.name = u"Regular expression: %s" % regexp_string
407 return sel_func412 return sel_func
408413
409 def devfiles_get_sf(self):414 def devfiles_get_sf(self):
410 """Return a selection function to exclude all dev files"""415 """Return a selection function to exclude all dev files"""
411 # Internal. Used by ParseArgs.416 # Internal. Used by ParseArgs.
412 if self.selection_functions:417 if self.selection_functions:
413 log.Warn(_("Warning: exclude-device-files is not the first "418 log.Warn(_(u"Warning: exclude-device-files is not the first "
414 "selector.\nThis may not be what you intended"))419 "selector.\nThis may not be what you intended"))
415420
416 def sel_func(path):421 def sel_func(path):
@@ -420,21 +425,22 @@
420 return None425 return None
421426
422 sel_func.exclude = 1427 sel_func.exclude = 1
423 sel_func.name = "Exclude device files"428 sel_func.name = u"Exclude device files"
424 return sel_func429 return sel_func
425430
426 def glob_get_sf(self, glob_str, include):431 def glob_get_sf(self, glob_str, include):
427 """Return selection function given by glob string"""432 """Return selection function given by glob string"""
428 # Internal. Used by ParseArgs, filelist_globbing_get_sfs and unit tests.433 # Internal. Used by ParseArgs, filelist_globbing_get_sfs and unit tests.
429 assert include == 0 or include == 1434 assert include == 0 or include == 1
430 if glob_str == "**":435 assert isinstance(glob_str, unicode)
436 if glob_str == u"**":
431 sel_func = lambda path: include437 sel_func = lambda path: include
432 else:438 else:
433 sel_func = self.glob_get_normal_sf(glob_str, include)439 sel_func = self.glob_get_normal_sf(glob_str, include)
434440
435 sel_func.exclude = not include441 sel_func.exclude = not include
436 sel_func.name = "Command-line %s glob: %s" % \442 sel_func.name = u"Command-line %s glob: %s" % \
437 (include and "include" or "exclude", glob_str)443 (include and u"include" or u"exclude", glob_str)
438 return sel_func444 return sel_func
439445
440 def present_get_sf(self, filename, include):446 def present_get_sf(self, filename, include):
@@ -453,9 +459,8 @@
453 # functions. Currently this will give an error for any459 # functions. Currently this will give an error for any
454 # locked directory within the folder being backed up.460 # locked directory within the folder being backed up.
455 log.Warn(_(461 log.Warn(_(
456 "Error accessing possibly locked file %s") % util.ufn(462 u"Error accessing possibly locked file %s") % path.uc_name,
457 path.name),463 log.WarningCode.cannot_read, util.escape(path.uc_name))
458 log.WarningCode.cannot_read, util.escape(path.name))
459 if diffdir.stats:464 if diffdir.stats:
460 diffdir.stats.Errors += 1465 diffdir.stats.Errors += 1
461 elif path.append(filename).exists():466 elif path.append(filename).exists():
@@ -470,8 +475,8 @@
470 log.ErrorCode.not_implemented)475 log.ErrorCode.not_implemented)
471476
472 sel_func.exclude = not include477 sel_func.exclude = not include
473 sel_func.name = "Command-line %s filename: %s" % \478 sel_func.name = u"Command-line %s filename: %s" % \
474 (include and "include-if-present" or "exclude-if-present", filename)479 (include and u"include-if-present" or u"exclude-if-present", filename)
475 return sel_func480 return sel_func
476481
477 def glob_get_normal_sf(self, glob_str, include):482 def glob_get_normal_sf(self, glob_str, include):
@@ -489,8 +494,8 @@
489 things similar to this.494 things similar to this.
490495
491 """496 """
492 # Internal. Used by glob_get_sf and unit tests.497 assert isinstance(glob_str, unicode), \
493498 u"The glob string " + glob_str.decode(sys.getfilesystemencoding(), "ignore") + u" is not unicode"
494 ignore_case = False499 ignore_case = False
495500
496 if glob_str.lower().startswith("ignorecase:"):501 if glob_str.lower().startswith("ignorecase:"):
497502
=== modified file 'duplicity/util.py'
--- duplicity/util.py 2017-11-23 13:02:23 +0000
+++ duplicity/util.py 2017-12-01 23:01:42 +0000
@@ -34,6 +34,37 @@
34import duplicity.globals as globals34import duplicity.globals as globals
35import duplicity.log as log35import duplicity.log as log
3636
37try:
38 # For paths, just use path.name/uname rather than converting with these
39 from os import fsencode, fsdecode
40except ImportError:
41 # Most likely Python version < 3.2, so define our own fsencode/fsdecode.
42 # These are functions that encode/decode unicode paths to filesystem encoding,
43 # but the cleverness is that they handle non-unicode characters on Linux
44 # There is a *partial* backport to Python2 available here:
45 # https://github.com/pjdelport/backports.os/blob/master/src/backports/os.py
46 # but if it cannot be trusted for full-circle translation, then we may as well
47 # just read and store the bytes version of the path as path.name before
48 # creating the unicode version (for path matching etc) and ensure that in
49 # real-world usage (as opposed to testing) we create the path objects from a
50 # bytes string.
51 # ToDo: Revisit this once we drop Python 2 support/the backport is complete
52
53 def fsencode(unicode_filename):
54 """Convert a unicode filename to a filename encoded in the system encoding"""
55 # For paths, just use path.name rather than converting with this
56 # If we are not doing any cleverness with non-unicode filename bytes,
57 # encoding to system encoding is good enough
58 return unicode_filename.encode(sys.getfilesystemencoding(), "replace")
59
60 def fsdecode(bytes_filename):
61 """Convert a filename encoded in the system encoding to unicode"""
62 # For paths, just use path.uname rather than converting with this
63 # If we are not doing any cleverness with non-unicode filename bytes,
64 # decoding using system encoding is good enough. Use "ignore" as
65 # Linux paths can contain non-Unicode characters
66 return bytes_filename.decode(globals.fsencoding, "ignore")
67
3768
38def exception_traceback(limit=50):69def exception_traceback(limit=50):
39 """70 """
@@ -58,9 +89,9 @@
5889
5990
60def ufn(filename):91def ufn(filename):
61 "Convert a (bytes) filename to unicode for printing"92 """Convert a (bytes) filename to unicode for printing"""
62 assert not isinstance(filename, unicode)93 # Note: path.uc_name is preferable for paths
63 return filename.decode(globals.fsencoding, 'replace')94 return filename.decode(globals.fsencoding, "replace")
6495
6596
66def uindex(index):97def uindex(index):
6798
=== modified file 'requirements.txt'
--- requirements.txt 2017-05-20 15:07:38 +0000
+++ requirements.txt 2017-12-01 23:01:42 +0000
@@ -2,6 +2,7 @@
2coverage2coverage
3dropbox==6.9.03dropbox==6.9.0
4fasteners4fasteners
5future
5paramiko6paramiko
6pexpect7pexpect
7pycodestyle8pycodestyle
89
=== modified file 'setup.py'
--- setup.py 2017-07-11 14:55:38 +0000
+++ setup.py 2017-12-01 23:01:42 +0000
@@ -196,7 +196,7 @@
196 ext_modules=ext_modules,196 ext_modules=ext_modules,
197 scripts=['bin/rdiffdir', 'bin/duplicity'],197 scripts=['bin/rdiffdir', 'bin/duplicity'],
198 data_files=data_files,198 data_files=data_files,
199 install_requires=['fasteners'],199 install_requires=['fasteners', 'future'],
200 tests_require=['fasteners', 'mock', 'pexpect'],200 tests_require=['fasteners', 'mock', 'pexpect'],
201 test_suite='testing',201 test_suite='testing',
202 cmdclass={'test': TestCommand,202 cmdclass={'test': TestCommand,
203203
=== modified file 'testing/__init__.py'
--- testing/__init__.py 2017-07-11 14:55:38 +0000
+++ testing/__init__.py 2017-12-01 23:01:42 +0000
@@ -55,10 +55,12 @@
5555
56class DuplicityTestCase(unittest.TestCase):56class DuplicityTestCase(unittest.TestCase):
5757
58 sign_key = '839E6A2856538CCF'58 sign_key = u'839E6A2856538CCF'
59 sign_passphrase = 'test'59 sign_passphrase = u'test'
60 encrypt_key1 = '839E6A2856538CCF'60 # ToDo: remove the below when gpg code (and test_gpg) is converted to unicode
61 encrypt_key2 = '453005CE9B736B2A'61 sign_passphrase_bytes = b'test'
62 encrypt_key1 = u'839E6A2856538CCF'
63 encrypt_key2 = u'453005CE9B736B2A'
6264
63 def setUp(self):65 def setUp(self):
64 super(DuplicityTestCase, self).setUp()66 super(DuplicityTestCase, self).setUp()
6567
=== modified file 'testing/functional/__init__.py'
--- testing/functional/__init__.py 2017-07-11 14:55:38 +0000
+++ testing/functional/__init__.py 2017-12-01 23:01:42 +0000
@@ -25,10 +25,11 @@
25import platform25import platform
26import sys26import sys
27import time27import time
28import unittest
2928
30from duplicity import backend29from duplicity import backend
30from duplicity import util
31from .. import DuplicityTestCase31from .. import DuplicityTestCase
32from pkg_resources import parse_version
3233
3334
34class CmdError(Exception):35class CmdError(Exception):
@@ -64,7 +65,7 @@
64 self.unpack_testfiles()65 self.unpack_testfiles()
6566
66 self.class_args = []67 self.class_args = []
67 self.backend_url = "file://testfiles/output"68 self.backend_url = u"file://testfiles/output"
68 self.last_backup = None69 self.last_backup = None
69 self.set_environ('PASSPHRASE', self.sign_passphrase)70 self.set_environ('PASSPHRASE', self.sign_passphrase)
70 self.set_environ("SIGN_PASSPHRASE", self.sign_passphrase)71 self.set_environ("SIGN_PASSPHRASE", self.sign_passphrase)
@@ -84,30 +85,57 @@
84 # We run under setsid and take input from /dev/null (below) because85 # We run under setsid and take input from /dev/null (below) because
85 # this way we force a failure if duplicity tries to read from the86 # this way we force a failure if duplicity tries to read from the
86 # console unexpectedly (like for gpg password or such).87 # console unexpectedly (like for gpg password or such).
87 if platform.platform().startswith('Linux'):88
88 cmd_list = ['setsid']89 # Check all string inputs are unicode -- we will convert to system encoding before running the command
90 for item in options:
91 assert not isinstance(item, str), "item " + unicode(item) + " in options is not unicode"
92
93 for item in passphrase_input:
94 assert isinstance(item, unicode), "item " + unicode(item) + " in passphrase_input is not unicode"
95
96 if platform.platform().startswith(u'Linux'):
97 cmd_list = [u'setsid']
89 if self._setsid_w:98 if self._setsid_w:
90 cmd_list.extend(["-w"])99 cmd_list.extend([u"-w"])
91 else:100 else:
92 cmd_list = []101 cmd_list = []
93 cmd_list.extend(["duplicity"])102 cmd_list.extend([u"duplicity"])
94 cmd_list.extend(options)103 cmd_list.extend(options)
95 cmd_list.extend(["-v0"])104 cmd_list.extend([u"-v0"])
96 cmd_list.extend(["--no-print-statistics"])105 cmd_list.extend([u"--no-print-statistics"])
97 cmd_list.extend(["--allow-source-mismatch"])106 cmd_list.extend([u"--allow-source-mismatch"])
98 cmd_list.extend(["--archive-dir=testfiles/cache"])107 cmd_list.extend([u"--archive-dir=testfiles/cache"])
99 if current_time:108 if current_time:
100 cmd_list.extend(["--current-time", current_time])109 cmd_list.extend([u"--current-time", current_time])
101 cmd_list.extend(self.class_args)110 cmd_list.extend(self.class_args)
102 if fail:111 if fail:
103 cmd_list.extend(["--fail", str(fail)])112 cmd_list.extend([u"--fail", unicode(fail)])
104 cmdline = " ".join(map(lambda x: '"%s"' % x, cmd_list))113 cmdline = u" ".join(map(lambda x: u'"%s"' % x, cmd_list))
105114
106 if not passphrase_input:115 if not passphrase_input:
107 cmdline += " < /dev/null"116 cmdline += u" < /dev/null"
108 child = pexpect.spawn('/bin/sh', ['-c', cmdline], timeout=None)117
118 # The immediately following block is the nicer way to execute pexpect with
119 # unicode strings, but we need to have the pre-4.0 version for some time yet,
120 # so for now this is commented out so tests execute the same way on all systems.
121
122 # if parse_version(pexpect.__version__) >= parse_version("4.0"):
123 # # pexpect.spawn only supports unicode from version 4.0
124 # # there was a separate pexpect.spawnu in 3.x, but it has an error on readline
125 # child = pexpect.spawn(u'/bin/sh', [u'-c', cmdline], timeout=None, encoding=sys.getfilesystemencoding())
126 #
127 # for passphrase in passphrase_input:
128 # child.expect(u'passphrase.*:')
129 # child.sendline(passphrase)
130 # else:
131
132 # Manually encode to filesystem encoding and send to spawn as bytes
133 # ToDo: Remove this once we no longer have to support systems with pexpect < 4.0
134 child = pexpect.spawn(b'/bin/sh', [b'-c', cmdline.encode(sys.getfilesystemencoding(),
135 'replace')], timeout=None)
136
109 for passphrase in passphrase_input:137 for passphrase in passphrase_input:
110 child.expect('passphrase.*:')138 child.expect(b'passphrase.*:')
111 child.sendline(passphrase)139 child.sendline(passphrase)
112140
113 # if the command fails, we need to clear its output141 # if the command fails, we need to clear its output
@@ -132,7 +160,7 @@
132160
133 def backup(self, type, input_dir, options=[], **kwargs):161 def backup(self, type, input_dir, options=[], **kwargs):
134 """Run duplicity backup to default directory"""162 """Run duplicity backup to default directory"""
135 options = [type, input_dir, self.backend_url, "--volsize", "1"] + options163 options = [type, input_dir, self.backend_url, u"--volsize", u"1"] + options
136 before_files = self.get_backend_files()164 before_files = self.get_backend_files()
137165
138 # If a chain ends with time X and the next full chain begins at time X,166 # If a chain ends with time X and the next full chain begins at time X,
@@ -149,27 +177,27 @@
149177
150 def restore(self, file_to_restore=None, time=None, options=[], **kwargs):178 def restore(self, file_to_restore=None, time=None, options=[], **kwargs):
151 assert not os.system("rm -rf testfiles/restore_out")179 assert not os.system("rm -rf testfiles/restore_out")
152 options = [self.backend_url, "testfiles/restore_out"] + options180 options = [self.backend_url, u"testfiles/restore_out"] + options
153 if file_to_restore:181 if file_to_restore:
154 options.extend(['--file-to-restore', file_to_restore])182 options.extend([u'--file-to-restore', file_to_restore])
155 if time:183 if time:
156 options.extend(['--restore-time', str(time)])184 options.extend([u'--restore-time', unicode(time)])
157 self.run_duplicity(options=options, **kwargs)185 self.run_duplicity(options=options, **kwargs)
158186
159 def verify(self, dirname, file_to_verify=None, time=None, options=[],187 def verify(self, dirname, file_to_verify=None, time=None, options=[],
160 **kwargs):188 **kwargs):
161 options = ["verify", self.backend_url, dirname] + options189 options = [u"verify", self.backend_url, dirname] + options
162 if file_to_verify:190 if file_to_verify:
163 options.extend(['--file-to-restore', file_to_verify])191 options.extend([u'--file-to-restore', file_to_verify])
164 if time:192 if time:
165 options.extend(['--restore-time', str(time)])193 options.extend([u'--restore-time', unicode(time)])
166 self.run_duplicity(options=options, **kwargs)194 self.run_duplicity(options=options, **kwargs)
167195
168 def cleanup(self, options=[]):196 def cleanup(self, options=[]):
169 """197 """
170 Run duplicity cleanup to default directory198 Run duplicity cleanup to default directory
171 """199 """
172 options = ["cleanup", self.backend_url, "--force"] + options200 options = [u"cleanup", self.backend_url, u"--force"] + options
173 self.run_duplicity(options=options)201 self.run_duplicity(options=options)
174202
175 def get_backend_files(self):203 def get_backend_files(self):
@@ -183,6 +211,6 @@
183 Makes a number of large files in testfiles/largefiles that each are211 Makes a number of large files in testfiles/largefiles that each are
184 the specified number of megabytes.212 the specified number of megabytes.
185 """213 """
186 assert not os.system("mkdir testfiles/largefiles")214 assert not os.system(u"mkdir testfiles/largefiles")
187 for n in range(count):215 for n in range(count):
188 assert not os.system("dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=%d > /dev/null 2>&1" % (n + 1, size * 1024))216 assert not os.system(u"dd if=/dev/urandom of=testfiles/largefiles/file%d bs=1024 count=%d > /dev/null 2>&1" % (n + 1, size * 1024))
189217
=== modified file 'testing/functional/test_badupload.py'
--- testing/functional/test_badupload.py 2014-12-27 15:16:06 +0000
+++ testing/functional/test_badupload.py 2017-12-01 23:01:42 +0000
@@ -34,7 +34,7 @@
34 Test basic lost file34 Test basic lost file
35 """35 """
36 try:36 try:
37 self.backup("full", "testfiles/dir1", options=["--skip-volume=1"])37 self.backup(u"full", u"testfiles/dir1", options=[u"--skip-volume=1"])
38 self.fail()38 self.fail()
39 except CmdError as e:39 except CmdError as e:
40 self.assertEqual(e.exit_status, 44, str(e))40 self.assertEqual(e.exit_status, 44, str(e))
4141
=== modified file 'testing/functional/test_cleanup.py'
--- testing/functional/test_cleanup.py 2014-04-20 05:58:47 +0000
+++ testing/functional/test_cleanup.py 2017-12-01 23:01:42 +0000
@@ -35,27 +35,27 @@
35 after a failed backup.35 after a failed backup.
36 """36 """
37 self.make_largefiles()37 self.make_largefiles()
38 good_files = self.backup("full", "testfiles/largefiles")38 good_files = self.backup(u"full", u"testfiles/largefiles")
39 good_files |= self.backup("inc", "testfiles/largefiles")39 good_files |= self.backup(u"inc", u"testfiles/largefiles")
40 good_files |= self.backup("inc", "testfiles/largefiles")40 good_files |= self.backup(u"inc", u"testfiles/largefiles")
41 self.backup("full", "testfiles/largefiles", fail=1)41 self.backup(u"full", u"testfiles/largefiles", fail=1)
42 bad_files = self.get_backend_files()42 bad_files = self.get_backend_files()
43 bad_files -= good_files43 bad_files -= good_files
44 self.assertNotEqual(bad_files, set())44 self.assertNotEqual(bad_files, set())
45 # the cleanup should go OK45 # the cleanup should go OK
46 self.run_duplicity(options=["cleanup", self.backend_url, "--force"])46 self.run_duplicity(options=[u"cleanup", self.backend_url, u"--force"])
47 leftovers = self.get_backend_files()47 leftovers = self.get_backend_files()
48 self.assertEqual(good_files, leftovers)48 self.assertEqual(good_files, leftovers)
49 self.backup("inc", "testfiles/largefiles")49 self.backup(u"inc", u"testfiles/largefiles")
50 self.verify("testfiles/largefiles")50 self.verify(u"testfiles/largefiles")
5151
52 def test_remove_all_but_n(self):52 def test_remove_all_but_n(self):
53 """53 """
54 Test that remove-all-but-n works in the simple case.54 Test that remove-all-but-n works in the simple case.
55 """55 """
56 full1_files = self.backup("full", "testfiles/empty_dir")56 full1_files = self.backup(u"full", u"testfiles/empty_dir")
57 full2_files = self.backup("full", "testfiles/empty_dir")57 full2_files = self.backup(u"full", u"testfiles/empty_dir")
58 self.run_duplicity(options=["remove-all-but-n", "1", self.backend_url, "--force"])58 self.run_duplicity(options=[u"remove-all-but-n", u"1", self.backend_url, u"--force"])
59 leftovers = self.get_backend_files()59 leftovers = self.get_backend_files()
60 self.assertEqual(full2_files, leftovers)60 self.assertEqual(full2_files, leftovers)
6161
@@ -63,10 +63,10 @@
63 """63 """
64 Test that remove-all-inc-of-but-n-full works in the simple case.64 Test that remove-all-inc-of-but-n-full works in the simple case.
65 """65 """
66 full1_files = self.backup("full", "testfiles/empty_dir")66 full1_files = self.backup(u"full", u"testfiles/empty_dir")
67 inc1_files = self.backup("inc", "testfiles/empty_dir")67 inc1_files = self.backup(u"inc", u"testfiles/empty_dir")
68 full2_files = self.backup("full", "testfiles/empty_dir")68 full2_files = self.backup(u"full", u"testfiles/empty_dir")
69 self.run_duplicity(options=["remove-all-inc-of-but-n-full", "1", self.backend_url, "--force"])69 self.run_duplicity(options=[u"remove-all-inc-of-but-n-full", u"1", self.backend_url, u"--force"])
70 leftovers = self.get_backend_files()70 leftovers = self.get_backend_files()
71 self.assertEqual(full1_files | full2_files, leftovers)71 self.assertEqual(full1_files | full2_files, leftovers)
7272
7373
=== modified file 'testing/functional/test_final.py'
--- testing/functional/test_final.py 2017-04-22 19:30:28 +0000
+++ testing/functional/test_final.py 2017-12-01 23:01:42 +0000
@@ -36,11 +36,11 @@
3636
37 # Back up directories to local backend37 # Back up directories to local backend
38 current_time = 10000038 current_time = 100000
39 self.backup("full", dirlist[0], current_time=current_time,39 self.backup(u"full", dirlist[0], current_time=current_time,
40 options=backup_options)40 options=backup_options)
41 for new_dir in dirlist[1:]:41 for new_dir in dirlist[1:]:
42 current_time += 10000042 current_time += 100000
43 self.backup("inc", new_dir, current_time=current_time,43 self.backup(u"inc", new_dir, current_time=current_time,
44 options=backup_options)44 options=backup_options)
4545
46 # Restore each and compare them46 # Restore each and compare them
@@ -48,7 +48,7 @@
48 dirname = dirlist[i]48 dirname = dirlist[i]
49 current_time = 100000 * (i + 1)49 current_time = 100000 * (i + 1)
50 self.restore(time=current_time, options=restore_options)50 self.restore(time=current_time, options=restore_options)
51 self.check_same(dirname, "testfiles/restore_out")51 self.check_same(dirname, u"testfiles/restore_out")
52 self.verify(dirname,52 self.verify(dirname,
53 time=current_time, options=restore_options)53 time=current_time, options=restore_options)
5454
@@ -59,57 +59,57 @@
5959
60 def test_basic_cycle(self, backup_options=[], restore_options=[]):60 def test_basic_cycle(self, backup_options=[], restore_options=[]):
61 """Run backup/restore test on basic directories"""61 """Run backup/restore test on basic directories"""
62 self.runtest(["testfiles/dir1",62 self.runtest([u"testfiles/dir1",
63 "testfiles/dir2",63 u"testfiles/dir2",
64 "testfiles/dir3"],64 u"testfiles/dir3"],
65 backup_options=backup_options,65 backup_options=backup_options,
66 restore_options=restore_options)66 restore_options=restore_options)
6767
68 # Test restoring various sub files68 # Test restoring various sub files
69 for filename, time, dir in [('symbolic_link', 99999, 'dir1'),69 for filename, time, dir in [(u'symbolic_link', 99999, u'dir1'),
70 ('directory_to_file', 100100, 'dir1'),70 (u'directory_to_file', 100100, u'dir1'),
71 ('directory_to_file', 200100, 'dir2'),71 (u'directory_to_file', 200100, u'dir2'),
72 ('largefile', 300000, 'dir3')]:72 (u'largefile', 300000, u'dir3')]:
73 self.restore(filename, time, options=restore_options)73 self.restore(filename, time, options=restore_options)
74 self.check_same('testfiles/%s/%s' % (dir, filename),74 self.check_same(u'testfiles/%s/%s' % (dir, filename),
75 'testfiles/restore_out')75 u'testfiles/restore_out')
76 self.verify('testfiles/%s/%s' % (dir, filename),76 self.verify(u'testfiles/%s/%s' % (dir, filename),
77 file_to_verify=filename, time=time,77 file_to_verify=filename, time=time,
78 options=restore_options)78 options=restore_options)
7979
80 def test_asym_cycle(self):80 def test_asym_cycle(self):
81 """Like test_basic_cycle but use asymmetric encryption and signing"""81 """Like test_basic_cycle but use asymmetric encryption and signing"""
82 backup_options = ["--encrypt-key", self.encrypt_key1,82 backup_options = [u"--encrypt-key", self.encrypt_key1,
83 "--sign-key", self.sign_key]83 u"--sign-key", self.sign_key]
84 restore_options = ["--encrypt-key", self.encrypt_key1,84 restore_options = [u"--encrypt-key", self.encrypt_key1,
85 "--sign-key", self.sign_key]85 u"--sign-key", self.sign_key]
86 self.test_basic_cycle(backup_options=backup_options,86 self.test_basic_cycle(backup_options=backup_options,
87 restore_options=restore_options)87 restore_options=restore_options)
8888
89 def test_asym_with_hidden_recipient_cycle(self):89 def test_asym_with_hidden_recipient_cycle(self):
90 """Like test_basic_cycle but use asymmetric encryption (hiding key id) and signing"""90 """Like test_basic_cycle but use asymmetric encryption (hiding key id) and signing"""
91 backup_options = ["--hidden-encrypt-key", self.encrypt_key1,91 backup_options = [u"--hidden-encrypt-key", self.encrypt_key1,
92 "--sign-key", self.sign_key]92 u"--sign-key", self.sign_key]
93 restore_options = ["--hidden-encrypt-key", self.encrypt_key1,93 restore_options = [u"--hidden-encrypt-key", self.encrypt_key1,
94 "--sign-key", self.sign_key]94 u"--sign-key", self.sign_key]
95 self.test_basic_cycle(backup_options=backup_options,95 self.test_basic_cycle(backup_options=backup_options,
96 restore_options=restore_options)96 restore_options=restore_options)
9797
98 def test_single_regfile(self):98 def test_single_regfile(self):
99 """Test backing and restoring up a single regular file"""99 """Test backing and restoring up a single regular file"""
100 self.runtest(["testfiles/various_file_types/regular_file"])100 self.runtest([u"testfiles/various_file_types/regular_file"])
101101
102 def test_empty_backup(self):102 def test_empty_backup(self):
103 """Make sure backup works when no files change"""103 """Make sure backup works when no files change"""
104 self.backup("full", "testfiles/empty_dir")104 self.backup(u"full", u"testfiles/empty_dir")
105 self.backup("inc", "testfiles/empty_dir")105 self.backup(u"inc", u"testfiles/empty_dir")
106106
107 def test_long_filenames(self):107 def test_long_filenames(self):
108 """Test backing up a directory with long filenames in it"""108 """Test backing up a directory with long filenames in it"""
109 # Note that some versions of ecryptfs (at least through Ubuntu 11.10)109 # Note that some versions of ecryptfs (at least through Ubuntu 11.10)
110 # have a bug where they treat the max path segment length as 143110 # have a bug where they treat the max path segment length as 143
111 # instead of 255. So make sure that these segments don't break that.111 # instead of 255. So make sure that these segments don't break that.
112 lf_dir = path.Path("testfiles/long_filenames")112 lf_dir = path.Path(u"testfiles/long_filenames")
113 if lf_dir.exists():113 if lf_dir.exists():
114 lf_dir.deltree()114 lf_dir.deltree()
115 lf_dir.mkdir()115 lf_dir.mkdir()
@@ -130,36 +130,36 @@
130 fp.write("hello" * 1000)130 fp.write("hello" * 1000)
131 assert not fp.close()131 assert not fp.close()
132132
133 self.runtest(["testfiles/empty_dir", lf_dir.name,133 self.runtest([u"testfiles/empty_dir", lf_dir.uc_name,
134 "testfiles/empty_dir", lf_dir.name])134 u"testfiles/empty_dir", lf_dir.uc_name])
135135
136 def test_empty_restore(self):136 def test_empty_restore(self):
137 """Make sure error raised when restore doesn't match anything"""137 """Make sure error raised when restore doesn't match anything"""
138 self.backup("full", "testfiles/dir1")138 self.backup(u"full", u"testfiles/dir1")
139 self.assertRaises(CmdError, self.restore, "this_file_does_not_exist")139 self.assertRaises(CmdError, self.restore, u"this_file_does_not_exist")
140 self.backup("inc", "testfiles/empty_dir")140 self.backup(u"inc", u"testfiles/empty_dir")
141 self.assertRaises(CmdError, self.restore, "this_file_does_not_exist")141 self.assertRaises(CmdError, self.restore, u"this_file_does_not_exist")
142142
143 def test_remove_older_than(self):143 def test_remove_older_than(self):
144 """Test removing old backup chains"""144 """Test removing old backup chains"""
145 first_chain = self.backup("full", "testfiles/dir1", current_time=10000)145 first_chain = self.backup(u"full", u"testfiles/dir1", current_time=10000)
146 first_chain |= self.backup("inc", "testfiles/dir2", current_time=20000)146 first_chain |= self.backup(u"inc", u"testfiles/dir2", current_time=20000)
147 second_chain = self.backup("full", "testfiles/dir1", current_time=30000)147 second_chain = self.backup(u"full", u"testfiles/dir1", current_time=30000)
148 second_chain |= self.backup("inc", "testfiles/dir3", current_time=40000)148 second_chain |= self.backup(u"inc", u"testfiles/dir3", current_time=40000)
149149
150 self.assertEqual(self.get_backend_files(), first_chain | second_chain)150 self.assertEqual(self.get_backend_files(), first_chain | second_chain)
151151
152 self.run_duplicity(options=["remove-older-than", "35000", "--force", self.backend_url])152 self.run_duplicity(options=[u"remove-older-than", u"35000", u"--force", self.backend_url])
153 self.assertEqual(self.get_backend_files(), second_chain)153 self.assertEqual(self.get_backend_files(), second_chain)
154154
155 # Now check to make sure we can't delete only chain155 # Now check to make sure we can't delete only chain
156 self.run_duplicity(options=["remove-older-than", "50000", "--force", self.backend_url])156 self.run_duplicity(options=[u"remove-older-than", u"50000", u"--force", self.backend_url])
157 self.assertEqual(self.get_backend_files(), second_chain)157 self.assertEqual(self.get_backend_files(), second_chain)
158158
159 def test_piped_password(self):159 def test_piped_password(self):
160 """Make sure that prompting for a password works"""160 """Make sure that prompting for a password works"""
161 self.set_environ("PASSPHRASE", None)161 self.set_environ(u"PASSPHRASE", None)
162 self.backup("full", "testfiles/empty_dir",162 self.backup(u"full", u"testfiles/empty_dir",
163 passphrase_input=[self.sign_passphrase, self.sign_passphrase])163 passphrase_input=[self.sign_passphrase, self.sign_passphrase])
164 self.restore(passphrase_input=[self.sign_passphrase])164 self.restore(passphrase_input=[self.sign_passphrase])
165165
@@ -168,14 +168,14 @@
168168
169 def setUp(self):169 def setUp(self):
170 super(OldFilenamesFinalTest, self).setUp()170 super(OldFilenamesFinalTest, self).setUp()
171 self.class_args.extend(["--old-filenames"])171 self.class_args.extend([u"--old-filenames"])
172172
173173
174class ShortFilenamesFinalTest(FinalTest):174class ShortFilenamesFinalTest(FinalTest):
175175
176 def setUp(self):176 def setUp(self):
177 super(ShortFilenamesFinalTest, self).setUp()177 super(ShortFilenamesFinalTest, self).setUp()
178 self.class_args.extend(["--short-filenames"])178 self.class_args.extend([u"--short-filenames"])
179179
180if __name__ == "__main__":180if __name__ == "__main__":
181 unittest.main()181 unittest.main()
182182
=== modified file 'testing/functional/test_replicate.py'
--- testing/functional/test_replicate.py 2017-06-20 15:20:35 +0000
+++ testing/functional/test_replicate.py 2017-12-01 23:01:42 +0000
@@ -34,17 +34,17 @@
34 def runtest(self, dirlist, backup_options=[], replicate_options=[], restore_options=[]):34 def runtest(self, dirlist, backup_options=[], replicate_options=[], restore_options=[]):
35 # Back up directories to local backend35 # Back up directories to local backend
36 current_time = 10000036 current_time = 100000
37 self.backup("full", dirlist[0], current_time=current_time,37 self.backup(u"full", dirlist[0], current_time=current_time,
38 options=backup_options)38 options=backup_options)
39 for new_dir in dirlist[1:]:39 for new_dir in dirlist[1:]:
40 current_time += 10000040 current_time += 100000
41 self.backup("inc", new_dir, current_time=current_time,41 self.backup(u"inc", new_dir, current_time=current_time,
42 options=backup_options)42 options=backup_options)
4343
44 # Replicate to other backend44 # Replicate to other backend
45 source_url = self.backend_url45 source_url = self.backend_url
46 target_url = "file://testfiles/replicate_out"46 target_url = u"file://testfiles/replicate_out"
47 self.run_duplicity(options=["replicate"] +47 self.run_duplicity(options=[u"replicate"] +
48 replicate_options + [source_url, target_url])48 replicate_options + [source_url, target_url])
4949
50 self.backend_url = target_url50 self.backend_url = target_url
@@ -54,7 +54,7 @@
54 dirname = dirlist[i]54 dirname = dirlist[i]
55 current_time = 100000 * (i + 1)55 current_time = 100000 * (i + 1)
56 self.restore(time=current_time, options=restore_options)56 self.restore(time=current_time, options=restore_options)
57 self.check_same(dirname, "testfiles/restore_out")57 self.check_same(dirname, u"testfiles/restore_out")
58 self.verify(dirname,58 self.verify(dirname,
59 time=current_time, options=restore_options)59 time=current_time, options=restore_options)
6060
@@ -65,15 +65,15 @@
6565
66 def test_replicate(self):66 def test_replicate(self):
67 """Test replication"""67 """Test replication"""
68 self.runtest(["testfiles/dir1", "testfiles/dir2"])68 self.runtest([u"testfiles/dir1", u"testfiles/dir2"])
6969
70 def test_replicate_noencryption(self):70 def test_replicate_noencryption(self):
71 """Test replication with decryption"""71 """Test replication with decryption"""
72 self.runtest(["testfiles/dir1", "testfiles/dir2"],72 self.runtest([u"testfiles/dir1", u"testfiles/dir2"],
73 replicate_options=["--no-encryption"])73 replicate_options=[u"--no-encryption"])
7474
75 def test_replicate_asym(self):75 def test_replicate_asym(self):
76 """Test replication with reencryption"""76 """Test replication with reencryption"""
77 asym_options = ["--encrypt-key", self.encrypt_key1]77 asym_options = [u"--encrypt-key", self.encrypt_key1]
78 self.runtest(["testfiles/dir1", "testfiles/dir2"],78 self.runtest([u"testfiles/dir1", u"testfiles/dir2"],
79 replicate_options=asym_options, restore_options=asym_options)79 replicate_options=asym_options, restore_options=asym_options)
8080
=== modified file 'testing/functional/test_restart.py'
--- testing/functional/test_restart.py 2017-07-11 14:55:38 +0000
+++ testing/functional/test_restart.py 2017-12-01 23:01:42 +0000
@@ -37,20 +37,20 @@
37 Test basic Checkpoint/Restart37 Test basic Checkpoint/Restart
38 """38 """
39 self.make_largefiles()39 self.make_largefiles()
40 self.backup("full", "testfiles/largefiles", fail=1)40 self.backup(u"full", u"testfiles/largefiles", fail=1)
41 self.backup("full", "testfiles/largefiles")41 self.backup(u"full", u"testfiles/largefiles")
42 self.verify("testfiles/largefiles")42 self.verify(u"testfiles/largefiles")
4343
44 def test_multiple_checkpoint_restart(self):44 def test_multiple_checkpoint_restart(self):
45 """45 """
46 Test multiple Checkpoint/Restart46 Test multiple Checkpoint/Restart
47 """47 """
48 self.make_largefiles()48 self.make_largefiles()
49 self.backup("full", "testfiles/largefiles", fail=1)49 self.backup(u"full", u"testfiles/largefiles", fail=1)
50 self.backup("full", "testfiles/largefiles", fail=2)50 self.backup(u"full", u"testfiles/largefiles", fail=2)
51 self.backup("full", "testfiles/largefiles", fail=3)51 self.backup(u"full", u"testfiles/largefiles", fail=3)
52 self.backup("full", "testfiles/largefiles")52 self.backup(u"full", u"testfiles/largefiles")
53 self.verify("testfiles/largefiles")53 self.verify(u"testfiles/largefiles")
5454
55 def test_first_volume_failure(self):55 def test_first_volume_failure(self):
56 """56 """
@@ -58,10 +58,10 @@
58 Caused when duplicity fails before the first transfer.58 Caused when duplicity fails before the first transfer.
59 """59 """
60 self.make_largefiles()60 self.make_largefiles()
61 self.backup("full", "testfiles/largefiles", fail=1)61 self.backup(u"full", u"testfiles/largefiles", fail=1)
62 assert not os.system("rm testfiles/output/duplicity-full*difftar*")62 assert not os.system(u"rm testfiles/output/duplicity-full*difftar*")
63 self.backup("full", "testfiles/largefiles")63 self.backup(u"full", u"testfiles/largefiles")
64 self.verify("testfiles/largefiles")64 self.verify(u"testfiles/largefiles")
6565
66 def test_multi_volume_failure(self):66 def test_multi_volume_failure(self):
67 """67 """
@@ -70,10 +70,10 @@
70 fails the last queued transfer(s).70 fails the last queued transfer(s).
71 """71 """
72 self.make_largefiles()72 self.make_largefiles()
73 self.backup("full", "testfiles/largefiles", fail=3)73 self.backup(u"full", u"testfiles/largefiles", fail=3)
74 assert not os.system("rm testfiles/output/duplicity-full*vol[23].difftar*")74 assert not os.system(u"rm testfiles/output/duplicity-full*vol[23].difftar*")
75 self.backup("full", "testfiles/largefiles")75 self.backup(u"full", u"testfiles/largefiles")
76 self.verify("testfiles/largefiles")76 self.verify(u"testfiles/largefiles")
7777
78 def test_restart_sign_and_encrypt(self):78 def test_restart_sign_and_encrypt(self):
79 """79 """
@@ -81,10 +81,10 @@
81 https://bugs.launchpad.net/duplicity/+bug/94698881 https://bugs.launchpad.net/duplicity/+bug/946988
82 """82 """
83 self.make_largefiles()83 self.make_largefiles()
84 enc_opts = ["--sign-key", self.sign_key, "--encrypt-key", self.sign_key]84 enc_opts = [u"--sign-key", self.sign_key, u"--encrypt-key", self.sign_key]
85 self.backup("full", "testfiles/largefiles", options=enc_opts, fail=2)85 self.backup(u"full", u"testfiles/largefiles", options=enc_opts, fail=2)
86 self.backup("full", "testfiles/largefiles", options=enc_opts)86 self.backup(u"full", u"testfiles/largefiles", options=enc_opts)
87 self.verify("testfiles/largefiles")87 self.verify(u"testfiles/largefiles")
8888
89 def test_restart_sign_and_hidden_encrypt(self):89 def test_restart_sign_and_hidden_encrypt(self):
90 """90 """
@@ -92,10 +92,10 @@
92 https://bugs.launchpad.net/duplicity/+bug/94698892 https://bugs.launchpad.net/duplicity/+bug/946988
93 """93 """
94 self.make_largefiles()94 self.make_largefiles()
95 enc_opts = ["--sign-key", self.sign_key, "--hidden-encrypt-key", self.sign_key]95 enc_opts = [u"--sign-key", self.sign_key, u"--hidden-encrypt-key", self.sign_key]
96 self.backup("full", "testfiles/largefiles", options=enc_opts, fail=2)96 self.backup(u"full", u"testfiles/largefiles", options=enc_opts, fail=2)
97 self.backup("full", "testfiles/largefiles", options=enc_opts)97 self.backup(u"full", u"testfiles/largefiles", options=enc_opts)
98 self.verify("testfiles/largefiles")98 self.verify(u"testfiles/largefiles")
9999
100 def test_last_file_missing_in_middle(self):100 def test_last_file_missing_in_middle(self):
101 """101 """
@@ -104,12 +104,12 @@
104 the file in the middle of the backup, with files following.104 the file in the middle of the backup, with files following.
105 """105 """
106 self.make_largefiles()106 self.make_largefiles()
107 self.backup("full", "testfiles/largefiles", fail=3)107 self.backup(u"full", u"testfiles/largefiles", fail=3)
108 assert not os.system("rm testfiles/largefiles/file2")108 assert not os.system(u"rm testfiles/largefiles/file2")
109 self.backup("full", "testfiles/largefiles")109 self.backup(u"full", u"testfiles/largefiles")
110 # TODO: we can't verify but we need to to check for other errors that might show up110 # TODO: we can't verify but we need to to check for other errors that might show up
111 # there should be 2 differences found, one missing file, one mtime change111 # there should be 2 differences found, one missing file, one mtime change
112 # self.verify("testfiles/largefiles")112 # self.verify(u"testfiles/largefiles")
113113
114 def test_last_file_missing_at_end(self):114 def test_last_file_missing_at_end(self):
115 """115 """
@@ -118,22 +118,22 @@
118 the file at the end of the backup, with no files following.118 the file at the end of the backup, with no files following.
119 """119 """
120 self.make_largefiles()120 self.make_largefiles()
121 self.backup("full", "testfiles/largefiles", fail=6)121 self.backup(u"full", u"testfiles/largefiles", fail=6)
122 assert not os.system("rm testfiles/largefiles/file3")122 assert not os.system(u"rm testfiles/largefiles/file3")
123 self.backup("full", "testfiles/largefiles")123 self.backup(u"full", u"testfiles/largefiles")
124 # TODO: we can't verify but we need to to check for other errors that might show up124 # TODO: we can't verify but we need to to check for other errors that might show up
125 # there should be 2 differences found, one missing file, one mtime change125 # there should be 2 differences found, one missing file, one mtime change
126 # self.verify("testfiles/largefiles")126 # self.verify(u"testfiles/largefiles")
127127
128 def test_restart_incremental(self):128 def test_restart_incremental(self):
129 """129 """
130 Test restarting an incremental backup130 Test restarting an incremental backup
131 """131 """
132 self.make_largefiles()132 self.make_largefiles()
133 self.backup("full", "testfiles/dir1")133 self.backup(u"full", u"testfiles/dir1")
134 self.backup("inc", "testfiles/largefiles", fail=2)134 self.backup(u"inc", u"testfiles/largefiles", fail=2)
135 self.backup("inc", "testfiles/largefiles")135 self.backup(u"inc", u"testfiles/largefiles")
136 self.verify("testfiles/largefiles")136 self.verify(u"testfiles/largefiles")
137137
138 def make_fake_second_volume(self, name):138 def make_fake_second_volume(self, name):
139 """139 """
@@ -175,16 +175,16 @@
175 If we restart right after a volume that ended with a small175 If we restart right after a volume that ended with a small
176 (one-block) file, make sure we restart in the right place.176 (one-block) file, make sure we restart in the right place.
177 """177 """
178 source = 'testfiles/largefiles'178 source = u'testfiles/largefiles'
179 assert not os.system("mkdir -p %s" % source)179 assert not os.system("mkdir -p %s" % source)
180 assert not os.system("echo hello > %s/file1" % source)180 assert not os.system("echo hello > %s/file1" % source)
181 self.backup("full", source, options=["--name=backup1"])181 self.backup(u"full", source, options=[u"--name=backup1"])
182 # Fake an interruption182 # Fake an interruption
183 self.make_fake_second_volume("backup1")183 self.make_fake_second_volume(u"backup1")
184 # Add new file184 # Add new file
185 assert not os.system("cp %s/file1 %s/newfile" % (source, source))185 assert not os.system("cp %s/file1 %s/newfile" % (source, source))
186 # 'restart' the backup186 # 'restart' the backup
187 self.backup("full", source, options=["--name=backup1"])187 self.backup(u"full", source, options=[u"--name=backup1"])
188 # Confirm we actually resumed the previous backup188 # Confirm we actually resumed the previous backup
189 self.assertEqual(len(os.listdir("testfiles/output")), 4)189 self.assertEqual(len(os.listdir("testfiles/output")), 4)
190 # Now make sure everything is byte-for-byte the same once restored190 # Now make sure everything is byte-for-byte the same once restored
@@ -196,15 +196,15 @@
196 If we restart right after a volume that ended with a large196 If we restart right after a volume that ended with a large
197 (multi-block) file, make sure we restart in the right place.197 (multi-block) file, make sure we restart in the right place.
198 """198 """
199 source = 'testfiles/largefiles'199 source = u'testfiles/largefiles'
200 self.make_largefiles(count=1, size=1)200 self.make_largefiles(count=1, size=1)
201 self.backup("full", source, options=["--volsize=5", "--name=backup1"])201 self.backup(u"full", source, options=[u"--volsize=5", u"--name=backup1"])
202 # Fake an interruption202 # Fake an interruption
203 self.make_fake_second_volume("backup1")203 self.make_fake_second_volume(u"backup1")
204 # Add new file204 # Add new file
205 assert not os.system("cp %s/file1 %s/newfile" % (source, source))205 assert not os.system("cp %s/file1 %s/newfile" % (source, source))
206 # 'restart' the backup206 # 'restart' the backup
207 self.backup("full", source, options=["--volsize=5", "--name=backup1"])207 self.backup(u"full", source, options=[u"--volsize=5", u"--name=backup1"])
208 # Confirm we actually resumed the previous backup208 # Confirm we actually resumed the previous backup
209 self.assertEqual(len(os.listdir("testfiles/output")), 4)209 self.assertEqual(len(os.listdir("testfiles/output")), 4)
210 # Now make sure everything is byte-for-byte the same once restored210 # Now make sure everything is byte-for-byte the same once restored
@@ -216,13 +216,13 @@
216 If we restart right after a volume that ended inside of a large216 If we restart right after a volume that ended inside of a large
217 (multi-block) file, make sure we restart in the right place.217 (multi-block) file, make sure we restart in the right place.
218 """218 """
219 source = 'testfiles/largefiles'219 source = u'testfiles/largefiles'
220 self.make_largefiles(count=1, size=3)220 self.make_largefiles(count=1, size=3)
221 self.backup("full", source, options=["--name=backup1"])221 self.backup(u"full", source, options=[u"--name=backup1"])
222 # Fake an interruption222 # Fake an interruption
223 self.make_fake_second_volume("backup1")223 self.make_fake_second_volume(u"backup1")
224 # 'restart' the backup224 # 'restart' the backup
225 self.backup("full", source, options=["--name=backup1"])225 self.backup(u"full", source, options=[u"--name=backup1"])
226 # Now make sure everything is byte-for-byte the same once restored226 # Now make sure everything is byte-for-byte the same once restored
227 self.restore()227 self.restore()
228 assert not os.system("diff -r %s testfiles/restore_out" % source)228 assert not os.system("diff -r %s testfiles/restore_out" % source)
@@ -234,16 +234,16 @@
234 (Expected result is to ignore new, ealier files, but pick up later234 (Expected result is to ignore new, ealier files, but pick up later
235 ones.)235 ones.)
236 """236 """
237 source = 'testfiles/largefiles'237 source = u'testfiles/largefiles'
238 self.make_largefiles(count=1, size=1)238 self.make_largefiles(count=1, size=1)
239 self.backup("full", source, options=["--name=backup1"])239 self.backup(u"full", source, options=[u"--name=backup1"])
240 # Fake an interruption240 # Fake an interruption
241 self.make_fake_second_volume("backup1")241 self.make_fake_second_volume(u"backup1")
242 # Add new files, earlier and later in filename sort order242 # Add new files, earlier and later in filename sort order
243 assert not os.system("echo hello > %s/a" % source)243 assert not os.system("echo hello > %s/a" % source)
244 assert not os.system("echo hello > %s/z" % source)244 assert not os.system("echo hello > %s/z" % source)
245 # 'restart' the backup245 # 'restart' the backup
246 self.backup("full", source, options=["--name=backup1"])246 self.backup(u"full", source, options=[u"--name=backup1"])
247 # Now make sure everything is the same once restored, except 'a'247 # Now make sure everything is the same once restored, except 'a'
248 self.restore()248 self.restore()
249 assert not os.system("test ! -e testfiles/restore_out/a")249 assert not os.system("test ! -e testfiles/restore_out/a")
@@ -258,15 +258,15 @@
258 if the source data changes to be small enough to not create a vol3 on258 if the source data changes to be small enough to not create a vol3 on
259 restart.259 restart.
260 """260 """
261 source = 'testfiles/largefiles'261 source = u'testfiles/largefiles'
262 self.make_largefiles(count=5, size=1)262 self.make_largefiles(count=5, size=1)
263 self.backup("full", source, fail=3)263 self.backup(u"full", source, fail=3)
264 # now delete the last volume on remote end and some source files264 # now delete the last volume on remote end and some source files
265 assert not os.system("rm testfiles/output/duplicity-full*vol3.difftar*")265 assert not os.system("rm testfiles/output/duplicity-full*vol3.difftar*")
266 assert not os.system("rm %s/file[2345]" % source)266 assert not os.system("rm %s/file[2345]" % source)
267 assert not os.system("echo hello > %s/z" % source)267 assert not os.system("echo hello > %s/z" % source)
268 # finish backup268 # finish backup
269 self.backup("full", source)269 self.backup(u"full", source)
270 # and verify we can restore270 # and verify we can restore
271 self.restore()271 self.restore()
272272
@@ -277,14 +277,14 @@
277 possible that the first chunk of the next file will be skipped unless277 possible that the first chunk of the next file will be skipped unless
278 we're careful.278 we're careful.
279 """279 """
280 source = 'testfiles/largefiles'280 source = u'testfiles/largefiles'
281 self.make_largefiles(count=1)281 self.make_largefiles(count=1)
282 self.backup("full", source, fail=2)282 self.backup(u"full", source, fail=2)
283 # now remove starting source data and make sure we add something after283 # now remove starting source data and make sure we add something after
284 assert not os.system("rm %s/*" % source)284 assert not os.system("rm %s/*" % source)
285 assert not os.system("echo hello > %s/z" % source)285 assert not os.system("echo hello > %s/z" % source)
286 # finish backup286 # finish backup
287 self.backup("full", source)287 self.backup(u"full", source)
288 # and verify we can restore288 # and verify we can restore
289 self.restore()289 self.restore()
290 assert not os.system("diff %s/z testfiles/restore_out/z" % source)290 assert not os.system("diff %s/z testfiles/restore_out/z" % source)
@@ -295,7 +295,7 @@
295295
296 def setUp(self):296 def setUp(self):
297 super(RestartTestWithoutEncryption, self).setUp()297 super(RestartTestWithoutEncryption, self).setUp()
298 self.class_args.extend(["--no-encryption"])298 self.class_args.extend([u"--no-encryption"])
299299
300 def test_no_write_double_snapshot(self):300 def test_no_write_double_snapshot(self):
301 """301 """
@@ -305,8 +305,8 @@
305 https://launchpad.net/bugs/929067305 https://launchpad.net/bugs/929067
306 """306 """
307 self.make_largefiles()307 self.make_largefiles()
308 self.backup("full", "testfiles/largefiles", fail=2)308 self.backup(u"full", u"testfiles/largefiles", fail=2)
309 self.backup("full", "testfiles/largefiles")309 self.backup(u"full", u"testfiles/largefiles")
310 # Now check sigtar310 # Now check sigtar
311 sigtars = glob.glob("testfiles/output/duplicity-full*.sigtar.gz")311 sigtars = glob.glob("testfiles/output/duplicity-full*.sigtar.gz")
312 self.assertEqual(1, len(sigtars))312 self.assertEqual(1, len(sigtars))
@@ -333,7 +333,7 @@
333 raise Exception("Platform %s not supported by tar/gtar." % platform.platform())333 raise Exception("Platform %s not supported by tar/gtar." % platform.platform())
334334
335 # Intial normal backup335 # Intial normal backup
336 self.backup("full", "testfiles/blocktartest")336 self.backup(u"full", u"testfiles/blocktartest")
337 # Create an exact clone of the snapshot folder in the sigtar already.337 # Create an exact clone of the snapshot folder in the sigtar already.
338 # Permissions and mtime must match.338 # Permissions and mtime must match.
339 os.mkdir("testfiles/snapshot", 0o755)339 os.mkdir("testfiles/snapshot", 0o755)
@@ -353,7 +353,7 @@
353 self.assertEqual(0, os.system("rm -r testfiles/cache"))353 self.assertEqual(0, os.system("rm -r testfiles/cache"))
354 # Try a follow on incremental (which in buggy versions, would create354 # Try a follow on incremental (which in buggy versions, would create
355 # a deleted entry for the base dir)355 # a deleted entry for the base dir)
356 self.backup("inc", "testfiles/blocktartest")356 self.backup(u"inc", u"testfiles/blocktartest")
357 self.assertEqual(1, len(glob.glob("testfiles/output/duplicity-new*.sigtar.gz")))357 self.assertEqual(1, len(glob.glob("testfiles/output/duplicity-new*.sigtar.gz")))
358 # Confirm we can restore it (which in buggy versions, would fail)358 # Confirm we can restore it (which in buggy versions, would fail)
359 self.restore()359 self.restore()
360360
=== modified file 'testing/functional/test_selection.py'
--- testing/functional/test_selection.py 2017-07-11 14:55:38 +0000
+++ testing/functional/test_selection.py 2017-12-01 23:01:42 +0000
@@ -1,3 +1,4 @@
1# -*- coding: utf-8 -*-
1# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-2# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
2#3#
3# Copyright 2014 Aaron Whitehouse <aaron@whitehouse.kiwi.nz>4# Copyright 2014 Aaron Whitehouse <aaron@whitehouse.kiwi.nz>
@@ -21,6 +22,7 @@
21import os22import os
22import sys23import sys
23import platform24import platform
25import io
2426
25import unittest27import unittest
2628
@@ -91,57 +93,57 @@
91 # --------- trailing_space sub2_file.txt (ea) # Excluded until trailing_space test, when (is)93 # --------- trailing_space sub2_file.txt (ea) # Excluded until trailing_space test, when (is)
9294
93 complete_directory_tree = [95 complete_directory_tree = [
94 ['1', '2', '3', 'trailing_space ', '1.doc', '1.py'],96 [u"1", u"2", u"3", u"trailing_space ", u"1.doc", u"1.py"],
95 ['1sub1', '1sub2', '1sub3'],97 [u"1sub1", u"1sub2", u"1sub3"],
96 ['1sub1sub1', '1sub1sub2', '1sub1sub3'],98 [u"1sub1sub1", u"1sub1sub2", u"1sub1sub3"],
97 ['1sub1sub1_file.txt'],99 [u"1sub1sub1_file.txt"],
98 ['1sub1sub2_file.txt'],100 [u"1sub1sub2_file.txt"],
99 ['1sub1sub3_file.txt'],101 [u"1sub1sub3_file.txt"],
100 ['1sub2sub1', '1sub2sub2', '1sub2sub3'],102 [u"1sub2sub1", u"1sub2sub2", u"1sub2sub3"],
101 ['1sub3sub1', '1sub3sub2', '1sub3sub3'],103 [u"1sub3sub1", u"1sub3sub2", u"1sub3sub3"],
102 ['2sub1', '2sub2', '2sub3'],104 [u"2sub1", u"2sub2", u"2sub3"],
103 ['2sub1sub1', '2sub1sub2', '2sub1sub3'],105 [u"2sub1sub1", u"2sub1sub2", u"2sub1sub3"],
104 ['2sub1sub1_file.txt'],106 [u"2sub1sub1_file.txt"],
105 ['2sub2sub1', '2sub2sub2', '2sub2sub3'],107 [u"2sub2sub1", u"2sub2sub2", u"2sub2sub3"],
106 ['2sub3sub1', '2sub3sub2', '2sub3sub3'],108 [u"2sub3sub1", u"2sub3sub2", u"2sub3sub3"],
107 ['3sub1', '3sub2', '3sub3'],109 [u"3sub1", u"3sub2", u"3sub3"],
108 ['3sub1sub1', '3sub1sub2', '3sub1sub3'],110 [u"3sub1sub1", u"3sub1sub2", u"3sub1sub3"],
109 ['3sub2sub1', '3sub2sub2', '3sub2sub3'],111 [u"3sub2sub1", u"3sub2sub2", u"3sub2sub3"],
110 ['3sub3sub1', '3sub3sub2', '3sub3sub3'],112 [u"3sub3sub1", u"3sub3sub2", u"3sub3sub3"],
111 ['3sub3sub2_file.txt'],113 [u"3sub3sub2_file.txt"],
112 ['trailing_space sub1', 'trailing_space sub2'],114 [u"trailing_space sub1", u"trailing_space sub2"],
113 ['trailing_space sub2_file.txt']115 [u"trailing_space sub2_file.txt"]
114 ]116 ]
115117
116 expected_restored_tree = [['1', '2', '3', '1.py'],118 expected_restored_tree = [[u"1", u"2", u"3", u"1.py"],
117 ['1sub1', '1sub2', '1sub3'],119 [u"1sub1", u"1sub2", u"1sub3"],
118 ['1sub1sub1', '1sub1sub3'],120 [u"1sub1sub1", u"1sub1sub3"],
119 ['1sub1sub1_file.txt'],121 [u"1sub1sub1_file.txt"],
120 ['1sub2sub1'],122 [u"1sub2sub1"],
121 ['1sub3sub3'],123 [u"1sub3sub3"],
122 ['2sub1'],124 [u"2sub1"],
123 ['2sub1sub1'],125 [u"2sub1sub1"],
124 ['2sub1sub1_file.txt'],126 [u"2sub1sub1_file.txt"],
125 ['3sub2', '3sub3'],127 [u"3sub2", u"3sub3"],
126 ['3sub2sub1', '3sub2sub2', '3sub2sub3'],128 [u"3sub2sub1", u"3sub2sub2", u"3sub2sub3"],
127 ['3sub3sub1', '3sub3sub2', '3sub3sub3'],129 [u"3sub3sub1", u"3sub3sub2", u"3sub3sub3"],
128 ['3sub3sub2_file.txt']]130 [u"3sub3sub2_file.txt"]]
129131
130 expected_restored_tree_with_trailing_space = [['1', '2', '3', 'trailing_space ', '1.py'],132 expected_restored_tree_with_trailing_space = [[u"1", u"2", u"3", u"trailing_space ", u"1.py"],
131 ['1sub1', '1sub2', '1sub3'],133 [u"1sub1", u"1sub2", u"1sub3"],
132 ['1sub1sub1', '1sub1sub3'],134 [u"1sub1sub1", u"1sub1sub3"],
133 ['1sub1sub1_file.txt'],135 [u"1sub1sub1_file.txt"],
134 ['1sub2sub1'],136 [u"1sub2sub1"],
135 ['1sub3sub3'],137 [u"1sub3sub3"],
136 ['2sub1'],138 [u"2sub1"],
137 ['2sub1sub1'],139 [u"2sub1sub1"],
138 ['2sub1sub1_file.txt'],140 [u"2sub1sub1_file.txt"],
139 ['3sub2', '3sub3'],141 [u"3sub2", u"3sub3"],
140 ['3sub2sub1', '3sub2sub2', '3sub2sub3'],142 [u"3sub2sub1", u"3sub2sub2", u"3sub2sub3"],
141 ['3sub3sub1', '3sub3sub2', '3sub3sub3'],143 [u"3sub3sub1", u"3sub3sub2", u"3sub3sub3"],
142 ['3sub3sub2_file.txt'],144 [u"3sub3sub2_file.txt"],
143 ['trailing_space sub1', 'trailing_space sub2'],145 [u"trailing_space sub1", u"trailing_space sub2"],
144 ['trailing_space sub2_file.txt']]146 [u"trailing_space sub2_file.txt"]]
145147
146 def directory_tree_to_list_of_lists(self, parent_directory):148 def directory_tree_to_list_of_lists(self, parent_directory):
147 """149 """
@@ -167,7 +169,7 @@
167169
168 def test_files_are_as_expected(self):170 def test_files_are_as_expected(self):
169 """Test that the contents of testfiles/select are as expected."""171 """Test that the contents of testfiles/select are as expected."""
170 testfiles = self.directory_tree_to_list_of_lists('testfiles/select2')172 testfiles = self.directory_tree_to_list_of_lists(u"testfiles/select2")
171 # print(testfiles)173 # print(testfiles)
172 self.assertEqual(testfiles, self.complete_directory_tree)174 self.assertEqual(testfiles, self.complete_directory_tree)
173175
@@ -177,28 +179,28 @@
177179
178 def test_include_exclude_basic(self):180 def test_include_exclude_basic(self):
179 """ Test --include and --exclude work in the basic case """181 """ Test --include and --exclude work in the basic case """
180 self.backup("full", "testfiles/select2",182 self.backup(u"full", u"testfiles/select2",
181 options=["--include", "testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",183 options=[u"--include", u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
182 "--exclude", "testfiles/select2/3/3sub3/3sub3sub2",184 u"--exclude", u"testfiles/select2/3/3sub3/3sub3sub2",
183 "--include", "testfiles/select2/3/3sub2/3sub2sub2",185 u"--include", u"testfiles/select2/3/3sub2/3sub2sub2",
184 "--include", "testfiles/select2/3/3sub3",186 u"--include", u"testfiles/select2/3/3sub3",
185 "--exclude", "testfiles/select2/3/3sub1",187 u"--exclude", u"testfiles/select2/3/3sub1",
186 "--exclude", "testfiles/select2/2/2sub1/2sub1sub3",188 u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub3",
187 "--exclude", "testfiles/select2/2/2sub1/2sub1sub2",189 u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub2",
188 "--include", "testfiles/select2/2/2sub1",190 u"--include", u"testfiles/select2/2/2sub1",
189 "--exclude", "testfiles/select2/1/1sub3/1sub3sub2",191 u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub2",
190 "--exclude", "testfiles/select2/1/1sub3/1sub3sub1",192 u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub1",
191 "--exclude", "testfiles/select2/1/1sub2/1sub2sub3",193 u"--exclude", u"testfiles/select2/1/1sub2/1sub2sub3",
192 "--include", "testfiles/select2/1/1sub2/1sub2sub1",194 u"--include", u"testfiles/select2/1/1sub2/1sub2sub1",
193 "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",195 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
194 "--exclude", "testfiles/select2/1/1sub1/1sub1sub2",196 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2",
195 "--exclude", "testfiles/select2/1/1sub2",197 u"--exclude", u"testfiles/select2/1/1sub2",
196 "--include", "testfiles/select2/1.py",198 u"--include", u"testfiles/select2/1.py",
197 "--include", "testfiles/select2/3",199 u"--include", u"testfiles/select2/3",
198 "--include", "testfiles/select2/1",200 u"--include", u"testfiles/select2/1",
199 "--exclude", "testfiles/select2/**"])201 u"--exclude", u"testfiles/select2/**"])
200 self.restore()202 self.restore()
201 restore_dir = 'testfiles/restore_out'203 restore_dir = u"testfiles/restore_out"
202 restored = self.directory_tree_to_list_of_lists(restore_dir)204 restored = self.directory_tree_to_list_of_lists(restore_dir)
203 self.assertEqual(restored, self.expected_restored_tree)205 self.assertEqual(restored, self.expected_restored_tree)
204206
@@ -207,32 +209,32 @@
207 # Note that, because this only passes items in as a list of options, this test does not test whether duplicity209 # Note that, because this only passes items in as a list of options, this test does not test whether duplicity
208 # would correctly interpret commandline options with spaces. However, bin/duplicity uses sys.argv[1:], which210 # would correctly interpret commandline options with spaces. However, bin/duplicity uses sys.argv[1:], which
209 # should return a list of strings after having correctly processed quotes etc.211 # should return a list of strings after having correctly processed quotes etc.
210 self.backup("full", "testfiles/select2",212 self.backup(u"full", u"testfiles/select2",
211 options=["--include",213 options=[u"--include",
212 "testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt",214 u"testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt",
213 "--exclude", "testfiles/select2/trailing_space /trailing_space sub2",215 u"--exclude", u"testfiles/select2/trailing_space /trailing_space sub2",
214 "--include", "testfiles/select2/trailing_space ",216 u"--include", u"testfiles/select2/trailing_space ",
215 "--include", "testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",217 u"--include", u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
216 "--exclude", "testfiles/select2/3/3sub3/3sub3sub2",218 u"--exclude", u"testfiles/select2/3/3sub3/3sub3sub2",
217 "--include", "testfiles/select2/3/3sub2/3sub2sub2",219 u"--include", u"testfiles/select2/3/3sub2/3sub2sub2",
218 "--include", "testfiles/select2/3/3sub3",220 u"--include", u"testfiles/select2/3/3sub3",
219 "--exclude", "testfiles/select2/3/3sub1",221 u"--exclude", u"testfiles/select2/3/3sub1",
220 "--exclude", "testfiles/select2/2/2sub1/2sub1sub3",222 u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub3",
221 "--exclude", "testfiles/select2/2/2sub1/2sub1sub2",223 u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub2",
222 "--include", "testfiles/select2/2/2sub1",224 u"--include", u"testfiles/select2/2/2sub1",
223 "--exclude", "testfiles/select2/1/1sub3/1sub3sub2",225 u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub2",
224 "--exclude", "testfiles/select2/1/1sub3/1sub3sub1",226 u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub1",
225 "--exclude", "testfiles/select2/1/1sub2/1sub2sub3",227 u"--exclude", u"testfiles/select2/1/1sub2/1sub2sub3",
226 "--include", "testfiles/select2/1/1sub2/1sub2sub1",228 u"--include", u"testfiles/select2/1/1sub2/1sub2sub1",
227 "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",229 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
228 "--exclude", "testfiles/select2/1/1sub1/1sub1sub2",230 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2",
229 "--exclude", "testfiles/select2/1/1sub2",231 u"--exclude", u"testfiles/select2/1/1sub2",
230 "--include", "testfiles/select2/1.py",232 u"--include", u"testfiles/select2/1.py",
231 "--include", "testfiles/select2/3",233 u"--include", u"testfiles/select2/3",
232 "--include", "testfiles/select2/1",234 u"--include", u"testfiles/select2/1",
233 "--exclude", "testfiles/select2/**"])235 u"--exclude", u"testfiles/select2/**"])
234 self.restore()236 self.restore()
235 restore_dir = 'testfiles/restore_out'237 restore_dir = u"testfiles/restore_out"
236 restored = self.directory_tree_to_list_of_lists(restore_dir)238 restored = self.directory_tree_to_list_of_lists(restore_dir)
237 self.assertEqual(restored, self.expected_restored_tree_with_trailing_space)239 self.assertEqual(restored, self.expected_restored_tree_with_trailing_space)
238240
@@ -246,29 +248,29 @@
246 """Test that exclude filelist works in the basic case """248 """Test that exclude filelist works in the basic case """
247 # As this is an exclude filelist any lines with no +/- modifier should be treated as if they have a -.249 # As this is an exclude filelist any lines with no +/- modifier should be treated as if they have a -.
248 # Create a filelist250 # Create a filelist
249 with open('testfiles/exclude.txt', 'w') as f:251 with io.open(u"testfiles/exclude.txt", u"w") as f:
250 f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'252 f.write(u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
251 'testfiles/select2/3/3sub3/3sub3sub2\n'253 u"testfiles/select2/3/3sub3/3sub3sub2\n"
252 '+ testfiles/select2/3/3sub2/3sub2sub2\n'254 u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
253 '+ testfiles/select2/3/3sub3\n'255 u"+ testfiles/select2/3/3sub3\n"
254 '- testfiles/select2/3/3sub1\n' # - added to ensure it makes no difference256 u"- testfiles/select2/3/3sub1\n" # - added to ensure it makes no difference
255 'testfiles/select2/2/2sub1/2sub1sub3\n'257 u"testfiles/select2/2/2sub1/2sub1sub3\n"
256 'testfiles/select2/2/2sub1/2sub1sub2\n'258 u"testfiles/select2/2/2sub1/2sub1sub2\n"
257 '+ testfiles/select2/2/2sub1\n'259 u"+ testfiles/select2/2/2sub1\n"
258 'testfiles/select2/1/1sub3/1sub3sub2\n'260 u"testfiles/select2/1/1sub3/1sub3sub2\n"
259 'testfiles/select2/1/1sub3/1sub3sub1\n'261 u"testfiles/select2/1/1sub3/1sub3sub1\n"
260 'testfiles/select2/1/1sub2/1sub2sub3\n'262 u"testfiles/select2/1/1sub2/1sub2sub3\n"
261 '+ testfiles/select2/1/1sub2/1sub2sub1\n'263 u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
262 'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'264 u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
263 'testfiles/select2/1/1sub1/1sub1sub2\n'265 u"testfiles/select2/1/1sub1/1sub1sub2\n"
264 '- testfiles/select2/1/1sub2\n' # - added to ensure it makes no difference266 u"- testfiles/select2/1/1sub2\n" # - added to ensure it makes no difference
265 '+ testfiles/select2/1.py\n'267 u"+ testfiles/select2/1.py\n"
266 '+ testfiles/select2/3\n'268 u"+ testfiles/select2/3\n"
267 '+ testfiles/select2/1\n'269 u"+ testfiles/select2/1\n"
268 'testfiles/select2/**')270 u"testfiles/select2/**")
269 self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"])271 self.backup(u"full", u"testfiles/select2", options=[u"--exclude-filelist=testfiles/exclude.txt"])
270 self.restore()272 self.restore()
271 restore_dir = 'testfiles/restore_out'273 restore_dir = u"testfiles/restore_out"
272 restored = self.directory_tree_to_list_of_lists(restore_dir)274 restored = self.directory_tree_to_list_of_lists(restore_dir)
273 self.assertEqual(restored, self.expected_restored_tree)275 self.assertEqual(restored, self.expected_restored_tree)
274276
@@ -285,33 +287,33 @@
285 # * Unnecessarily quoted filenames with/without modifier (both " and ')287 # * Unnecessarily quoted filenames with/without modifier (both " and ')
286288
287 # Create a filelist289 # Create a filelist
288 with open('testfiles/exclude.txt', 'w') as f:290 with io.open(u"testfiles/exclude.txt", u"w") as f:
289 f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'291 f.write(u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
290 'testfiles/select2/3/3sub3/3sub3sub2\n'292 u"testfiles/select2/3/3sub3/3sub3sub2\n"
291 '+ testfiles/select2/3/3sub2/3sub2sub2\n'293 u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
292 ' + testfiles/select2/3/3sub3\n' # Note leading space added here294 u" + testfiles/select2/3/3sub3\n" # Note leading space added here
293 '- testfiles/select2/3/3sub1\n'295 u"- testfiles/select2/3/3sub1\n"
294 ' testfiles/select2/2/2sub1/2sub1sub3\n' # Note leading spaces added here296 u" testfiles/select2/2/2sub1/2sub1sub3\n" # Note leading spaces added here
295 '\n'297 u"\n"
296 'testfiles/select2/2/2sub1/2sub1sub2\n'298 u"testfiles/select2/2/2sub1/2sub1sub2\n"
297 ' + testfiles/select2/2/2sub1 \n' # Note added trailing/leading space here299 u" + testfiles/select2/2/2sub1 \n" # Note added trailing/leading space here
298 '- "testfiles/select2/1/1sub3/1sub3sub2"\n' # Unnecessary quotes300 u'- "testfiles/select2/1/1sub3/1sub3sub2"\n' # Unnecessary quotes
299 '# Testing a full-line comment\n'301 u"# Testing a full-line comment\n"
300 "'testfiles/select2/1/1sub3/1sub3sub1' \n" # Note added spaces and quotes here302 u"'testfiles/select2/1/1sub3/1sub3sub1' \n" # Note added spaces and quotes here
301 'testfiles/select2/1/1sub2/1sub2sub3\n'303 u"testfiles/select2/1/1sub2/1sub2sub3\n"
302 ' \n'304 u" \n"
303 '+ testfiles/select2/1/1sub2/1sub2sub1\n'305 u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
304 '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'306 u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
305 'testfiles/select2/1/1sub1/1sub1sub2\n'307 u"testfiles/select2/1/1sub1/1sub1sub2\n"
306 ' # Testing a full-line comment with leading and trailing spaces \n'308 u" # Testing a full-line comment with leading and trailing spaces \n"
307 'testfiles/select2/1/1sub2 \n' # Note added spaces here309 u"testfiles/select2/1/1sub2 \n" # Note added spaces here
308 '+ testfiles/select2/1.py\n'310 u"+ testfiles/select2/1.py\n"
309 '+ testfiles/select2/3 \n' # Note added space here311 u"+ testfiles/select2/3 \n" # Note added space here
310 '+ testfiles/select2/1\n'312 u"+ testfiles/select2/1\n"
311 '- testfiles/select2/**')313 u"- testfiles/select2/**")
312 self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"])314 self.backup(u"full", u"testfiles/select2", options=[u"--exclude-filelist=testfiles/exclude.txt"])
313 self.restore()315 self.restore()
314 restore_dir = 'testfiles/restore_out'316 restore_dir = u"testfiles/restore_out"
315 restored = self.directory_tree_to_list_of_lists(restore_dir)317 restored = self.directory_tree_to_list_of_lists(restore_dir)
316 self.assertEqual(restored, self.expected_restored_tree)318 self.assertEqual(restored, self.expected_restored_tree)
317319
@@ -330,65 +332,65 @@
330 # * Unnecessarily quoted filenames with/without modifier (both " and ')332 # * Unnecessarily quoted filenames with/without modifier (both " and ')
331333
332 # Create a filelist334 # Create a filelist
333 with open('testfiles/exclude.txt', 'w') as f:335 with io.open(u"testfiles/exclude.txt", u"w") as f:
334 f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'336 f.write(u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
335 'testfiles/select2/3/3sub3/3sub3sub2\n'337 u"testfiles/select2/3/3sub3/3sub3sub2\n"
336 '+ testfiles/select2/3/3sub2/3sub2sub2\n'338 u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
337 ' + testfiles/select2/3/3sub3\n' # Note leading space added here339 u" + testfiles/select2/3/3sub3\n" # Note leading space added here
338 '- testfiles/select2/3/3sub1\n'340 u"- testfiles/select2/3/3sub1\n"
339 ' testfiles/select2/2/2sub1/2sub1sub3\n' # Note leading spaces added here341 u" testfiles/select2/2/2sub1/2sub1sub3\n" # Note leading spaces added here
340 '\n'342 u"\n"
341 'testfiles/select2/2/2sub1/2sub1sub2\n'343 u"testfiles/select2/2/2sub1/2sub1sub2\n"
342 ' + testfiles/select2/2/2sub1 \n' # Note added trailing/leading space here344 u" + testfiles/select2/2/2sub1 \n" # Note added trailing/leading space here
343 '- "testfiles/select2/1/1sub3/1sub3sub2"\n' # Unnecessary quotes345 u'- "testfiles/select2/1/1sub3/1sub3sub2"\n' # Unnecessary quotes
344 '# Testing a full-line comment\n'346 u"# Testing a full-line comment\n"
345 "'testfiles/select2/1/1sub3/1sub3sub1' \n" # Note added spaces and quotes here347 u"'testfiles/select2/1/1sub3/1sub3sub1' \n" # Note added spaces and quotes here
346 'testfiles/select2/1/1sub2/1sub2sub3\n'348 u"testfiles/select2/1/1sub2/1sub2sub3\n"
347 ' \n'349 u" \n"
348 '+ testfiles/select2/1/1sub2/1sub2sub1\n'350 u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
349 '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'351 u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
350 'testfiles/select2/1/1sub1/1sub1sub2\n'352 u"testfiles/select2/1/1sub1/1sub1sub2\n"
351 ' # Testing a full-line comment with leading and trailing spaces \n'353 u" # Testing a full-line comment with leading and trailing spaces \n"
352 'testfiles/select2/1/1sub2 \n' # Note added spaces here354 u"testfiles/select2/1/1sub2 \n" # Note added spaces here
353 '+ testfiles/select2/1.py\n'355 u"+ testfiles/select2/1.py\n"
354 '+ testfiles/select2/3 \n' # Note added space here356 u"+ testfiles/select2/3 \n" # Note added space here
355 '+ testfiles/select2/1\n'357 u"+ testfiles/select2/1\n"
356 '- testfiles/select2/**')358 u"- testfiles/select2/**")
357 self.backup("full", "testfiles/select2", options=["--exclude-globbing-filelist=testfiles/exclude.txt"])359 self.backup(u"full", u"testfiles/select2", options=[u"--exclude-globbing-filelist=testfiles/exclude.txt"])
358 self.restore()360 self.restore()
359 restore_dir = 'testfiles/restore_out'361 restore_dir = u"testfiles/restore_out"
360 restored = self.directory_tree_to_list_of_lists(restore_dir)362 restored = self.directory_tree_to_list_of_lists(restore_dir)
361 self.assertEqual(restored, self.expected_restored_tree)363 self.assertEqual(restored, self.expected_restored_tree)
362364
363 def test_exclude_filelist_trailing_whitespace_folders_work_with_quotes(self):365 def test_exclude_filelist_trailing_whitespace_folders_work_with_quotes(self):
364 """Test that folders with trailing whitespace in the names work correctly if they are enclosed in quotes"""366 """Test that folders with trailing whitespace in the names work correctly if they are enclosed in quotes"""
365 # Create a filelist367 # Create a filelist
366 with open('testfiles/exclude.txt', 'w') as f:368 with io.open(u"testfiles/exclude.txt", u"w") as f:
367 f.write('+ "testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt"\n' # New369 f.write(u'+ "testfiles/select2/trailing_space /trailing_space sub2/trailing_space sub2_file.txt"\n' # New
368 '- "testfiles/select2/trailing_space /trailing_space sub2"\n' # New370 u"- 'testfiles/select2/trailing_space /trailing_space sub2'\n" # New
369 '+ "testfiles/select2/trailing_space "\n' # New371 u'+ "testfiles/select2/trailing_space "\n' # New
370 '+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'372 u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
371 'testfiles/select2/3/3sub3/3sub3sub2\n'373 u"testfiles/select2/3/3sub3/3sub3sub2\n"
372 '+ testfiles/select2/3/3sub2/3sub2sub2\n'374 u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
373 '+ testfiles/select2/3/3sub3\n'375 u"+ testfiles/select2/3/3sub3\n"
374 '- testfiles/select2/3/3sub1\n'376 u"- testfiles/select2/3/3sub1\n"
375 'testfiles/select2/2/2sub1/2sub1sub3\n'377 u"testfiles/select2/2/2sub1/2sub1sub3\n"
376 'testfiles/select2/2/2sub1/2sub1sub2\n'378 u"testfiles/select2/2/2sub1/2sub1sub2\n"
377 '+ testfiles/select2/2/2sub1\n'379 u"+ testfiles/select2/2/2sub1\n"
378 'testfiles/select2/1/1sub3/1sub3sub2\n'380 u"testfiles/select2/1/1sub3/1sub3sub2\n"
379 'testfiles/select2/1/1sub3/1sub3sub1\n'381 u"testfiles/select2/1/1sub3/1sub3sub1\n"
380 'testfiles/select2/1/1sub2/1sub2sub3\n'382 u"testfiles/select2/1/1sub2/1sub2sub3\n"
381 '+ testfiles/select2/1/1sub2/1sub2sub1\n'383 u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
382 'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'384 u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
383 'testfiles/select2/1/1sub1/1sub1sub2\n'385 u"testfiles/select2/1/1sub1/1sub1sub2\n"
384 '- testfiles/select2/1/1sub2\n'386 u"- testfiles/select2/1/1sub2\n"
385 '+ testfiles/select2/1.py\n'387 u"+ testfiles/select2/1.py\n"
386 '+ testfiles/select2/3\n'388 u"+ testfiles/select2/3\n"
387 '+ testfiles/select2/1\n'389 u"+ testfiles/select2/1\n"
388 'testfiles/select2/**')390 u"testfiles/select2/**")
389 self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt"])391 self.backup(u"full", u"testfiles/select2", options=[u"--exclude-filelist=testfiles/exclude.txt"])
390 self.restore()392 self.restore()
391 restore_dir = 'testfiles/restore_out'393 restore_dir = u"testfiles/restore_out"
392 restored = self.directory_tree_to_list_of_lists(restore_dir)394 restored = self.directory_tree_to_list_of_lists(restore_dir)
393 self.assertEqual(restored, self.expected_restored_tree_with_trailing_space)395 self.assertEqual(restored, self.expected_restored_tree_with_trailing_space)
394396
@@ -396,32 +398,32 @@
396 """Test that exclude filelist is unaffected by the --progress option"""398 """Test that exclude filelist is unaffected by the --progress option"""
397 # Regression test for Bug #1264744 (https://bugs.launchpad.net/duplicity/+bug/1264744)399 # Regression test for Bug #1264744 (https://bugs.launchpad.net/duplicity/+bug/1264744)
398 # Create a filelist identical to that used in test_exclude_filelist400 # Create a filelist identical to that used in test_exclude_filelist
399 with open('testfiles/exclude.txt', 'w') as f:401 with io.open(u"testfiles/exclude.txt", u"w") as f:
400 f.write('+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'402 f.write(u"+ testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
401 'testfiles/select2/3/3sub3/3sub3sub2\n'403 u"testfiles/select2/3/3sub3/3sub3sub2\n"
402 '+ testfiles/select2/3/3sub2/3sub2sub2\n'404 u"+ testfiles/select2/3/3sub2/3sub2sub2\n"
403 '+ testfiles/select2/3/3sub3\n'405 u"+ testfiles/select2/3/3sub3\n"
404 '- testfiles/select2/3/3sub1\n' # - added to ensure it makes no difference406 u"- testfiles/select2/3/3sub1\n" # - added to ensure it makes no difference
405 'testfiles/select2/2/2sub1/2sub1sub3\n'407 u"testfiles/select2/2/2sub1/2sub1sub3\n"
406 'testfiles/select2/2/2sub1/2sub1sub2\n'408 u"testfiles/select2/2/2sub1/2sub1sub2\n"
407 '+ testfiles/select2/2/2sub1\n'409 u"+ testfiles/select2/2/2sub1\n"
408 'testfiles/select2/1/1sub3/1sub3sub2\n'410 u"testfiles/select2/1/1sub3/1sub3sub2\n"
409 'testfiles/select2/1/1sub3/1sub3sub1\n'411 u"testfiles/select2/1/1sub3/1sub3sub1\n"
410 'testfiles/select2/1/1sub2/1sub2sub3\n'412 u"testfiles/select2/1/1sub2/1sub2sub3\n"
411 '+ testfiles/select2/1/1sub2/1sub2sub1\n'413 u"+ testfiles/select2/1/1sub2/1sub2sub1\n"
412 'testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'414 u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
413 'testfiles/select2/1/1sub1/1sub1sub2\n'415 u"testfiles/select2/1/1sub1/1sub1sub2\n"
414 '- testfiles/select2/1/1sub2\n' # - added to ensure it makes no difference416 u"- testfiles/select2/1/1sub2\n" # - added to ensure it makes no difference
415 '+ testfiles/select2/1.py\n'417 u"+ testfiles/select2/1.py\n"
416 '+ testfiles/select2/3\n'418 u"+ testfiles/select2/3\n"
417 '+ testfiles/select2/1\n'419 u"+ testfiles/select2/1\n"
418 'testfiles/select2/**')420 u"testfiles/select2/**")
419421
420 # Backup the files exactly as in test_exclude_filelist, but with the --progress option422 # Backup the files exactly as in test_exclude_filelist, but with the --progress option
421 self.backup("full", "testfiles/select2", options=["--exclude-filelist=testfiles/exclude.txt",423 self.backup(u"full", u"testfiles/select2", options=[u"--exclude-filelist=testfiles/exclude.txt",
422 "--progress"])424 u"--progress"])
423 self.restore()425 self.restore()
424 restore_dir = 'testfiles/restore_out'426 restore_dir = u"testfiles/restore_out"
425 restored = self.directory_tree_to_list_of_lists(restore_dir)427 restored = self.directory_tree_to_list_of_lists(restore_dir)
426 # The restored files should match those restored in test_exclude_filelist428 # The restored files should match those restored in test_exclude_filelist
427 self.assertEqual(restored, self.expected_restored_tree)429 self.assertEqual(restored, self.expected_restored_tree)
@@ -437,29 +439,29 @@
437 # See test_exclude_filelist above for explanation of what is expected. As this is an include filelist439 # See test_exclude_filelist above for explanation of what is expected. As this is an include filelist
438 # any lines with no +/- modifier should be treated as if they have a +.440 # any lines with no +/- modifier should be treated as if they have a +.
439 # Create a filelist441 # Create a filelist
440 with open('testfiles/include.txt', 'w') as f:442 with io.open(u"testfiles/include.txt", u"w") as f:
441 f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'443 f.write(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
442 '- testfiles/select2/3/3sub3/3sub3sub2\n'444 u"- testfiles/select2/3/3sub3/3sub3sub2\n"
443 'testfiles/select2/3/3sub2/3sub2sub2\n'445 u"testfiles/select2/3/3sub2/3sub2sub2\n"
444 '+ testfiles/select2/3/3sub3\n' # + added to ensure it makes no difference446 u"+ testfiles/select2/3/3sub3\n" # + added to ensure it makes no difference
445 '- testfiles/select2/3/3sub1\n'447 u"- testfiles/select2/3/3sub1\n"
446 '- testfiles/select2/2/2sub1/2sub1sub3\n'448 u"- testfiles/select2/2/2sub1/2sub1sub3\n"
447 '- testfiles/select2/2/2sub1/2sub1sub2\n'449 u"- testfiles/select2/2/2sub1/2sub1sub2\n"
448 'testfiles/select2/2/2sub1\n'450 u"testfiles/select2/2/2sub1\n"
449 '- testfiles/select2/1/1sub3/1sub3sub2\n'451 u"- testfiles/select2/1/1sub3/1sub3sub2\n"
450 '- testfiles/select2/1/1sub3/1sub3sub1\n'452 u"- testfiles/select2/1/1sub3/1sub3sub1\n"
451 '- testfiles/select2/1/1sub2/1sub2sub3\n'453 u"- testfiles/select2/1/1sub2/1sub2sub3\n"
452 '+ testfiles/select2/1/1sub2/1sub2sub1\n' # + added to ensure it makes no difference454 u"+ testfiles/select2/1/1sub2/1sub2sub1\n" # + added to ensure it makes no difference
453 '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'455 u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
454 '- testfiles/select2/1/1sub1/1sub1sub2\n'456 u"- testfiles/select2/1/1sub1/1sub1sub2\n"
455 '- testfiles/select2/1/1sub2\n'457 u"- testfiles/select2/1/1sub2\n"
456 'testfiles/select2/1.py\n'458 u"testfiles/select2/1.py\n"
457 'testfiles/select2/3\n'459 u"testfiles/select2/3\n"
458 'testfiles/select2/1\n'460 u"testfiles/select2/1\n"
459 '- testfiles/select2/**')461 u"- testfiles/select2/**")
460 self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"])462 self.backup(u"full", u"testfiles/select2", options=[u"--include-filelist=testfiles/include.txt"])
461 self.restore()463 self.restore()
462 restore_dir = 'testfiles/restore_out'464 restore_dir = u"testfiles/restore_out"
463 restored = self.directory_tree_to_list_of_lists(restore_dir)465 restored = self.directory_tree_to_list_of_lists(restore_dir)
464 self.assertEqual(restored, self.expected_restored_tree)466 self.assertEqual(restored, self.expected_restored_tree)
465467
@@ -475,33 +477,33 @@
475 # * Full-line comments with # as the first character and with leading/trailing spaces477 # * Full-line comments with # as the first character and with leading/trailing spaces
476 # * Unnecessarily quoted filenames with/without modifier (both " and ')478 # * Unnecessarily quoted filenames with/without modifier (both " and ')
477 # Create a filelist479 # Create a filelist
478 with open('testfiles/include.txt', 'w') as f:480 with io.open(u"testfiles/include.txt", u"w") as f:
479 f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'481 f.write(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
480 '- testfiles/select2/3/3sub3/3sub3sub2\n'482 u"- testfiles/select2/3/3sub3/3sub3sub2\n"
481 '"testfiles/select2/3/3sub2/3sub2sub2"\n'483 u'"testfiles/select2/3/3sub2/3sub2sub2"\n'
482 ' + testfiles/select2/3/3sub3\n' # + added to ensure it makes no difference484 u" + testfiles/select2/3/3sub3\n" # + added to ensure it makes no difference
483 '- testfiles/select2/3/3sub1\n'485 u"- testfiles/select2/3/3sub1\n"
484 '- testfiles/select2/2/2sub1/2sub1sub3\n'486 u"- testfiles/select2/2/2sub1/2sub1sub3\n"
485 ' - "testfiles/select2/2/2sub1/2sub1sub2"\n'487 u' - "testfiles/select2/2/2sub1/2sub1sub2"\n'
486 'testfiles/select2/2/2sub1 \n'488 u"testfiles/select2/2/2sub1 \n"
487 '\n'489 u"\n"
488 '- testfiles/select2/1/1sub3/1sub3sub2\n'490 u"- testfiles/select2/1/1sub3/1sub3sub2\n"
489 '- testfiles/select2/1/1sub3/1sub3sub1 \n'491 u"- testfiles/select2/1/1sub3/1sub3sub1 \n"
490 "- 'testfiles/select2/1/1sub2/1sub2sub3'\n"492 u"- 'testfiles/select2/1/1sub2/1sub2sub3'\n"
491 ' \n'493 u" \n"
492 ' + testfiles/select2/1/1sub2/1sub2sub1 \n' # + added to ensure it makes no difference494 u" + testfiles/select2/1/1sub2/1sub2sub1 \n" # + added to ensure it makes no difference
493 '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'495 u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
494 ' - testfiles/select2/1/1sub1/1sub1sub2 \n'496 u" - testfiles/select2/1/1sub1/1sub1sub2 \n"
495 '# Testing full-line comment\n'497 u"# Testing full-line comment\n"
496 '- testfiles/select2/1/1sub2\n'498 u"- testfiles/select2/1/1sub2\n"
497 "'testfiles/select2/1.py'\n"499 u"'testfiles/select2/1.py'\n"
498 'testfiles/select2/3\n'500 u"testfiles/select2/3\n"
499 ' # Testing another full-line comment \n'501 u" # Testing another full-line comment \n"
500 'testfiles/select2/1\n'502 u"testfiles/select2/1\n"
501 '- testfiles/select2/**')503 u"- testfiles/select2/**")
502 self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"])504 self.backup(u"full", u"testfiles/select2", options=[u"--include-filelist=testfiles/include.txt"])
503 self.restore()505 self.restore()
504 restore_dir = 'testfiles/restore_out'506 restore_dir = u"testfiles/restore_out"
505 restored = self.directory_tree_to_list_of_lists(restore_dir)507 restored = self.directory_tree_to_list_of_lists(restore_dir)
506 self.assertEqual(restored, self.expected_restored_tree)508 self.assertEqual(restored, self.expected_restored_tree)
507509
@@ -519,37 +521,37 @@
519 # * Full-line comments with # as the first character and with leading/trailing spaces521 # * Full-line comments with # as the first character and with leading/trailing spaces
520 # * Unnecessarily quoted filenames with/without modifier (both " and ')522 # * Unnecessarily quoted filenames with/without modifier (both " and ')
521 # Create a filelist523 # Create a filelist
522 with open('testfiles/include.txt', 'w') as f:524 with io.open(u"testfiles/include.txt", u"w") as f:
523 f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'525 f.write(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
524 'testfiles/select2/3/3sub2/3sub2sub2 \n'526 u"testfiles/select2/3/3sub2/3sub2sub2 \n"
525 ' + testfiles/select2/3/3sub3\n' # + added to ensure it makes no difference527 u" + testfiles/select2/3/3sub3\n" # + added to ensure it makes no difference
526 ' - testfiles/select2/3/3sub1 \n'528 u" - testfiles/select2/3/3sub1 \n"
527 '- testfiles/select2/2/2sub1/2sub1sub3\n'529 u"- testfiles/select2/2/2sub1/2sub1sub3\n"
528 '- testfiles/select2/2/2sub1/2sub1sub2\n'530 u"- testfiles/select2/2/2sub1/2sub1sub2\n"
529 '"testfiles/select2/2/2sub1"\n'531 u'"testfiles/select2/2/2sub1"\n'
530 ' - testfiles/select2/2/2sub3 \n' # Added because of Bug #1408411532 u" - testfiles/select2/2/2sub3 \n" # Added because of Bug #1408411
531 '- testfiles/select2/2/2sub2\n' # Added because of Bug #1408411533 u"- testfiles/select2/2/2sub2\n" # Added because of Bug #1408411
532 "- 'testfiles/select2/1/1sub3/1sub3sub2'\n"534 u"- 'testfiles/select2/1/1sub3/1sub3sub2'\n"
533 '\n'535 u"\n"
534 '- testfiles/select2/1/1sub3/1sub3sub1\n'536 u"- testfiles/select2/1/1sub3/1sub3sub1\n"
535 '- testfiles/select2/1/1sub2/1sub2sub3\n'537 u"- testfiles/select2/1/1sub2/1sub2sub3\n"
536 '- "testfiles/select2/1/1sub2/1sub2sub2"\n' # Added because of Bug #1408411538 u'- "testfiles/select2/1/1sub2/1sub2sub2"\n' # Added because of Bug #1408411
537 '# This is a full-line comment\n'539 u"# This is a full-line comment\n"
538 '+ testfiles/select2/1/1sub2/1sub2sub1 \n' # + added to ensure it makes no difference540 u"+ testfiles/select2/1/1sub2/1sub2sub1 \n" # + added to ensure it makes no difference
539 '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'541 u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
540 ' \n'542 u" \n"
541 '- testfiles/select2/1/1sub1/1sub1sub2\n'543 u"- testfiles/select2/1/1sub1/1sub1sub2\n"
542 # '- testfiles/select2/1/1sub2\n' # Commented out because of Bug #1408411544 # u"- testfiles/select2/1/1sub2\n" # Commented out because of Bug #1408411
543 "'testfiles/select2/1.py'\n"545 u"'testfiles/select2/1.py'\n"
544 ' # This is another full-line comment, with spaces \n'546 u" # This is another full-line comment, with spaces \n"
545 'testfiles/select2/3\n'547 u"testfiles/select2/3\n"
546 # '- testfiles/select2/2\n' # Commented out because of Bug #1408411548 # u"- testfiles/select2/2\n" # Commented out because of Bug #1408411
547 'testfiles/select2/1\n'549 u"testfiles/select2/1\n"
548 '- "testfiles/select2/trailing_space "\n' # es instead of ea as no wildcard - **550 u'- "testfiles/select2/trailing_space "\n' # es instead of ea as no wildcard - **
549 '- testfiles/select2/1.doc') # es instead of ea as no wildcard - **551 u"- testfiles/select2/1.doc") # es instead of ea as no wildcard - **
550 self.backup("full", "testfiles/select2", options=["--include-filelist=testfiles/include.txt"])552 self.backup(u"full", u"testfiles/select2", options=[u"--include-filelist=testfiles/include.txt"])
551 self.restore()553 self.restore()
552 restore_dir = 'testfiles/restore_out'554 restore_dir = u"testfiles/restore_out"
553 restored = self.directory_tree_to_list_of_lists(restore_dir)555 restored = self.directory_tree_to_list_of_lists(restore_dir)
554 self.assertEqual(restored, self.expected_restored_tree)556 self.assertEqual(restored, self.expected_restored_tree)
555557
@@ -567,33 +569,33 @@
567 # * Full-line comments with # as the first character and with leading/trailing spaces569 # * Full-line comments with # as the first character and with leading/trailing spaces
568 # * Unnecessarily quoted filenames with/without modifier (both " and ')570 # * Unnecessarily quoted filenames with/without modifier (both " and ')
569 # Create a filelist571 # Create a filelist
570 with open('testfiles/include.txt', 'w') as f:572 with io.open(u"testfiles/include.txt", u"w") as f:
571 f.write('testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n'573 f.write(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt\n"
572 '- testfiles/select2/3/3sub3/3sub3sub2\n'574 u"- testfiles/select2/3/3sub3/3sub3sub2\n"
573 '"testfiles/select2/3/3sub2/3sub2sub2"\n'575 u'"testfiles/select2/3/3sub2/3sub2sub2"\n'
574 ' + testfiles/select2/3/3sub3\n' # + added to ensure it makes no difference576 u" + testfiles/select2/3/3sub3\n" # + added to ensure it makes no difference
575 '- testfiles/select2/3/3sub1\n'577 u"- testfiles/select2/3/3sub1\n"
576 '- testfiles/select2/2/2sub1/2sub1sub3\n'578 u"- testfiles/select2/2/2sub1/2sub1sub3\n"
577 ' - "testfiles/select2/2/2sub1/2sub1sub2"\n'579 u' - "testfiles/select2/2/2sub1/2sub1sub2"\n'
578 'testfiles/select2/2/2sub1 \n'580 u"testfiles/select2/2/2sub1 \n"
579 '\n'581 u"\n"
580 '- testfiles/select2/1/1sub3/1sub3sub2\n'582 u"- testfiles/select2/1/1sub3/1sub3sub2\n"
581 '- testfiles/select2/1/1sub3/1sub3sub1 \n'583 u"- testfiles/select2/1/1sub3/1sub3sub1 \n"
582 "- 'testfiles/select2/1/1sub2/1sub2sub3'\n"584 u"- 'testfiles/select2/1/1sub2/1sub2sub3'\n"
583 ' \n'585 u" \n"
584 ' + testfiles/select2/1/1sub2/1sub2sub1 \n' # + added to ensure it makes no difference586 u" + testfiles/select2/1/1sub2/1sub2sub1 \n" # + added to ensure it makes no difference
585 '- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n'587 u"- testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt\n"
586 ' - testfiles/select2/1/1sub1/1sub1sub2 \n'588 u" - testfiles/select2/1/1sub1/1sub1sub2 \n"
587 '# Testing full-line comment\n'589 u"# Testing full-line comment\n"
588 '- testfiles/select2/1/1sub2\n'590 u"- testfiles/select2/1/1sub2\n"
589 "'testfiles/select2/1.py'\n"591 u"'testfiles/select2/1.py'\n"
590 'testfiles/select2/3\n'592 u"testfiles/select2/3\n"
591 ' # Testing another full-line comment \n'593 u" # Testing another full-line comment \n"
592 'testfiles/select2/1\n'594 u"testfiles/select2/1\n"
593 '- testfiles/select2/**')595 u"- testfiles/select2/**")
594 self.backup("full", "testfiles/select2", options=["--include-globbing-filelist=testfiles/include.txt"])596 self.backup(u"full", u"testfiles/select2", options=[u"--include-globbing-filelist=testfiles/include.txt"])
595 self.restore()597 self.restore()
596 restore_dir = 'testfiles/restore_out'598 restore_dir = u"testfiles/restore_out"
597 restored = self.directory_tree_to_list_of_lists(restore_dir)599 restored = self.directory_tree_to_list_of_lists(restore_dir)
598 self.assertEqual(restored, self.expected_restored_tree)600 self.assertEqual(restored, self.expected_restored_tree)
599601
@@ -605,54 +607,54 @@
605 def write_filelist(self, filelist_name):607 def write_filelist(self, filelist_name):
606 """Used by the below tests to write the filelist"""608 """Used by the below tests to write the filelist"""
607 assert filelist_name is not None609 assert filelist_name is not None
608 with open(filelist_name, 'w') as f:610 with io.open(filelist_name, u"w") as f:
609 f.write("+ testfiles/select/1/2/1\n"611 f.write(u"+ testfiles/select/1/2/1\n"
610 "- testfiles/select/1/2\n"612 u"- testfiles/select/1/2\n"
611 "- testfiles/select/1/1\n"613 u"- testfiles/select/1/1\n"
612 "- testfiles/select/1/3")614 u"- testfiles/select/1/3")
613615
614 def restore_and_check(self):616 def restore_and_check(self):
615 """Restores the backup and compares to what was expected (based on the filelist in write_filelist)"""617 """Restores the backup and compares to what was expected (based on the filelist in write_filelist)"""
616 self.restore()618 self.restore()
617 restore_dir = 'testfiles/restore_out'619 restore_dir = u"testfiles/restore_out"
618 restored = self.directory_tree_to_list_of_lists(restore_dir)620 restored = self.directory_tree_to_list_of_lists(restore_dir)
619 self.assertEqual(restored, [['2'], ['1']])621 self.assertEqual(restored, [[u"2"], [u"1"]])
620622
621 def test_commandline_include_exclude(self):623 def test_commandline_include_exclude(self):
622 """test an excluded folder is included for included contents when using commandline includes and excludes"""624 """test an excluded folder is included for included contents when using commandline includes and excludes"""
623 self.backup("full", "testfiles/select/1",625 self.backup(u"full", u"testfiles/select/1",
624 options=["--include", "testfiles/select/1/2/1",626 options=[u"--include", u"testfiles/select/1/2/1",
625 "--exclude", "testfiles/select/1/2",627 u"--exclude", u"testfiles/select/1/2",
626 "--exclude", "testfiles/select/1/1",628 u"--exclude", u"testfiles/select/1/1",
627 "--exclude", "testfiles/select/1/3"])629 u"--exclude", u"testfiles/select/1/3"])
628 self.restore_and_check()630 self.restore_and_check()
629631
630 def test_include_globbing_filelist(self):632 def test_include_globbing_filelist(self):
631 """test an excluded folder is included for included contents with an include-globbing-filelist """633 """test an excluded folder is included for included contents with an include-globbing-filelist """
632 # Deprecated, but include for now to ensure it keeps working until it is deliberately removed.634 # Deprecated, but include for now to ensure it keeps working until it is deliberately removed.
633 self.write_filelist("testfiles/include.txt")635 self.write_filelist(u"testfiles/include.txt")
634 self.backup("full", "testfiles/select/1", options=["--include-globbing-filelist=testfiles/include.txt"])636 self.backup(u"full", u"testfiles/select/1", options=[u"--include-globbing-filelist=testfiles/include.txt"])
635 self.restore_and_check()637 self.restore_and_check()
636638
637 def test_exclude_globbing_filelist(self):639 def test_exclude_globbing_filelist(self):
638 """test an excluded folder is included for included contents with an exclude-globbing-filelist """640 """test an excluded folder is included for included contents with an exclude-globbing-filelist """
639 # Deprecated, but include for now to ensure it keeps working until it is deliberately removed.641 # Deprecated, but include for now to ensure it keeps working until it is deliberately removed.
640 self.write_filelist("testfiles/exclude.txt")642 self.write_filelist(u"testfiles/exclude.txt")
641 self.backup("full", "testfiles/select/1", options=["--exclude-globbing-filelist=testfiles/exclude.txt"])643 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-globbing-filelist=testfiles/exclude.txt"])
642 self.restore_and_check()644 self.restore_and_check()
643645
644 def test_include_filelist(self):646 def test_include_filelist(self):
645 """test an excluded folder is included for included contents with an include-filelist (non-globbing) """647 """test an excluded folder is included for included contents with an include-filelist (non-globbing) """
646 # Regression test for Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411)648 # Regression test for Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411)
647 self.write_filelist("testfiles/include.txt")649 self.write_filelist(u"testfiles/include.txt")
648 self.backup("full", "testfiles/select/1", options=["--include-filelist=testfiles/include.txt"])650 self.backup(u"full", u"testfiles/select/1", options=[u"--include-filelist=testfiles/include.txt"])
649 self.restore_and_check()651 self.restore_and_check()
650652
651 def test_exclude_filelist(self):653 def test_exclude_filelist(self):
652 """test an excluded folder is included for included contents with an exclude-filelist (non-globbing) """654 """test an excluded folder is included for included contents with an exclude-filelist (non-globbing) """
653 # Regression test for Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411)655 # Regression test for Bug #1408411 (https://bugs.launchpad.net/duplicity/+bug/1408411)
654 self.write_filelist("testfiles/exclude.txt")656 self.write_filelist(u"testfiles/exclude.txt")
655 self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/exclude.txt"])657 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/exclude.txt"])
656 self.restore_and_check()658 self.restore_and_check()
657659
658660
@@ -664,112 +666,112 @@
664 def restore_and_check(self):666 def restore_and_check(self):
665 """Restores the backup and compares to what is expected."""667 """Restores the backup and compares to what is expected."""
666 self.restore()668 self.restore()
667 restore_dir = 'testfiles/restore_out'669 restore_dir = u"testfiles/restore_out"
668 restored = self.directory_tree_to_list_of_lists(restore_dir)670 restored = self.directory_tree_to_list_of_lists(restore_dir)
669 self.assertEqual(restored, [['2'], ['1']])671 self.assertEqual(restored, [[u"2"], [u"1"]])
670672
671 def test_exclude_filelist_asterisks_none(self):673 def test_exclude_filelist_asterisks_none(self):
672 """Basic exclude filelist."""674 """Basic exclude filelist."""
673 with open("testfiles/filelist.txt", 'w') as f:675 with io.open(u"testfiles/filelist.txt", u"w") as f:
674 f.write("+ testfiles/select/1/2/1\n"676 f.write(u"+ testfiles/select/1/2/1\n"
675 "- testfiles/select/1/2\n"677 u"- testfiles/select/1/2\n"
676 "- testfiles/select/1/1\n"678 u"- testfiles/select/1/1\n"
677 "- testfiles/select/1/3")679 u"- testfiles/select/1/3")
678 self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])680 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
679 self.restore_and_check()681 self.restore_and_check()
680682
681 def test_exclude_filelist_asterisks_single(self):683 def test_exclude_filelist_asterisks_single(self):
682 """Exclude filelist with asterisks replacing folders."""684 """Exclude filelist with asterisks replacing folders."""
683 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)685 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
684 with open("testfiles/filelist.txt", 'w') as f:686 with io.open(u"testfiles/filelist.txt", u"w") as f:
685 f.write("+ */select/1/2/1\n"687 f.write(u"+ */select/1/2/1\n"
686 "- */select/1/2\n"688 u"- */select/1/2\n"
687 "- testfiles/*/1/1\n"689 u"- testfiles/*/1/1\n"
688 "- */*/1/3")690 u"- */*/1/3")
689 self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])691 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
690 self.restore_and_check()692 self.restore_and_check()
691693
692 def test_exclude_filelist_asterisks_double_asterisks(self):694 def test_exclude_filelist_asterisks_double_asterisks(self):
693 """Exclude filelist with double asterisks replacing folders."""695 """Exclude filelist with double asterisks replacing folders."""
694 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)696 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
695 with open("testfiles/filelist.txt", 'w') as f:697 with io.open(u"testfiles/filelist.txt", u"w") as f:
696 f.write("+ **/1/2/1\n"698 f.write(u"+ **/1/2/1\n"
697 "- **/1/2\n"699 u"- **/1/2\n"
698 "- **/select/1/1\n"700 u"- **/select/1/1\n"
699 "- testfiles/select/1/3")701 u"- testfiles/select/1/3")
700 self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])702 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
701 self.restore_and_check()703 self.restore_and_check()
702704
703 def test_commandline_asterisks_single_excludes_only(self):705 def test_commandline_asterisks_single_excludes_only(self):
704 """test_commandline_include_exclude with single asterisks on exclude lines."""706 """test_commandline_include_exclude with single asterisks on exclude lines."""
705 self.backup("full", "testfiles/select/1",707 self.backup(u"full", u"testfiles/select/1",
706 options=["--include", "testfiles/select/1/2/1",708 options=[u"--include", u"testfiles/select/1/2/1",
707 "--exclude", "testfiles/*/1/2",709 u"--exclude", u"testfiles/*/1/2",
708 "--exclude", "*/select/1/1",710 u"--exclude", u"*/select/1/1",
709 "--exclude", "*/select/1/3"])711 u"--exclude", u"*/select/1/3"])
710 self.restore_and_check()712 self.restore_and_check()
711713
712 def test_commandline_asterisks_single_both(self):714 def test_commandline_asterisks_single_both(self):
713 """test_commandline_include_exclude with single asterisks on both exclude and include lines."""715 """test_commandline_include_exclude with single asterisks on both exclude and include lines."""
714 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)716 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
715 self.backup("full", "testfiles/select/1",717 self.backup(u"full", u"testfiles/select/1",
716 options=["--include", "*/select/1/2/1",718 options=[u"--include", u"*/select/1/2/1",
717 "--exclude", "testfiles/*/1/2",719 u"--exclude", u"testfiles/*/1/2",
718 "--exclude", "*/select/1/1",720 u"--exclude", u"*/select/1/1",
719 "--exclude", "*/select/1/3"])721 u"--exclude", u"*/select/1/3"])
720 self.restore_and_check()722 self.restore_and_check()
721723
722 def test_commandline_asterisks_double_exclude_only(self):724 def test_commandline_asterisks_double_exclude_only(self):
723 """test_commandline_include_exclude with double asterisks on exclude lines."""725 """test_commandline_include_exclude with double asterisks on exclude lines."""
724 self.backup("full", "testfiles/select/1",726 self.backup(u"full", u"testfiles/select/1",
725 options=["--include", "testfiles/select/1/2/1",727 options=[u"--include", u"testfiles/select/1/2/1",
726 "--exclude", "**/1/2",728 u"--exclude", u"**/1/2",
727 "--exclude", "**/1/1",729 u"--exclude", u"**/1/1",
728 "--exclude", "**/1/3"])730 u"--exclude", u"**/1/3"])
729 self.restore_and_check()731 self.restore_and_check()
730732
731 def test_commandline_asterisks_double_both(self):733 def test_commandline_asterisks_double_both(self):
732 """test_commandline_include_exclude with double asterisks on both exclude and include lines."""734 """test_commandline_include_exclude with double asterisks on both exclude and include lines."""
733 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)735 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
734 self.backup("full", "testfiles/select/1",736 self.backup(u"full", u"testfiles/select/1",
735 options=["--include", "**/1/2/1",737 options=[u"--include", u"**/1/2/1",
736 "--exclude", "**/1/2",738 u"--exclude", u"**/1/2",
737 "--exclude", "**/1/1",739 u"--exclude", u"**/1/1",
738 "--exclude", "**/1/3"])740 u"--exclude", u"**/1/3"])
739 self.restore_and_check()741 self.restore_and_check()
740742
741 def test_single_and_double_asterisks(self):743 def test_single_and_double_asterisks(self):
742 """This compares a backup using --include-globbing-filelist with a single and double *."""744 """This compares a backup using --include-globbing-filelist with a single and double *."""
743 with open("testfiles/filelist.txt", 'w') as f:745 with io.open(u"testfiles/filelist.txt", u"w") as f:
744 f.write("+ testfiles/select2/*\n"746 f.write(u"+ testfiles/select2/*\n"
745 "- testfiles/select")747 u"- testfiles/select")
746 self.backup("full", "testfiles/", options=["--include-globbing-filelist=testfiles/filelist.txt"])748 self.backup(u"full", u"testfiles/", options=[u"--include-globbing-filelist=testfiles/filelist.txt"])
747 self.restore()749 self.restore()
748 restore_dir = 'testfiles/restore_out'750 restore_dir = u"testfiles/restore_out"
749 restored = self.directory_tree_to_list_of_lists(restore_dir + "/select2")751 restored = self.directory_tree_to_list_of_lists(restore_dir + u"/select2")
750 with open("testfiles/filelist2.txt", 'w') as f:752 with io.open(u"testfiles/filelist2.txt", u"w") as f:
751 f.write("+ testfiles/select2/**\n"753 f.write(u"+ testfiles/select2/**\n"
752 "- testfiles/select")754 u"- testfiles/select")
753 self.backup("full", "testfiles/", options=["--include-globbing-filelist=testfiles/filelist2.txt"])755 self.backup(u"full", u"testfiles/", options=[u"--include-globbing-filelist=testfiles/filelist2.txt"])
754 self.restore()756 self.restore()
755 restore_dir = 'testfiles/restore_out'757 restore_dir = u"testfiles/restore_out"
756 restored2 = self.directory_tree_to_list_of_lists(restore_dir + "/select2")758 restored2 = self.directory_tree_to_list_of_lists(restore_dir + u"/select2")
757 self.assertEqual(restored, restored2)759 self.assertEqual(restored, restored2)
758760
759 def test_single_and_double_asterisks_includes_excludes(self):761 def test_single_and_double_asterisks_includes_excludes(self):
760 """This compares a backup using --includes/--excludes with a single and double *."""762 """This compares a backup using --includes/--excludes with a single and double *."""
761 self.backup("full", "testfiles/",763 self.backup(u"full", u"testfiles/",
762 options=["--include", "testfiles/select2/*",764 options=[u"--include", u"testfiles/select2/*",
763 "--exclude", "testfiles/select"])765 u"--exclude", u"testfiles/select"])
764 self.restore()766 self.restore()
765 restore_dir = 'testfiles/restore_out'767 restore_dir = u"testfiles/restore_out"
766 restored = self.directory_tree_to_list_of_lists(restore_dir + "/select2")768 restored = self.directory_tree_to_list_of_lists(restore_dir + u"/select2")
767 self.backup("full", "testfiles/",769 self.backup(u"full", u"testfiles/",
768 options=["--include", "testfiles/select2/**",770 options=[u"--include", u"testfiles/select2/**",
769 "--exclude", "testfiles/select"])771 u"--exclude", u"testfiles/select"])
770 self.restore()772 self.restore()
771 restore_dir = 'testfiles/restore_out'773 restore_dir = u"testfiles/restore_out"
772 restored2 = self.directory_tree_to_list_of_lists(restore_dir + "/select2")774 restored2 = self.directory_tree_to_list_of_lists(restore_dir + u"/select2")
773 self.assertEqual(restored, restored2)775 self.assertEqual(restored, restored2)
774776
775777
@@ -780,62 +782,62 @@
780 def restore_and_check(self):782 def restore_and_check(self):
781 """Restores the backup and compares to what is expected."""783 """Restores the backup and compares to what is expected."""
782 self.restore()784 self.restore()
783 restore_dir = 'testfiles/restore_out'785 restore_dir = u"testfiles/restore_out"
784 restored = self.directory_tree_to_list_of_lists(restore_dir)786 restored = self.directory_tree_to_list_of_lists(restore_dir)
785 self.assertEqual(restored, [['2'], ['1']])787 self.assertEqual(restored, [[u"2"], [u"1"]])
786788
787 def test_exclude_filelist_trailing_slashes(self):789 def test_exclude_filelist_trailing_slashes(self):
788 """test_exclude_filelist_asterisks_none with trailing slashes."""790 """test_exclude_filelist_asterisks_none with trailing slashes."""
789 with open("testfiles/filelist.txt", 'w') as f:791 with io.open(u"testfiles/filelist.txt", u"w") as f:
790 f.write("+ testfiles/select/1/2/1/\n"792 f.write(u"+ testfiles/select/1/2/1/\n"
791 "- testfiles/select/1/2/\n"793 u"- testfiles/select/1/2/\n"
792 "- testfiles/select/1/1/\n"794 u"- testfiles/select/1/1/\n"
793 "- testfiles/select/1/3/")795 u"- testfiles/select/1/3/")
794 self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])796 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
795 self.restore_and_check()797 self.restore_and_check()
796798
797 def test_exclude_filelist_trailing_slashes_single_wildcards_excludes(self):799 def test_exclude_filelist_trailing_slashes_single_wildcards_excludes(self):
798 """test_exclude_filelist_trailing_slashes with single wildcards in excludes."""800 """test_exclude_filelist_trailing_slashes with single wildcards in excludes."""
799 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)801 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
800 with open("testfiles/filelist.txt", 'w') as f:802 with io.open(u"testfiles/filelist.txt", u"w") as f:
801 f.write("+ testfiles/select/1/2/1/\n"803 f.write(u"+ testfiles/select/1/2/1/\n"
802 "- */select/1/2/\n"804 u"- */select/1/2/\n"
803 "- testfiles/*/1/1/\n"805 u"- testfiles/*/1/1/\n"
804 "- */*/1/3/")806 u"- */*/1/3/")
805 self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])807 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
806 self.restore_and_check()808 self.restore_and_check()
807809
808 def test_exclude_filelist_trailing_slashes_double_wildcards_excludes(self):810 def test_exclude_filelist_trailing_slashes_double_wildcards_excludes(self):
809 """test_exclude_filelist_trailing_slashes with double wildcards in excludes."""811 """test_exclude_filelist_trailing_slashes with double wildcards in excludes."""
810 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)812 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
811 with open("testfiles/filelist.txt", 'w') as f:813 with io.open(u"testfiles/filelist.txt", u"w") as f:
812 f.write("+ testfiles/select/1/2/1/\n"814 f.write(u"+ testfiles/select/1/2/1/\n"
813 "- **/1/2/\n"815 u"- **/1/2/\n"
814 "- **/1/1/\n"816 u"- **/1/1/\n"
815 "- **/1/3/")817 u"- **/1/3/")
816 self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])818 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
817 self.restore_and_check()819 self.restore_and_check()
818820
819 def test_exclude_filelist_trailing_slashes_double_wildcards_excludes_2(self):821 def test_exclude_filelist_trailing_slashes_double_wildcards_excludes_2(self):
820 """second test_exclude_filelist_trailing_slashes with double wildcards in excludes."""822 """second test_exclude_filelist_trailing_slashes with double wildcards in excludes."""
821 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482) and823 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482) and
822 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)824 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
823 with open("testfiles/filelist.txt", 'w') as f:825 with io.open(u"testfiles/filelist.txt", u"w") as f:
824 f.write("+ **/1/2/1/\n"826 f.write(u"+ **/1/2/1/\n"
825 "- **/1/2/\n"827 u"- **/1/2/\n"
826 "- **/1/1/\n"828 u"- **/1/1/\n"
827 "- **/1/3/")829 u"- **/1/3/")
828 self.backup("full", "testfiles/select/1", options=["--exclude-filelist=testfiles/filelist.txt"])830 self.backup(u"full", u"testfiles/select/1", options=[u"--exclude-filelist=testfiles/filelist.txt"])
829 self.restore_and_check()831 self.restore_and_check()
830832
831 def test_exclude_filelist_trailing_slashes_wildcards(self):833 def test_exclude_filelist_trailing_slashes_wildcards(self):
832 """test_commandline_asterisks_single_excludes_only with trailing slashes."""834 """test_commandline_asterisks_single_excludes_only with trailing slashes."""
833 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)835 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
834 self.backup("full", "testfiles/select/1",836 self.backup(u"full", u"testfiles/select/1",
835 options=["--include", "testfiles/select/1/2/1/",837 options=[u"--include", u"testfiles/select/1/2/1/",
836 "--exclude", "testfiles/*/1/2/",838 u"--exclude", u"testfiles/*/1/2/",
837 "--exclude", "*/select/1/1/",839 u"--exclude", u"*/select/1/1/",
838 "--exclude", "*/select/1/3/"])840 u"--exclude", u"*/select/1/3/"])
839 self.restore_and_check()841 self.restore_and_check()
840842
841843
@@ -845,49 +847,49 @@
845847
846 def test_no_trailing_slash(self):848 def test_no_trailing_slash(self):
847 """ Test that including 1.py works as expected"""849 """ Test that including 1.py works as expected"""
848 self.backup("full", "testfiles/select2",850 self.backup(u"full", u"testfiles/select2",
849 options=["--include", "testfiles/select2/1.py",851 options=[u"--include", u"testfiles/select2/1.py",
850 "--exclude", "**"])852 u"--exclude", u"**"])
851 self.restore()853 self.restore()
852 restore_dir = 'testfiles/restore_out'854 restore_dir = u"testfiles/restore_out"
853 restored = self.directory_tree_to_list_of_lists(restore_dir)855 restored = self.directory_tree_to_list_of_lists(restore_dir)
854 self.assertEqual(restored, [['1.py']])856 self.assertEqual(restored, [[u"1.py"]])
855857
856 def test_trailing_slash(self):858 def test_trailing_slash(self):
857 """ Test that globs with a trailing slash only match directories"""859 """ Test that globs with a trailing slash only match directories"""
858 # Regression test for Bug #1479545860 # Regression test for Bug #1479545
859 # (https://bugs.launchpad.net/duplicity/+bug/1479545)861 # (https://bugs.launchpad.net/duplicity/+bug/1479545)
860 self.backup("full", "testfiles/select2",862 self.backup(u"full", u"testfiles/select2",
861 options=["--include", "testfiles/select2/1.py/",863 options=[u"--include", u"testfiles/select2/1.py/",
862 "--exclude", "**"])864 u"--exclude", u"**"])
863 self.restore()865 self.restore()
864 restore_dir = 'testfiles/restore_out'866 restore_dir = u"testfiles/restore_out"
865 restored = self.directory_tree_to_list_of_lists(restore_dir)867 restored = self.directory_tree_to_list_of_lists(restore_dir)
866 self.assertEqual(restored, [])868 self.assertEqual(restored, [])
867869
868 def test_include_files_not_subdirectories(self):870 def test_include_files_not_subdirectories(self):
869 """ Test that a trailing slash glob followed by a * glob only matches871 """ Test that a trailing slash glob followed by a * glob only matches
870 files and not subdirectories"""872 files and not subdirectories"""
871 self.backup("full", "testfiles/select2",873 self.backup(u"full", u"testfiles/select2",
872 options=["--exclude", "testfiles/select2/*/",874 options=[u"--exclude", u"testfiles/select2/*/",
873 "--include", "testfiles/select2/*",875 u"--include", u"testfiles/select2/*",
874 "--exclude", "**"])876 u"--exclude", u"**"])
875 self.restore()877 self.restore()
876 restore_dir = 'testfiles/restore_out'878 restore_dir = u"testfiles/restore_out"
877 restored = self.directory_tree_to_list_of_lists(restore_dir)879 restored = self.directory_tree_to_list_of_lists(restore_dir)
878 self.assertEqual(restored, [['1.doc', '1.py']])880 self.assertEqual(restored, [[u"1.doc", u"1.py"]])
879881
880 def test_include_subdirectories_not_files(self):882 def test_include_subdirectories_not_files(self):
881 """ Test that a trailing slash glob only matches directories"""883 """ Test that a trailing slash glob only matches directories"""
882 self.backup("full", "testfiles/select2",884 self.backup(u"full", u"testfiles/select2",
883 options=["--include", "testfiles/select2/1/1sub1/**/",885 options=[u"--include", u"testfiles/select2/1/1sub1/**/",
884 "--exclude", "testfiles/select2/1/1sub1/**",886 u"--exclude", u"testfiles/select2/1/1sub1/**",
885 "--exclude", "**"])887 u"--exclude", u"**"])
886 self.restore()888 self.restore()
887 restore_dir = 'testfiles/restore_out'889 restore_dir = u"testfiles/restore_out"
888 restored = self.directory_tree_to_list_of_lists(restore_dir)890 restored = self.directory_tree_to_list_of_lists(restore_dir)
889 self.assertEqual(restored, [['1'], ['1sub1'],891 self.assertEqual(restored, [[u"1"], [u"1sub1"],
890 ['1sub1sub1', '1sub1sub2', '1sub1sub3']])892 [u"1sub1sub1", u"1sub1sub2", u"1sub1sub3"]])
891893
892894
893class TestGlobbingReplacement(IncludeExcludeFunctionalTest):895class TestGlobbingReplacement(IncludeExcludeFunctionalTest):
@@ -905,25 +907,25 @@
905 # Identical to test_include_exclude_basic with globbing characters added to both include and exclude lines907 # Identical to test_include_exclude_basic with globbing characters added to both include and exclude lines
906 # Exhibits the issue reported in Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371).908 # Exhibits the issue reported in Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371).
907 # See above and the unit tests for more granularity on the issue.909 # See above and the unit tests for more granularity on the issue.
908 self.backup("full", "testfiles/select2",910 self.backup(u"full", u"testfiles/select2",
909 options=["--include", "testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt", # Note ** and ? added911 options=[u"--include", u"testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt", # Note ** and ? added
910 "--exclude", "testfiles/select2/*/3s*1", # Note * added in both directory and filename912 u"--exclude", u"testfiles/select2/*/3s*1", # Note * added in both directory and filename
911 "--exclude", "testfiles/select2/**/2sub1sub3", # Note ** added913 u"--exclude", u"testfiles/select2/**/2sub1sub3", # Note ** added
912 "--exclude", "ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2", # Note ignorecase added914 u"--exclude", u"ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2", # Note ignorecase added
913 "--include", "ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1", # Note ignorecase, [] and915 u"--include", u"ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1", # Note ignorecase, [] and
914 # ? added916 # ? added
915 "--exclude", "testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2", # Note [] added917 u"--exclude", u"testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2", # Note [] added
916 "--exclude", "testfiles/select2/1/1sub[1-4]/1sub3sub1", # Note [range] added918 u"--exclude", u"testfiles/select2/1/1sub[1-4]/1sub3sub1", # Note [range] added
917 "--include", "testfiles/select2/*/1sub2/1s[w,u,p,q]b2sub1", # Note * and [] added919 u"--include", u"testfiles/select2/*/1sub2/1s[w,u,p,q]b2sub1", # Note * and [] added
918 "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt", # Note ? added920 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt", # Note ? added
919 "--exclude", "testfiles/select2/1/1*1/1sub1sub2", # Note * added921 u"--exclude", u"testfiles/select2/1/1*1/1sub1sub2", # Note * added
920 "--exclude", "testfiles/select2/1/1sub2",922 u"--exclude", u"testfiles/select2/1/1sub2",
921 "--include", "testfiles/select[2-4]/*.py", # Note * and [range] added923 u"--include", u"testfiles/select[2-4]/*.py", # Note * and [range] added
922 "--include", "testfiles/*2/3", # Note * added924 u"--include", u"testfiles/*2/3", # Note * added
923 "--include", "**/select2/1", # Note ** added925 u"--include", u"**/select2/1", # Note ** added
924 "--exclude", "testfiles/select2/**"])926 u"--exclude", u"testfiles/select2/**"])
925 self.restore()927 self.restore()
926 restore_dir = 'testfiles/restore_out'928 restore_dir = u"testfiles/restore_out"
927 restored = self.directory_tree_to_list_of_lists(restore_dir)929 restored = self.directory_tree_to_list_of_lists(restore_dir)
928 self.assertEqual(restored, self.expected_restored_tree)930 self.assertEqual(restored, self.expected_restored_tree)
929931
@@ -933,40 +935,40 @@
933935
934 def test_exclude_if_present_baseline(self):936 def test_exclude_if_present_baseline(self):
935 """ Test that duplicity normally backs up files"""937 """ Test that duplicity normally backs up files"""
936 with open("testfiles/select2/1/1sub1/1sub1sub1/.nobackup", "w") as tag:938 with io.open(u"testfiles/select2/1/1sub1/1sub1sub1/.nobackup", u"w") as tag:
937 tag.write("Files in this folder should not be backed up.")939 tag.write(u"Files in this folder should not be backed up.")
938 self.backup("full", "testfiles/select2/1/1sub1",940 self.backup(u"full", u"testfiles/select2/1/1sub1",
939 options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/*",941 options=[u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
940 "--exclude", "**"])942 u"--exclude", u"**"])
941 self.restore()943 self.restore()
942 restore_dir = 'testfiles/restore_out'944 restore_dir = u"testfiles/restore_out"
943 restored = self.directory_tree_to_list_of_lists(restore_dir)945 restored = self.directory_tree_to_list_of_lists(restore_dir)
944 self.assertEqual(restored, [['1sub1sub1'],946 self.assertEqual(restored, [[u"1sub1sub1"],
945 ['.nobackup', '1sub1sub1_file.txt']])947 [u".nobackup", u"1sub1sub1_file.txt"]])
946948
947 def test_exclude_if_present_excludes(self):949 def test_exclude_if_present_excludes(self):
948 """ Test that duplicity excludes files with relevant tag"""950 """ Test that duplicity excludes files with relevant tag"""
949 with open("testfiles/select2/1/1sub1/1sub1sub1/.nobackup", "w") as tag:951 with io.open(u"testfiles/select2/1/1sub1/1sub1sub1/.nobackup", u"w") as tag:
950 tag.write("Files in this folder should not be backed up.")952 tag.write(u"Files in this folder should not be backed up.")
951 self.backup("full", "testfiles/select2/1/1sub1",953 self.backup(u"full", u"testfiles/select2/1/1sub1",
952 options=["--exclude-if-present", ".nobackup",954 options=[u"--exclude-if-present", u".nobackup",
953 "--include", "testfiles/select2/1/1sub1/1sub1sub1/*",955 u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
954 "--exclude", "**"])956 u"--exclude", u"**"])
955 self.restore()957 self.restore()
956 restore_dir = 'testfiles/restore_out'958 restore_dir = u"testfiles/restore_out"
957 restored = self.directory_tree_to_list_of_lists(restore_dir)959 restored = self.directory_tree_to_list_of_lists(restore_dir)
958 self.assertEqual(restored, [])960 self.assertEqual(restored, [])
959961
960 def test_exclude_if_present_excludes_2(self):962 def test_exclude_if_present_excludes_2(self):
961 """ Test that duplicity excludes files with relevant tag"""963 """ Test that duplicity excludes files with relevant tag"""
962 with open("testfiles/select2/1/1sub1/1sub1sub1/EXCLUDE.tag", "w") as tag:964 with io.open(u"testfiles/select2/1/1sub1/1sub1sub1/EXCLUDE.tag", u"w") as tag:
963 tag.write("Files in this folder should also not be backed up.")965 tag.write(u"Files in this folder should also not be backed up.")
964 self.backup("full", "testfiles/select2/1/1sub1",966 self.backup(u"full", u"testfiles/select2/1/1sub1",
965 options=["--exclude-if-present", "EXCLUDE.tag",967 options=[u"--exclude-if-present", u"EXCLUDE.tag",
966 "--include", "testfiles/select2/1/1sub1/1sub1sub1/*",968 u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
967 "--exclude", "**"])969 u"--exclude", u"**"])
968 self.restore()970 self.restore()
969 restore_dir = 'testfiles/restore_out'971 restore_dir = u"testfiles/restore_out"
970 restored = self.directory_tree_to_list_of_lists(restore_dir)972 restored = self.directory_tree_to_list_of_lists(restore_dir)
971 self.assertEqual(restored, [])973 self.assertEqual(restored, [])
972974
@@ -974,42 +976,42 @@
974class TestLockedFoldersNoError(IncludeExcludeFunctionalTest):976class TestLockedFoldersNoError(IncludeExcludeFunctionalTest):
975 """ This tests that inaccessible folders do not cause an error"""977 """ This tests that inaccessible folders do not cause an error"""
976978
977 @unittest.skipUnless(platform.platform().startswith('Linux'),979 @unittest.skipUnless(platform.platform().startswith("Linux"),
978 'Skip on non-Linux systems')980 u"Skip on non-Linux systems")
979 def test_locked_baseline(self):981 def test_locked_baseline(self):
980 """ Test no error if locked in path but excluded"""982 """ Test no error if locked in path but excluded"""
981 folder_to_lock = "testfiles/select2/1/1sub1/1sub1sub3"983 folder_to_lock = u"testfiles/select2/1/1sub1/1sub1sub3"
982 initial_mode = os.stat(folder_to_lock).st_mode984 initial_mode = os.stat(folder_to_lock).st_mode
983 os.chmod(folder_to_lock, 0o0000)985 os.chmod(folder_to_lock, 0o0000)
984 self.backup("full", "testfiles/select2/1/1sub1",986 self.backup(u"full", u"testfiles/select2/1/1sub1",
985 options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/*",987 options=[u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
986 "--exclude", "**"])988 u"--exclude", u"**"])
987 os.chmod(folder_to_lock, initial_mode)989 os.chmod(folder_to_lock, initial_mode)
988 self.restore()990 self.restore()
989 restore_dir = 'testfiles/restore_out'991 restore_dir = u"testfiles/restore_out"
990 restored = self.directory_tree_to_list_of_lists(restore_dir)992 restored = self.directory_tree_to_list_of_lists(restore_dir)
991 self.assertEqual(restored, [['1sub1sub1'],993 self.assertEqual(restored, [[u"1sub1sub1"],
992 ['1sub1sub1_file.txt']])994 [u"1sub1sub1_file.txt"]])
993995
994 @unittest.skipUnless(platform.platform().startswith('Linux'),996 @unittest.skipUnless(platform.platform().startswith("Linux"),
995 'Skip on non-Linux systems')997 u"Skip on non-Linux systems")
996 def test_locked_excl_if_present(self):998 def test_locked_excl_if_present(self):
997 """ Test no error if excluded locked with --exclude-if-present"""999 """ Test no error if excluded locked with --exclude-if-present"""
998 # Regression test for Bug #16200851000 # Regression test for Bug #1620085
999 # https://bugs.launchpad.net/duplicity/+bug/16200851001 # https://bugs.launchpad.net/duplicity/+bug/1620085
1000 folder_to_lock = "testfiles/select2/1/1sub1/1sub1sub3"1002 folder_to_lock = u"testfiles/select2/1/1sub1/1sub1sub3"
1001 initial_mode = os.stat(folder_to_lock).st_mode1003 initial_mode = os.stat(folder_to_lock).st_mode
1002 os.chmod(folder_to_lock, 0o0000)1004 os.chmod(folder_to_lock, 0o0000)
1003 self.backup("full", "testfiles/select2/1/1sub1",1005 self.backup(u"full", u"testfiles/select2/1/1sub1",
1004 options=["--exclude-if-present", "EXCLUDE.tag",1006 options=[u"--exclude-if-present", u"EXCLUDE.tag",
1005 "--include", "testfiles/select2/1/1sub1/1sub1sub1/*",1007 u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/*",
1006 "--exclude", "**"])1008 u"--exclude", u"**"])
1007 os.chmod(folder_to_lock, initial_mode)1009 os.chmod(folder_to_lock, initial_mode)
1008 self.restore()1010 self.restore()
1009 restore_dir = 'testfiles/restore_out'1011 restore_dir = u"testfiles/restore_out"
1010 restored = self.directory_tree_to_list_of_lists(restore_dir)1012 restored = self.directory_tree_to_list_of_lists(restore_dir)
1011 self.assertEqual(restored, [['1sub1sub1'],1013 self.assertEqual(restored, [[u"1sub1sub1"],
1012 ['1sub1sub1_file.txt']])1014 [u"1sub1sub1_file.txt"]])
10131015
10141016
1015class TestFolderIncludesFiles(IncludeExcludeFunctionalTest):1017class TestFolderIncludesFiles(IncludeExcludeFunctionalTest):
@@ -1018,73 +1020,73 @@
10181020
1019 def test_includes_files(self):1021 def test_includes_files(self):
1020 """This tests that including a folder includes the files within it"""1022 """This tests that including a folder includes the files within it"""
1021 self.backup("full", "testfiles/select2/1/1sub1",1023 self.backup(u"full", u"testfiles/select2/1/1sub1",
1022 options=["--include", "testfiles/select2/1/1sub1/1sub1sub1",1024 options=[u"--include", u"testfiles/select2/1/1sub1/1sub1sub1",
1023 "--exclude", "**"])1025 u"--exclude", u"**"])
1024 self.restore()1026 self.restore()
1025 restore_dir = 'testfiles/restore_out'1027 restore_dir = u"testfiles/restore_out"
1026 restored = self.directory_tree_to_list_of_lists(restore_dir)1028 restored = self.directory_tree_to_list_of_lists(restore_dir)
1027 self.assertEqual(restored, [['1sub1sub1'],1029 self.assertEqual(restored, [[u"1sub1sub1"],
1028 ['1sub1sub1_file.txt']])1030 [u"1sub1sub1_file.txt"]])
10291031
1030 def test_includes_files_trailing_slash(self):1032 def test_includes_files_trailing_slash(self):
1031 """This tests that including a folder includes the files within it"""1033 """This tests that including a folder includes the files within it"""
1032 self.backup("full", "testfiles/select2/1/1sub1",1034 self.backup(u"full", u"testfiles/select2/1/1sub1",
1033 options=["--include", "testfiles/select2/1/1sub1/1sub1sub1/",1035 options=[u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/",
1034 "--exclude", "**"])1036 u"--exclude", u"**"])
1035 self.restore()1037 self.restore()
1036 restore_dir = 'testfiles/restore_out'1038 restore_dir = u"testfiles/restore_out"
1037 restored = self.directory_tree_to_list_of_lists(restore_dir)1039 restored = self.directory_tree_to_list_of_lists(restore_dir)
1038 self.assertEqual(restored, [['1sub1sub1'],1040 self.assertEqual(restored, [[u"1sub1sub1"],
1039 ['1sub1sub1_file.txt']])1041 [u"1sub1sub1_file.txt"]])
10401042
1041 def test_includes_files_trailing_slash_globbing_chars(self):1043 def test_includes_files_trailing_slash_globbing_chars(self):
1042 """Tests folder includes with globbing char and /"""1044 """Tests folder includes with globbing char and /"""
1043 self.backup("full", "testfiles/select2/1/1sub1",1045 self.backup(u"full", u"testfiles/select2/1/1sub1",
1044 options=["--include", "testfiles/s?lect2/1/1sub1/1sub1sub1/",1046 options=[u"--include", u"testfiles/s?lect2/1/1sub1/1sub1sub1/",
1045 "--exclude", "**"])1047 u"--exclude", u"**"])
1046 self.restore()1048 self.restore()
1047 restore_dir = 'testfiles/restore_out'1049 restore_dir = u"testfiles/restore_out"
1048 restored = self.directory_tree_to_list_of_lists(restore_dir)1050 restored = self.directory_tree_to_list_of_lists(restore_dir)
1049 self.assertEqual(restored, [['1sub1sub1'],1051 self.assertEqual(restored, [[u"1sub1sub1"],
1050 ['1sub1sub1_file.txt']])1052 [u"1sub1sub1_file.txt"]])
10511053
1052 def test_excludes_files_no_trailing_slash(self):1054 def test_excludes_files_no_trailing_slash(self):
1053 """This tests that excluding a folder excludes the files within it"""1055 """This tests that excluding a folder excludes the files within it"""
1054 self.backup("full", "testfiles/select2/1/1sub1",1056 self.backup(u"full", u"testfiles/select2/1/1sub1",
1055 options=["--exclude", "testfiles/select2/1/1sub1/1sub1sub1",1057 options=[u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub1",
1056 "--exclude", "testfiles/select2/1/1sub1/1sub1sub2",1058 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2",
1057 "--exclude", "testfiles/select2/1/1sub1/1sub1sub3",1059 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3",
1058 "--include", "testfiles/select2/1/1sub1/1sub1**",1060 u"--include", u"testfiles/select2/1/1sub1/1sub1**",
1059 "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"])1061 u"--exclude", u"testfiles/select2/1/1sub1/irrelevant.txt"])
1060 self.restore()1062 self.restore()
1061 restore_dir = 'testfiles/restore_out'1063 restore_dir = u"testfiles/restore_out"
1062 restored = self.directory_tree_to_list_of_lists(restore_dir)1064 restored = self.directory_tree_to_list_of_lists(restore_dir)
1063 self.assertEqual(restored, [])1065 self.assertEqual(restored, [])
10641066
1065 def test_excludes_files_trailing_slash(self):1067 def test_excludes_files_trailing_slash(self):
1066 """Excluding a folder excludes the files within it, if ends with /"""1068 """Excluding a folder excludes the files within it, if ends with /"""
1067 self.backup("full", "testfiles/select2/1/1sub1",1069 self.backup(u"full", u"testfiles/select2/1/1sub1",
1068 options=["--exclude", "testfiles/select2/1/1sub1/1sub1sub1/",1070 options=[u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub1/",
1069 "--exclude", "testfiles/select2/1/1sub1/1sub1sub2/",1071 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2/",
1070 "--exclude", "testfiles/select2/1/1sub1/1sub1sub3/",1072 u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/",
1071 "--include", "testfiles/select2/1/1sub1/1sub1**",1073 u"--include", u"testfiles/select2/1/1sub1/1sub1**",
1072 "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"])1074 u"--exclude", u"testfiles/select2/1/1sub1/irrelevant.txt"])
1073 self.restore()1075 self.restore()
1074 restore_dir = 'testfiles/restore_out'1076 restore_dir = u"testfiles/restore_out"
1075 restored = self.directory_tree_to_list_of_lists(restore_dir)1077 restored = self.directory_tree_to_list_of_lists(restore_dir)
1076 self.assertEqual(restored, [])1078 self.assertEqual(restored, [])
10771079
1078 def test_excludes_files_trailing_slash_globbing_chars(self):1080 def test_excludes_files_trailing_slash_globbing_chars(self):
1079 """Tests folder excludes with globbing char and /"""1081 """Tests folder excludes with globbing char and /"""
1080 self.backup("full", "testfiles/select2/1/1sub1",1082 self.backup(u"full", u"testfiles/select2/1/1sub1",
1081 options=["--exclude", "testfiles/sel?ct2/1/1sub1/1sub1sub1/",1083 options=[u"--exclude", u"testfiles/sel?ct2/1/1sub1/1sub1sub1/",
1082 "--exclude", "testfiles/sel[e,f]ct2/1/1sub1/1sub1sub2/",1084 u"--exclude", u"testfiles/sel[e,f]ct2/1/1sub1/1sub1sub2/",
1083 "--exclude", "testfiles/sel*t2/1/1sub1/1sub1sub3/",1085 u"--exclude", u"testfiles/sel*t2/1/1sub1/1sub1sub3/",
1084 "--include", "testfiles/select2/1/1sub1/1sub1**",1086 u"--include", u"testfiles/select2/1/1sub1/1sub1**",
1085 "--exclude", "testfiles/select2/1/1sub1/irrelevant.txt"])1087 u"--exclude", u"testfiles/select2/1/1sub1/irrelevant.txt"])
1086 self.restore()1088 self.restore()
1087 restore_dir = 'testfiles/restore_out'1089 restore_dir = u"testfiles/restore_out"
1088 restored = self.directory_tree_to_list_of_lists(restore_dir)1090 restored = self.directory_tree_to_list_of_lists(restore_dir)
1089 self.assertEqual(restored, [])1091 self.assertEqual(restored, [])
10901092
@@ -1094,30 +1096,110 @@
10941096
1095 def test_absolute_paths_non_globbing(self):1097 def test_absolute_paths_non_globbing(self):
1096 """ Test --include and --exclude work with absolute paths"""1098 """ Test --include and --exclude work with absolute paths"""
1097 self.backup("full", os.path.abspath("testfiles/select2"),1099 self.backup(u"full", os.path.abspath(u"testfiles/select2"),
1098 options=["--include", os.path.abspath("testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"),1100 options=[u"--include", os.path.abspath(u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"),
1099 "--exclude", os.path.abspath("testfiles/select2/3/3sub3/3sub3sub2"),1101 u"--exclude", os.path.abspath(u"testfiles/select2/3/3sub3/3sub3sub2"),
1100 "--include", os.path.abspath("testfiles/select2/3/3sub2/3sub2sub2"),1102 u"--include", os.path.abspath(u"testfiles/select2/3/3sub2/3sub2sub2"),
1101 "--include", os.path.abspath("testfiles/select2/3/3sub3"),1103 u"--include", os.path.abspath(u"testfiles/select2/3/3sub3"),
1102 "--exclude", os.path.abspath("testfiles/select2/3/3sub1"),1104 u"--exclude", os.path.abspath(u"testfiles/select2/3/3sub1"),
1103 "--exclude", os.path.abspath("testfiles/select2/2/2sub1/2sub1sub3"),1105 u"--exclude", os.path.abspath(u"testfiles/select2/2/2sub1/2sub1sub3"),
1104 "--exclude", os.path.abspath("testfiles/select2/2/2sub1/2sub1sub2"),1106 u"--exclude", os.path.abspath(u"testfiles/select2/2/2sub1/2sub1sub2"),
1105 "--include", os.path.abspath("testfiles/select2/2/2sub1"),1107 u"--include", os.path.abspath(u"testfiles/select2/2/2sub1"),
1106 "--exclude", os.path.abspath("testfiles/select2/1/1sub3/1sub3sub2"),1108 u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub3/1sub3sub2"),
1107 "--exclude", os.path.abspath("testfiles/select2/1/1sub3/1sub3sub1"),1109 u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub3/1sub3sub1"),
1108 "--exclude", os.path.abspath("testfiles/select2/1/1sub2/1sub2sub3"),1110 u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub2/1sub2sub3"),
1109 "--include", os.path.abspath("testfiles/select2/1/1sub2/1sub2sub1"),1111 u"--include", os.path.abspath(u"testfiles/select2/1/1sub2/1sub2sub1"),
1110 "--exclude", os.path.abspath("testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"),1112 u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"),
1111 "--exclude", os.path.abspath("testfiles/select2/1/1sub1/1sub1sub2"),1113 u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub1/1sub1sub2"),
1112 "--exclude", os.path.abspath("testfiles/select2/1/1sub2"),1114 u"--exclude", os.path.abspath(u"testfiles/select2/1/1sub2"),
1113 "--include", os.path.abspath("testfiles/select2/1.py"),1115 u"--include", os.path.abspath(u"testfiles/select2/1.py"),
1114 "--include", os.path.abspath("testfiles/select2/3"),1116 u"--include", os.path.abspath(u"testfiles/select2/3"),
1115 "--include", os.path.abspath("testfiles/select2/1"),1117 u"--include", os.path.abspath(u"testfiles/select2/1"),
1116 "--exclude", os.path.abspath("testfiles/select2/**")])1118 u"--exclude", os.path.abspath(u"testfiles/select2/**")])
1117 self.restore()1119 self.restore()
1118 restore_dir = 'testfiles/restore_out'1120 restore_dir = u"testfiles/restore_out"
1119 restored = self.directory_tree_to_list_of_lists(restore_dir)1121 restored = self.directory_tree_to_list_of_lists(restore_dir)
1120 self.assertEqual(restored, self.expected_restored_tree)1122 self.assertEqual(restored, self.expected_restored_tree)
11211123
1124
1125@unittest.skipUnless(sys.getfilesystemencoding() == "UTF-8",
1126 u"Skipping TestUnicode -- Only tested to work on UTF-8 systems")
1127class TestUnicode(IncludeExcludeFunctionalTest):
1128 """ Tests include/exclude options with unicode paths"""
1129
1130 def test_unicode_paths_non_globbing(self):
1131 """ Test --include and --exclude work with unicode paths"""
1132 self.backup(u"full", u"testfiles/select-unicode",
1133 options=[u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/Παράδειγμα/उदाहरण.txt",
1134 u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/Παράδειγμα/דוגמא.txt",
1135 u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/მაგალითი/",
1136 u"--include", u"testfiles/select-unicode/прыклад/пример/例/",
1137 u"--exclude", u"testfiles/select-unicode/прыклад/пример/",
1138 u"--include", u"testfiles/select-unicode/прыклад/",
1139 u"--include", u"testfiles/select-unicode/օրինակ.txt",
1140 u"--exclude", u"testfiles/select-unicode/**"])
1141 self.restore()
1142 restore_dir = u"testfiles/restore_out"
1143 restored = self.directory_tree_to_list_of_lists(restore_dir)
1144 self.assertEqual(restored, [[u"прыклад", u"օրինակ.txt"],
1145 [u"пример", u"উদাহরণ"], [u"例"], [u"Παράδειγμα"], [u"ઉદાહરણ.log"]])
1146
1147 def test_unicode_paths_asterisks(self):
1148 """ Test --include and --exclude work with unicode paths and globs containing * and **"""
1149 p = u"testfiles/select-unicode/"
1150 self.backup(u"full", u"testfiles/select-unicode",
1151 options=[u"--exclude", p + u"прыклад/пример/例/Παρά*ειγμα/उदाहरण.txt", # Note *
1152 u"--exclude", p + u"прыклад/пример/例/Παράδειγμα/דוגמא.txt",
1153 u"--exclude", p + u"прыклад/пример/例/მაგალითი/",
1154 u"--include", p + u"пр**/例/", # Note **
1155 u"--exclude", p + u"прыклад/пример/",
1156 u"--include", p + u"прыкла*/", # Note *
1157 u"--include", p + u"օր*ակ.txt", # Note *
1158 u"--exclude", p + u"**"])
1159 self.restore()
1160 restore_dir = u"testfiles/restore_out"
1161 restored = self.directory_tree_to_list_of_lists(restore_dir)
1162 self.assertEqual(restored, [[u"прыклад", u"օրինակ.txt"],
1163 [u"пример", u"উদাহরণ"], [u"例"], [u"Παράδειγμα"], [u"ઉદાહરણ.log"]])
1164
1165 def test_unicode_paths_square_brackets(self):
1166 """ Test --include and --exclude work with unicode paths with character options in []s and [!]s"""
1167 p = u"testfiles/select-unicode/"
1168 self.backup(u"full", u"testfiles/select-unicode",
1169 options=[u"--exclude", p + u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt",
1170 u"--exclude", p + u"пры[к,и,р]лад/пример/例/Παράδειγμα/דוגמא.txt",
1171 u"--exclude", p + u"прыклад/пр[!a,b,c]мер/例/მაგალითი/",
1172 u"--include", p + u"прыклад/при[g,м,д]ер/例/",
1173 u"--exclude", p + u"прыклад/пример/",
1174 u"--include", p + u"прыклад/",
1175 u"--include", p + u"օրինակ.txt",
1176 u"--exclude", p + u"**"])
1177 self.restore()
1178 restore_dir = u"testfiles/restore_out"
1179 restored = self.directory_tree_to_list_of_lists(restore_dir)
1180 self.assertEqual(restored, [[u"прыклад", u"օրինակ.txt"],
1181 [u"пример", u"উদাহরণ"], [u"例"], [u"Παράδειγμα"], [u"ઉદાહરણ.log"]])
1182
1183 def test_unicode_filelist(self):
1184 """Test that exclude filelist works with unicode filenames"""
1185 # As this is an exclude filelist any lines with no +/- modifier should be treated as if they have a -.
1186 path = u"testfiles/select-unicode/"
1187 # Create a filelist
1188 with io.open(u"testfiles/exclude.txt", u"w", encoding="UTF-8") as f:
1189 f.write(u"- " + path + u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt\n"
1190 u"- " + path + u"прыклад/пример/例/Παράδειγμα/דוגמא.txt\n"
1191 u"- " + path + u"прыклад/пример/例/მაგალითი/\n"
1192 u"+ " + path + u"прыклад/пример/例/\n"
1193 u"- " + path + u"прыклад/пример/\n"
1194 u"+ " + path + u"прыклад/\n"
1195 u"+ " + path + u"օրինակ.txt\n"
1196 u"- " + path + u"**")
1197 self.backup(u"full", path, options=[u"--exclude-filelist=testfiles/exclude.txt"])
1198 self.restore()
1199 restore_dir = u"testfiles/restore_out"
1200 restored = self.directory_tree_to_list_of_lists(restore_dir)
1201 self.assertEqual(restored, [[u"прыклад", u"օրինակ.txt"],
1202 [u"пример", u"উদাহরণ"], [u"例"], [u"Παράδειγμα"], [u"ઉદાહરણ.log"]])
1203
1122if __name__ == "__main__":1204if __name__ == "__main__":
1123 unittest.main()1205 unittest.main()
11241206
=== modified file 'testing/functional/test_verify.py'
--- testing/functional/test_verify.py 2015-01-01 13:07:31 +0000
+++ testing/functional/test_verify.py 2017-12-01 23:01:42 +0000
@@ -32,20 +32,20 @@
32 """32 """
33 def test_verify(self):33 def test_verify(self):
34 """Test that verify (without --compare-data) works in the basic case"""34 """Test that verify (without --compare-data) works in the basic case"""
35 self.backup("full", "testfiles/various_file_types", options=[])35 self.backup(u"full", u"testfiles/various_file_types", options=[])
36 self.verify('testfiles/various_file_types/executable', file_to_verify='executable', options=[])36 self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable', options=[])
3737
38 def test_verify_changed_source_file(self):38 def test_verify_changed_source_file(self):
39 """Test verify (without --compare-data) gives no error if a source file is changed"""39 """Test verify (without --compare-data) gives no error if a source file is changed"""
40 # This test was made to pass in fixing Bug #135488040 # This test was made to pass in fixing Bug #1354880
41 self.backup("full", "testfiles/various_file_types", options=[])41 self.backup(u"full", u"testfiles/various_file_types", options=[])
4242
43 # Edit source file43 # Edit source file
44 with open('testfiles/various_file_types/executable', 'r+') as f:44 with open('testfiles/various_file_types/executable', 'r+') as f:
45 f.write('This changes a source file.')45 f.write('This changes a source file.')
4646
47 # Test verify for the file47 # Test verify for the file
48 self.verify('testfiles/various_file_types/executable', file_to_verify='executable', options=[])48 self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable', options=[])
4949
50 def test_verify_changed_source_file_adjust_mtime(self):50 def test_verify_changed_source_file_adjust_mtime(self):
51 """Test verify (without --compare-data) gives no error if a source file is changed and the mtime is changed51 """Test verify (without --compare-data) gives no error if a source file is changed and the mtime is changed
@@ -58,7 +58,7 @@
58 # the times from a stat call don't match what a utime will set.58 # the times from a stat call don't match what a utime will set.
59 os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))59 os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))
6060
61 self.backup("full", "testfiles/various_file_types", options=[])61 self.backup(u"full", u"testfiles/various_file_types", options=[])
6262
63 # Edit source file63 # Edit source file
64 with open('testfiles/various_file_types/executable', 'r+') as f:64 with open('testfiles/various_file_types/executable', 'r+') as f:
@@ -68,19 +68,19 @@
68 os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))68 os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))
6969
70 # Test verify for the file70 # Test verify for the file
71 self.verify('testfiles/various_file_types/executable', file_to_verify='executable', options=[])71 self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable', options=[])
7272
73 def test_verify_compare_data(self):73 def test_verify_compare_data(self):
74 """Test that verify works in the basic case when the --compare-data option is used"""74 """Test that verify works in the basic case when the --compare-data option is used"""
75 self.backup("full", "testfiles/various_file_types", options=[])75 self.backup(u"full", u"testfiles/various_file_types", options=[])
7676
77 # Test verify for the file with --compare-data77 # Test verify for the file with --compare-data
78 self.verify('testfiles/various_file_types/executable', file_to_verify='executable',78 self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable',
79 options=["--compare-data"])79 options=[u"--compare-data"])
8080
81 def test_verify_compare_data_changed_source_file(self):81 def test_verify_compare_data_changed_source_file(self):
82 """Test verify with --compare-data gives an error if a source file is changed"""82 """Test verify with --compare-data gives an error if a source file is changed"""
83 self.backup("full", "testfiles/various_file_types", options=[])83 self.backup(u"full", u"testfiles/various_file_types", options=[])
8484
85 # Edit source file85 # Edit source file
86 with open('testfiles/various_file_types/executable', 'r+') as f:86 with open('testfiles/various_file_types/executable', 'r+') as f:
@@ -88,8 +88,8 @@
8888
89 # Test verify for edited file fails with --compare-data89 # Test verify for edited file fails with --compare-data
90 try:90 try:
91 self.verify('testfiles/various_file_types/executable', file_to_verify='executable',91 self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable',
92 options=["--compare-data"])92 options=[u"--compare-data"])
93 except CmdError as e:93 except CmdError as e:
94 self.assertEqual(e.exit_status, 1, str(e))94 self.assertEqual(e.exit_status, 1, str(e))
95 else:95 else:
@@ -105,7 +105,7 @@
105 # the times from a stat call don't match what a utime will set105 # the times from a stat call don't match what a utime will set
106 os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))106 os.utime('testfiles/various_file_types/executable', (file_info.st_atime, file_info.st_mtime))
107107
108 self.backup("full", "testfiles/various_file_types", options=[])108 self.backup(u"full", u"testfiles/various_file_types", options=[])
109 # Edit source file109 # Edit source file
110 with open('testfiles/various_file_types/executable', 'r+') as f:110 with open('testfiles/various_file_types/executable', 'r+') as f:
111 f.write('This changes a source file.')111 f.write('This changes a source file.')
@@ -115,8 +115,8 @@
115115
116 # Test verify for edited file fails with --compare-data116 # Test verify for edited file fails with --compare-data
117 try:117 try:
118 self.verify('testfiles/various_file_types/executable', file_to_verify='executable',118 self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable',
119 options=["--compare-data"])119 options=[u"--compare-data"])
120 except CmdError as e:120 except CmdError as e:
121 self.assertEqual(e.exit_status, 1, str(e))121 self.assertEqual(e.exit_status, 1, str(e))
122 else:122 else:
@@ -124,7 +124,7 @@
124124
125 def test_verify_corrupt_archive(self):125 def test_verify_corrupt_archive(self):
126 """Test verify (without --compare-data) gives an error if the archive is corrupted"""126 """Test verify (without --compare-data) gives an error if the archive is corrupted"""
127 self.backup("full", "testfiles/various_file_types", options=[])127 self.backup(u"full", u"testfiles/various_file_types", options=[])
128 output_files = os.listdir("testfiles/output")128 output_files = os.listdir("testfiles/output")
129 archives = [elem for elem in output_files if "vol" in elem]129 archives = [elem for elem in output_files if "vol" in elem]
130 for archive in archives:130 for archive in archives:
@@ -133,7 +133,7 @@
133 f.write('This writes text into each archive file to corrupt it.')133 f.write('This writes text into each archive file to corrupt it.')
134 # Test verify for the file134 # Test verify for the file
135 try:135 try:
136 self.verify('testfiles/various_file_types/executable', file_to_verify='executable', options=[])136 self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable', options=[])
137 except CmdError as e:137 except CmdError as e:
138 # Should return a 21 error code for "hash mismatch"138 # Should return a 21 error code for "hash mismatch"
139 self.assertEqual(e.exit_status, 21, str(e))139 self.assertEqual(e.exit_status, 21, str(e))
@@ -142,7 +142,7 @@
142142
143 def test_verify_corrupt_archive_compare_data(self):143 def test_verify_corrupt_archive_compare_data(self):
144 """Test verify with --compare-data gives an error if the archive is corrupted"""144 """Test verify with --compare-data gives an error if the archive is corrupted"""
145 self.backup("full", "testfiles/various_file_types", options=[])145 self.backup(u"full", u"testfiles/various_file_types", options=[])
146 output_files = os.listdir("testfiles/output")146 output_files = os.listdir("testfiles/output")
147 archives = [elem for elem in output_files if "vol" in elem]147 archives = [elem for elem in output_files if "vol" in elem]
148 for archive in archives:148 for archive in archives:
@@ -151,8 +151,8 @@
151 f.write('This writes text into each archive file to corrupt it.')151 f.write('This writes text into each archive file to corrupt it.')
152 # Test verify for the file152 # Test verify for the file
153 try:153 try:
154 self.verify('testfiles/various_file_types/executable', file_to_verify='executable',154 self.verify(u'testfiles/various_file_types/executable', file_to_verify=u'executable',
155 options=["--compare-data"])155 options=[u"--compare-data"])
156 except CmdError as e:156 except CmdError as e:
157 # Should return a 21 error code for "hash mismatch"157 # Should return a 21 error code for "hash mismatch"
158 self.assertEqual(e.exit_status, 21, str(e))158 self.assertEqual(e.exit_status, 21, str(e))
159159
=== added file 'testing/testfiles.tar.gz'
160Binary files testing/testfiles.tar.gz 1970-01-01 00:00:00 +0000 and testing/testfiles.tar.gz 2017-12-01 23:01:42 +0000 differ160Binary files testing/testfiles.tar.gz 1970-01-01 00:00:00 +0000 and testing/testfiles.tar.gz 2017-12-01 23:01:42 +0000 differ
=== removed file 'testing/testfiles.tar.gz'
161Binary files testing/testfiles.tar.gz 2017-11-14 16:53:17 +0000 and testing/testfiles.tar.gz 1970-01-01 00:00:00 +0000 differ161Binary files testing/testfiles.tar.gz 2017-11-14 16:53:17 +0000 and testing/testfiles.tar.gz 1970-01-01 00:00:00 +0000 differ
=== modified file 'testing/unit/test_diffdir.py'
--- testing/unit/test_diffdir.py 2017-01-18 22:59:29 +0000
+++ testing/unit/test_diffdir.py 2017-12-01 23:01:42 +0000
@@ -20,8 +20,6 @@
20# along with duplicity; if not, write to the Free Software Foundation,20# along with duplicity; if not, write to the Free Software Foundation,
21# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA21# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2222
23import os
24import sys
25import unittest23import unittest
2624
27from duplicity.path import * # @UnusedWildImport25from duplicity.path import * # @UnusedWildImport
2826
=== modified file 'testing/unit/test_globmatch.py'
--- testing/unit/test_globmatch.py 2017-07-11 14:55:38 +0000
+++ testing/unit/test_globmatch.py 2017-12-01 23:01:42 +0000
@@ -1,3 +1,4 @@
1# -*- coding: utf-8 -*-
1# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-2# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
2#3#
3# Copyright 2002 Ben Escoto <ben@emerose.org>4# Copyright 2002 Ben Escoto <ben@emerose.org>
@@ -20,6 +21,8 @@
20# along with duplicity; if not, write to the Free Software Foundation,21# along with duplicity; if not, write to the Free Software Foundation,
21# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA22# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2223
24import unittest
25
23from duplicity.globmatch import *26from duplicity.globmatch import *
24from duplicity.path import *27from duplicity.path import *
25from . import UnitTestCase28from . import UnitTestCase
@@ -75,14 +78,14 @@
7578
76 def test_glob_to_regex(self):79 def test_glob_to_regex(self):
77 """test_glob_re - test translation of shell pattern to regular exp"""80 """test_glob_re - test translation of shell pattern to regular exp"""
78 self.assertEqual(glob_to_regex("hello"), "hello")81 self.assertEqual(glob_to_regex(u"hello"), u"hello")
79 self.assertEqual(glob_to_regex(".e?ll**o"), "\\.e[^/]ll.*o")82 self.assertEqual(glob_to_regex(u".e?ll**o"), u"\\.e[^/]ll.*o")
80 self.assertEqual(glob_to_regex("[abc]el[^de][!fg]h"),83 self.assertEqual(glob_to_regex(u"[abc]el[^de][!fg]h"),
81 "[abc]el[^de][^fg]h")84 u"[abc]el[^de][^fg]h")
82 self.assertEqual(glob_to_regex("/usr/*/bin/"),85 self.assertEqual(glob_to_regex(u"/usr/*/bin/"),
83 "\\/usr\\/[^/]*\\/bin\\/")86 u"\\/usr\\/[^/]*\\/bin\\/")
84 self.assertEqual(glob_to_regex("[a.b/c]"), "[a.b/c]")87 self.assertEqual(glob_to_regex(u"[a.b/c]"), u"[a.b/c]")
85 self.assertEqual(glob_to_regex("[a*b-c]e[!]]"), "[a*b-c]e[^]]")88 self.assertEqual(glob_to_regex(u"[a*b-c]e[!]]"), u"[a*b-c]e[^]]")
8689
8790
88class TestSelectValuesFromGlobs(UnitTestCase):91class TestSelectValuesFromGlobs(UnitTestCase):
@@ -91,22 +94,22 @@
91 def test_glob_scans_parent_directories(self):94 def test_glob_scans_parent_directories(self):
92 """Test glob scans parent"""95 """Test glob scans parent"""
93 self.assertEqual(96 self.assertEqual(
94 inc_sel_dir("testfiles/parent/sub", "testfiles/parent"), 2)97 inc_sel_dir(u"testfiles/parent/sub", u"testfiles/parent"), 2)
95 self.assertEqual(98 self.assertEqual(
96 inc_sel_dir("testfiles/select2/3/3sub2", "testfiles/select2/3"), 2)99 inc_sel_dir(u"testfiles/select2/3/3sub2", u"testfiles/select2/3"), 2)
97100
98 def test_double_asterisk_include(self):101 def test_double_asterisk_include(self):
99 """Test a few globbing patterns, including **"""102 """Test a few globbing patterns, including **"""
100 self.assertEqual(inc_sel_file("**", "foo.txt"), 1)103 self.assertEqual(inc_sel_file(u"**", u"foo.txt"), 1)
101 self.assertEqual(inc_sel_dir("**", "folder"), 1)104 self.assertEqual(inc_sel_dir(u"**", u"folder"), 1)
102105
103 def test_double_asterisk_extension_include(self):106 def test_double_asterisk_extension_include(self):
104 """Test **.py"""107 """Test **.py"""
105 self.assertEqual(inc_sel_file("**.py", "what/ever.py"), 1)108 self.assertEqual(inc_sel_file(u"**.py", u"what/ever.py"), 1)
106 self.assertEqual(inc_sel_file("**.py", "what/ever.py/foo"), 1)109 self.assertEqual(inc_sel_file(u"**.py", u"what/ever.py/foo"), 1)
107 self.assertEqual(inc_sel_dir("**.py", "foo"), 2)110 self.assertEqual(inc_sel_dir(u"**.py", u"foo"), 2)
108 self.assertEqual(inc_sel_dir("**.py", "usr/local/bin"), 2)111 self.assertEqual(inc_sel_dir(u"**.py", u"usr/local/bin"), 2)
109 self.assertEqual(inc_sel_dir("**.py", "/usr/local/bin"), 2)112 self.assertEqual(inc_sel_dir(u"**.py", u"/usr/local/bin"), 2)
110113
111114
112class TestTrailingSlash(UnitTestCase):115class TestTrailingSlash(UnitTestCase):
@@ -115,95 +118,95 @@
115 def test_trailing_slash_matches_only_dirs(self):118 def test_trailing_slash_matches_only_dirs(self):
116 """Test matching where glob includes a trailing slash"""119 """Test matching where glob includes a trailing slash"""
117 # Test the folder named "folder" is included120 # Test the folder named "folder" is included
118 self.assertEqual(inc_sel_dir("fold*/", "folder"), 1)121 self.assertEqual(inc_sel_dir(u"fold*/", u"folder"), 1)
119122
120 # Test the file (not folder) named "folder" is not included123 # Test the file (not folder) named "folder" is not included
121 self.assertEqual(inc_sel_file("fold*/", "folder"), None)124 self.assertEqual(inc_sel_file(u"fold*/", u"folder"), None)
122 self.assertEqual(inc_sel_file("folder/", "folder"), None)125 self.assertEqual(inc_sel_file(u"folder/", u"folder"), None)
123126
124 # Test miscellaneous file/folder127 # Test miscellaneous file/folder
125 self.assertEqual(inc_sel_file("fo*/", "foo.txt"), None)128 self.assertEqual(inc_sel_file(u"fo*/", u"foo.txt"), None)
126129
127 def test_included_files_are_matched_no_slash(self):130 def test_included_files_are_matched_no_slash(self):
128 """Test that files within an included folder are matched"""131 """Test that files within an included folder are matched"""
129 self.assertEqual(inc_sel_file("fold*", "folder/file.txt"), 1)132 self.assertEqual(inc_sel_file(u"fold*", u"folder/file.txt"), 1)
130 self.assertEqual(inc_sel_file("fold*", "folder/file.txt"), 1)133 self.assertEqual(inc_sel_file(u"fold*", u"folder/file.txt"), 1)
131 self.assertEqual(inc_sel_file("fold*", "folder/2/file.txt"), 1)134 self.assertEqual(inc_sel_file(u"fold*", u"folder/2/file.txt"), 1)
132135
133 def test_included_files_are_matched_no_slash_2(self):136 def test_included_files_are_matched_no_slash_2(self):
134 """Test that files within an included folder are matched"""137 """Test that files within an included folder are matched"""
135 self.assertEqual(inc_sel_file("folder", "folder/file.txt"), 1)138 self.assertEqual(inc_sel_file(u"folder", u"folder/file.txt"), 1)
136 self.assertEqual(inc_sel_file("folder/2", "folder/2/file.txt"), 1)139 self.assertEqual(inc_sel_file(u"folder/2", u"folder/2/file.txt"), 1)
137140
138 def test_included_files_are_matched_slash(self):141 def test_included_files_are_matched_slash(self):
139 """Test that files within an included folder are matched with /"""142 """Test that files within an included folder are matched with /"""
140 # Bug #1624725143 # Bug #1624725
141 # https://bugs.launchpad.net/duplicity/+bug/1624725144 # https://bugs.launchpad.net/duplicity/+bug/1624725
142 self.assertEqual(inc_sel_file("folder/", "folder/file.txt"), 1)145 self.assertEqual(inc_sel_file(u"folder/", u"folder/file.txt"), 1)
143146
144 def test_included_files_are_matched_slash_2(self):147 def test_included_files_are_matched_slash_2(self):
145 """Test that files within an included folder are matched with /"""148 """Test that files within an included folder are matched with /"""
146 # Bug #1624725149 # Bug #1624725
147 # https://bugs.launchpad.net/duplicity/+bug/1624725150 # https://bugs.launchpad.net/duplicity/+bug/1624725
148 self.assertEqual(inc_sel_file(151 self.assertEqual(inc_sel_file(
149 "testfiles/select2/1/1sub1/1sub1sub1/",152 u"testfiles/select2/1/1sub1/1sub1sub1/",
150 "testfiles/select2/1/1sub1/1sub1sub1/1sub1sub1_file.txt"), 1)153 u"testfiles/select2/1/1sub1/1sub1sub1/1sub1sub1_file.txt"), 1)
151154
152 def test_included_files_are_matched_slash_2_parents(self):155 def test_included_files_are_matched_slash_2_parents(self):
153 """Test that duplicity will scan parent of glob/"""156 """Test that duplicity will scan parent of glob/"""
154 # Bug #1624725157 # Bug #1624725
155 # https://bugs.launchpad.net/duplicity/+bug/1624725158 # https://bugs.launchpad.net/duplicity/+bug/1624725
156 self.assertEqual(inc_sel_dir(159 self.assertEqual(inc_sel_dir(
157 "testfiles/select2/1/1sub1/1sub1sub1/",160 u"testfiles/select2/1/1sub1/1sub1sub1/",
158 "testfiles/select2/1/1sub1/1sub1sub1"), 1)161 u"testfiles/select2/1/1sub1/1sub1sub1"), 1)
159 self.assertEqual(inc_sel_dir(162 self.assertEqual(inc_sel_dir(
160 "testfiles/select2/1/1sub1/1sub1sub1/",163 u"testfiles/select2/1/1sub1/1sub1sub1/",
161 "testfiles/select2/1/1sub1"), 2)164 u"testfiles/select2/1/1sub1"), 2)
162165
163 def test_included_files_are_matched_slash_wildcard(self):166 def test_included_files_are_matched_slash_wildcard(self):
164 """Test that files within an included folder are matched with /"""167 """Test that files within an included folder are matched with /"""
165 # Bug #1624725168 # Bug #1624725
166 # https://bugs.launchpad.net/duplicity/+bug/1624725169 # https://bugs.launchpad.net/duplicity/+bug/1624725
167 self.assertEqual(inc_sel_file("fold*/", "folder/file.txt"), 1)170 self.assertEqual(inc_sel_file(u"fold*/", u"folder/file.txt"), 1)
168171
169 def test_slash_matches_everything(self):172 def test_slash_matches_everything(self):
170 """Test / matches everything"""173 """Test / matches everything"""
171 self.assertEqual(inc_sel_dir("/", "/tmp/testfiles/select/1/2"), 1)174 self.assertEqual(inc_sel_dir(u"/", u"/tmp/testfiles/select/1/2"), 1)
172 self.assertEqual(inc_sel_dir("/", "/test/random/path"), 1)175 self.assertEqual(inc_sel_dir(u"/", u"/test/random/path"), 1)
173 self.assertEqual(exc_sel_dir("/", "/test/random/path"), 0)176 self.assertEqual(exc_sel_dir(u"/", u"/test/random/path"), 0)
174 self.assertEqual(inc_sel_dir("/", "/"), 1)177 self.assertEqual(inc_sel_dir(u"/", u"/"), 1)
175 self.assertEqual(inc_sel_dir("/", "/var/log"), 1)178 self.assertEqual(inc_sel_dir(u"/", u"/var/log"), 1)
176 self.assertEqual(inc_sel_file("/", "/var/log/log.txt"), 1)179 self.assertEqual(inc_sel_file(u"/", u"/var/log/log.txt"), 1)
177180
178 def test_slash_star_scans_folder(self):181 def test_slash_star_scans_folder(self):
179 """Test that folder/* scans folder/"""182 """Test that folder/* scans folder/"""
180 # This behaviour is a bit ambiguous - either include or scan could be183 # This behaviour is a bit ambiguous - either include or scan could be
181 # argued as most appropriate here, but only an empty folder is at stake184 # argued as most appropriate here, but only an empty folder is at stake
182 # so long as test_slash_star_includes_folder_contents passes.185 # so long as test_slash_star_includes_folder_contents passes.
183 self.assertEqual(inc_sel_dir("folder/*", "folder"), 2)186 self.assertEqual(inc_sel_dir(u"folder/*", u"folder"), 2)
184187
185 def test_slash_star_includes_folder_contents(self):188 def test_slash_star_includes_folder_contents(self):
186 """Test that folder/* includes folder contents"""189 """Test that folder/* includes folder contents"""
187 self.assertEqual(inc_sel_file("folder/*", "folder/file.txt"), 1)190 self.assertEqual(inc_sel_file(u"folder/*", u"folder/file.txt"), 1)
188 self.assertEqual(inc_sel_file("folder/*", "folder/other_file.log"), 1)191 self.assertEqual(inc_sel_file(u"folder/*", u"folder/other_file.log"), 1)
189192
190 def test_slash_star_star_scans_folder(self):193 def test_slash_star_star_scans_folder(self):
191 """Test that folder/** scans folder/"""194 """Test that folder/** scans folder/"""
192 self.assertEqual(inc_sel_dir("folder/**", "folder"), 2)195 self.assertEqual(inc_sel_dir(u"folder/**", u"folder"), 2)
193196
194 def test_simple_trailing_slash_match(self):197 def test_simple_trailing_slash_match(self):
195 """Test that a normal folder string ending in / matches that path"""198 """Test that a normal folder string ending in / matches that path"""
196 self.assertEqual(inc_sel_dir("testfiles/select/1/2/1/",199 self.assertEqual(inc_sel_dir(u"testfiles/select/1/2/1/",
197 "testfiles/select/1/2/1"), 1)200 u"testfiles/select/1/2/1"), 1)
198201
199 def test_double_asterisk_string_slash(self):202 def test_double_asterisk_string_slash(self):
200 """Test string starting with ** and ending in /"""203 """Test string starting with ** and ending in /"""
201 self.assertEqual(inc_sel_dir("**/1/2/", "testfiles/select/1/2"), 1)204 self.assertEqual(inc_sel_dir(u"**/1/2/", u"testfiles/select/1/2"), 1)
202205
203 def test_string_double_asterisk_string_slash(self):206 def test_string_double_asterisk_string_slash(self):
204 """Test string ** string /"""207 """Test string ** string /"""
205 self.assertEqual(inc_sel_dir("testfiles**/2/",208 self.assertEqual(inc_sel_dir(u"testfiles**/2/",
206 "testfiles/select/1/2"), 1)209 u"testfiles/select/1/2"), 1)
207210
208211
209class TestDoubleAsterisk(UnitTestCase):212class TestDoubleAsterisk(UnitTestCase):
@@ -211,19 +214,75 @@
211214
212 def test_double_asterisk_no_match(self):215 def test_double_asterisk_no_match(self):
213 """Test that a folder string ending /** does not match other paths"""216 """Test that a folder string ending /** does not match other paths"""
214 self.assertEqual(inc_sel_dir("/test/folder/**", "/test/foo"), None)217 self.assertEqual(inc_sel_dir(u"/test/folder/**", u"/test/foo"), None)
215218
216 def test_double_asterisk_match(self):219 def test_double_asterisk_match(self):
217 """Test that a folder string ending in /** matches that path"""220 """Test that a folder string ending in /** matches that path"""
218 self.assertEqual(inc_sel_dir("/test/folder/**",221 self.assertEqual(inc_sel_dir(u"/test/folder/**",
219 "/test/folder/foo"), 1)222 u"/test/folder/foo"), 1)
220 self.assertEqual(inc_sel_file("/test/folder/**",223 self.assertEqual(inc_sel_file(u"/test/folder/**",
221 "/test/folder/foo.txt"), 1)224 u"/test/folder/foo.txt"), 1)
222 self.assertEqual(inc_sel_dir("/test/folder/**",225 self.assertEqual(inc_sel_dir(u"/test/folder/**",
223 "/test/folder/2/foo"), 1)226 u"/test/folder/2/foo"), 1)
224 self.assertEqual(inc_sel_file("/test/folder/**",227 self.assertEqual(inc_sel_file(u"/test/folder/**",
225 "/test/folder/2/foo.txt"), 1)228 u"/test/folder/2/foo.txt"), 1)
226229
227 def test_asterisk_slash_double_asterisk(self):230 def test_asterisk_slash_double_asterisk(self):
228 """Test folder string ending in */**"""231 """Test folder string ending in */**"""
229 self.assertEqual(inc_sel_dir("fold*/**", "folder"), 2)232 self.assertEqual(inc_sel_dir(u"fold*/**", u"folder"), 2)
233
234
235class TestSimpleUnicode(UnitTestCase):
236 """Test simple unicode comparison"""
237
238 def test_simple_unicode(self):
239 """Test simple unicode comparison"""
240 self.assertEqual(inc_sel_file(u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt",
241 u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt"), 1)
242
243
244class TestSquareBrackets(UnitTestCase):
245 """Test glob matching where the glob includes []s and [!]s"""
246
247 def test_square_bracket_options(self):
248 """Test file including options in []s"""
249 self.assertEqual(inc_sel_file(u"/test/f[o,s,p]lder/foo.txt",
250 u"/test/folder/foo.txt"), 1)
251 self.assertEqual(inc_sel_file(u"/test/f[i,s,p]lder/foo.txt",
252 u"/test/folder/foo.txt"), None)
253 self.assertEqual(inc_sel_file(u"/test/f[s,o,p]lder/foo.txt",
254 u"/test/folder/foo.txt"), 1)
255
256 def test_square_bracket_options_unicode(self):
257 """Test file including options in []s"""
258 self.assertEqual(inc_sel_file(u"прыклад/пр[и,j,l]мер/例/Παράδειγμα/उदाहरण.txt",
259 u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt"), 1)
260 self.assertEqual(inc_sel_file(u"прыклад/п[a,b,c]имер/例/Παράδειγμα/उदाहरण.txt",
261 u"прыклад/пример/例/Παράδειγμα/उदाहरण.txt"), None)
262
263 def test_not_square_bracket_options(self):
264 """Test file including options in [!]s"""
265 self.assertEqual(inc_sel_file(u"/test/f[!o,s,p]lder/foo.txt",
266 u"/test/folder/foo.txt"), None)
267 self.assertEqual(inc_sel_file(u"/test/f[!i,s,p]lder/foo.txt",
268 u"/test/folder/foo.txt"), 1)
269 self.assertEqual(inc_sel_file(u"/test/f[!s,o,p]lder/foo.txt",
270 u"/test/folder/foo.txt"), None)
271
272 def test_square_bracket_range(self):
273 """Test file including range in []s"""
274 self.assertEqual(inc_sel_file(u"/test/folder[1-5]/foo.txt",
275 u"/test/folder4/foo.txt"), 1)
276 self.assertEqual(inc_sel_file(u"/test/folder[5-9]/foo.txt",
277 u"/test/folder4/foo.txt"), None)
278 self.assertEqual(inc_sel_file(u"/test/folder[1-5]/foo.txt",
279 u"/test/folder6/foo.txt"), None)
280
281 def test_square_bracket_not_range(self):
282 """Test file including range in [!]s"""
283 self.assertEqual(inc_sel_file(u"/test/folder[!1-5]/foo.txt",
284 u"/test/folder4/foo.txt"), None)
285 self.assertEqual(inc_sel_file(u"/test/folder[!5-9]/foo.txt",
286 u"/test/folder4/foo.txt"), 1)
287 self.assertEqual(inc_sel_file(u"/test/folder[!1-5]/foo.txt",
288 u"/test/folder6/foo.txt"), 1)
230289
=== modified file 'testing/unit/test_gpg.py'
--- testing/unit/test_gpg.py 2017-07-11 14:55:38 +0000
+++ testing/unit/test_gpg.py 2017-12-01 23:01:42 +0000
@@ -71,23 +71,23 @@
7171
72 def test_gpg_asym(self):72 def test_gpg_asym(self):
73 """Test GPG asymmetric encryption"""73 """Test GPG asymmetric encryption"""
74 profile = gpg.GPGProfile(passphrase=self.sign_passphrase,74 profile = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
75 recipients=[self.encrypt_key1,75 recipients=[self.encrypt_key1,
76 self.encrypt_key2])76 self.encrypt_key2])
77 self.gpg_cycle("aoensutha aonetuh saoe", profile)77 self.gpg_cycle("aoensutha aonetuh saoe", profile)
7878
79 profile2 = gpg.GPGProfile(passphrase=self.sign_passphrase,79 profile2 = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
80 recipients=[self.encrypt_key1])80 recipients=[self.encrypt_key1])
81 self.gpg_cycle("aoeu" * 10000, profile2)81 self.gpg_cycle("aoeu" * 10000, profile2)
8282
83 def test_gpg_hidden_asym(self):83 def test_gpg_hidden_asym(self):
84 """Test GPG asymmetric encryption with hidden key id"""84 """Test GPG asymmetric encryption with hidden key id"""
85 profile = gpg.GPGProfile(passphrase=self.sign_passphrase,85 profile = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
86 hidden_recipients=[self.encrypt_key1,86 hidden_recipients=[self.encrypt_key1,
87 self.encrypt_key2])87 self.encrypt_key2])
88 self.gpg_cycle("aoensutha aonetuh saoe", profile)88 self.gpg_cycle("aoensutha aonetuh saoe", profile)
8989
90 profile2 = gpg.GPGProfile(passphrase=self.sign_passphrase,90 profile2 = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
91 hidden_recipients=[self.encrypt_key1])91 hidden_recipients=[self.encrypt_key1])
92 self.gpg_cycle("aoeu" * 10000, profile2)92 self.gpg_cycle("aoeu" * 10000, profile2)
9393
@@ -95,7 +95,7 @@
95 """Test to make sure GPG reports the proper signature key"""95 """Test to make sure GPG reports the proper signature key"""
96 plaintext = "hello" * 5000096 plaintext = "hello" * 50000
9797
98 signing_profile = gpg.GPGProfile(passphrase=self.sign_passphrase,98 signing_profile = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
99 sign_key=self.sign_key,99 sign_key=self.sign_key,
100 recipients=[self.encrypt_key1])100 recipients=[self.encrypt_key1])
101101
@@ -114,7 +114,7 @@
114 """Test to make sure GPG reports the proper signature key even with hidden encryption key id"""114 """Test to make sure GPG reports the proper signature key even with hidden encryption key id"""
115 plaintext = "hello" * 50000115 plaintext = "hello" * 50000
116116
117 signing_profile = gpg.GPGProfile(passphrase=self.sign_passphrase,117 signing_profile = gpg.GPGProfile(passphrase=self.sign_passphrase_bytes,
118 sign_key=self.sign_key,118 sign_key=self.sign_key,
119 hidden_recipients=[self.encrypt_key1])119 hidden_recipients=[self.encrypt_key1])
120120
121121
=== modified file 'testing/unit/test_patchdir.py'
--- testing/unit/test_patchdir.py 2015-02-01 17:37:37 +0000
+++ testing/unit/test_patchdir.py 2017-12-01 23:01:42 +0000
@@ -21,7 +21,6 @@
2121
22from future_builtins import map22from future_builtins import map
2323
24import sys
25import cStringIO24import cStringIO
26import unittest25import unittest
2726
2827
=== modified file 'testing/unit/test_selection.py'
--- testing/unit/test_selection.py 2017-07-11 14:55:38 +0000
+++ testing/unit/test_selection.py 2017-12-01 23:01:42 +0000
@@ -1,3 +1,4 @@
1# -*- coding: utf-8 -*-
1# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-2# -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*-
2#3#
3# Copyright 2002 Ben Escoto <ben@emerose.org>4# Copyright 2002 Ben Escoto <ben@emerose.org>
@@ -36,165 +37,165 @@
36 def setUp(self):37 def setUp(self):
37 super(MatchingTest, self).setUp()38 super(MatchingTest, self).setUp()
38 self.unpack_testfiles()39 self.unpack_testfiles()
39 self.root = Path("testfiles/select")40 self.root = Path(u"testfiles/select")
40 self.Select = Select(self.root)41 self.Select = Select(self.root)
4142
42 def makeext(self, path):43 def makeext(self, path):
43 return self.root.new_index(tuple(path.split("/")))44 return self.root.new_index(tuple(path.split(u"/")))
4445
45 def testRegexp(self):46 def testRegexp(self):
46 """Test regular expression selection func"""47 """Test regular expression selection func"""
47 sf1 = self.Select.regexp_get_sf(".*\.py", 1)48 sf1 = self.Select.regexp_get_sf(u".*\.py", 1)
48 assert sf1(self.makeext("1.py")) == 149 assert sf1(self.makeext(u"1.py")) == 1
49 assert sf1(self.makeext("usr/foo.py")) == 150 assert sf1(self.makeext(u"usr/foo.py")) == 1
50 assert sf1(self.root.append("1.doc")) is None51 assert sf1(self.root.append(u"1.doc")) is None
5152
52 sf2 = self.Select.regexp_get_sf("hello", 0)53 sf2 = self.Select.regexp_get_sf(u"hello", 0)
53 assert sf2(Path("hello")) == 054 assert sf2(Path(u"hello")) == 0
54 assert sf2(Path("foohello_there")) == 055 assert sf2(Path(u"foohello_there")) == 0
55 assert sf2(Path("foo")) is None56 assert sf2(Path(u"foo")) is None
5657
57 def test_tuple_include(self):58 def test_tuple_include(self):
58 """Test include selection function made from a regular filename"""59 """Test include selection function made from a regular filename"""
59 self.assertRaises(FilePrefixError, self.Select.glob_get_normal_sf,60 self.assertRaises(FilePrefixError, self.Select.glob_get_normal_sf,
60 "foo", 1)61 u"foo", 1)
6162
62 sf2 = self.Select.glob_get_sf("testfiles/select/usr/local/bin/", 1)63 sf2 = self.Select.glob_get_sf(u"testfiles/select/usr/local/bin/", 1)
6364
64 with patch('duplicity.path.ROPath.isdir') as mock_isdir:65 with patch(u"duplicity.path.ROPath.isdir") as mock_isdir:
65 mock_isdir.return_value = True66 mock_isdir.return_value = True
66 # Can't pass the return_value as an argument to patch, i.e.:67 # Can't pass the return_value as an argument to patch, i.e.:
67 # with patch('duplicity.path.ROPath.isdir', return_value=True):68 # with patch("duplicity.path.ROPath.isdir", return_value=True):
68 # as build system's mock is too old to support it.69 # as build system's mock is too old to support it.
6970
70 self.assertEqual(sf2(self.makeext("usr")), 2)71 self.assertEqual(sf2(self.makeext(u"usr")), 2)
71 self.assertEqual(sf2(self.makeext("usr/local")), 2)72 self.assertEqual(sf2(self.makeext(u"usr/local")), 2)
72 self.assertEqual(sf2(self.makeext("usr/local/bin")), 1)73 self.assertEqual(sf2(self.makeext(u"usr/local/bin")), 1)
73 self.assertEqual(sf2(self.makeext("usr/local/doc")), None)74 self.assertEqual(sf2(self.makeext(u"usr/local/doc")), None)
74 self.assertEqual(sf2(self.makeext("usr/local/bin/gzip")), 1)75 self.assertEqual(sf2(self.makeext(u"usr/local/bin/gzip")), 1)
75 self.assertEqual(sf2(self.makeext("usr/local/bingzip")), None)76 self.assertEqual(sf2(self.makeext(u"usr/local/bingzip")), None)
7677
77 def test_tuple_exclude(self):78 def test_tuple_exclude(self):
78 """Test exclude selection function made from a regular filename"""79 """Test exclude selection function made from a regular filename"""
79 self.assertRaises(FilePrefixError, self.Select.glob_get_normal_sf,80 self.assertRaises(FilePrefixError, self.Select.glob_get_normal_sf,
80 "foo", 0)81 u"foo", 0)
8182
82 sf2 = self.Select.glob_get_sf("testfiles/select/usr/local/bin/", 0)83 sf2 = self.Select.glob_get_sf(u"testfiles/select/usr/local/bin/", 0)
8384
84 with patch('duplicity.path.ROPath.isdir') as mock_isdir:85 with patch(u"duplicity.path.ROPath.isdir") as mock_isdir:
85 mock_isdir.return_value = True86 mock_isdir.return_value = True
8687
87 assert sf2(self.makeext("usr")) is None88 assert sf2(self.makeext(u"usr")) is None
88 assert sf2(self.makeext("usr/local")) is None89 assert sf2(self.makeext(u"usr/local")) is None
89 assert sf2(self.makeext("usr/local/bin")) == 090 assert sf2(self.makeext(u"usr/local/bin")) == 0
90 assert sf2(self.makeext("usr/local/doc")) is None91 assert sf2(self.makeext(u"usr/local/doc")) is None
91 assert sf2(self.makeext("usr/local/bin/gzip")) == 092 assert sf2(self.makeext(u"usr/local/bin/gzip")) == 0
92 assert sf2(self.makeext("usr/local/bingzip")) is None93 assert sf2(self.makeext(u"usr/local/bingzip")) is None
9394
94 def test_glob_star_include(self):95 def test_glob_star_include(self):
95 """Test a few globbing patterns, including **"""96 """Test a few globbing patterns, including **"""
96 sf1 = self.Select.glob_get_sf("**", 1)97 sf1 = self.Select.glob_get_sf(u"**", 1)
97 assert sf1(self.makeext("foo")) == 198 assert sf1(self.makeext(u"foo")) == 1
98 assert sf1(self.makeext("")) == 199 assert sf1(self.makeext(u"")) == 1
99100
100 sf2 = self.Select.glob_get_sf("**.py", 1)101 sf2 = self.Select.glob_get_sf(u"**.py", 1)
101 assert sf2(self.makeext("foo")) == 2102 assert sf2(self.makeext(u"foo")) == 2
102 assert sf2(self.makeext("usr/local/bin")) == 2103 assert sf2(self.makeext(u"usr/local/bin")) == 2
103 assert sf2(self.makeext("what/ever.py")) == 1104 assert sf2(self.makeext(u"what/ever.py")) == 1
104 assert sf2(self.makeext("what/ever.py/foo")) == 1105 assert sf2(self.makeext(u"what/ever.py/foo")) == 1
105106
106 def test_glob_star_exclude(self):107 def test_glob_star_exclude(self):
107 """Test a few glob excludes, including **"""108 """Test a few glob excludes, including **"""
108 sf1 = self.Select.glob_get_sf("**", 0)109 sf1 = self.Select.glob_get_sf(u"**", 0)
109 assert sf1(self.makeext("/usr/local/bin")) == 0110 assert sf1(self.makeext(u"/usr/local/bin")) == 0
110111
111 sf2 = self.Select.glob_get_sf("**.py", 0)112 sf2 = self.Select.glob_get_sf(u"**.py", 0)
112 assert sf2(self.makeext("foo")) is None113 assert sf2(self.makeext(u"foo")) is None
113 assert sf2(self.makeext("usr/local/bin")) is None114 assert sf2(self.makeext(u"usr/local/bin")) is None
114 assert sf2(self.makeext("what/ever.py")) == 0115 assert sf2(self.makeext(u"what/ever.py")) == 0
115 assert sf2(self.makeext("what/ever.py/foo")) == 0116 assert sf2(self.makeext(u"what/ever.py/foo")) == 0
116117
117 def test_simple_glob_double_asterisk(self):118 def test_simple_glob_double_asterisk(self):
118 """test_simple_glob_double_asterisk - primarily to check that the defaults used by the error tests work"""119 """test_simple_glob_double_asterisk - primarily to check that the defaults used by the error tests work"""
119 assert self.Select.glob_get_normal_sf("**", 1)120 assert self.Select.glob_get_normal_sf(u"**", 1)
120121
121 def test_glob_sf_exception(self):122 def test_glob_sf_exception(self):
122 """test_glob_sf_exception - see if globbing errors returned"""123 """test_glob_sf_exception - see if globbing errors returned"""
123 self.assertRaises(GlobbingError, self.Select.glob_get_normal_sf,124 self.assertRaises(GlobbingError, self.Select.glob_get_normal_sf,
124 "testfiles/select/hello//there", 1)125 u"testfiles/select/hello//there", 1)
125126
126 def test_file_prefix_sf_exception(self):127 def test_file_prefix_sf_exception(self):
127 """test_file_prefix_sf_exception - see if FilePrefix error is returned"""128 """test_file_prefix_sf_exception - see if FilePrefix error is returned"""
128 # These should raise a FilePrefixError because the root directory for the selection is "testfiles/select"129 # These should raise a FilePrefixError because the root directory for the selection is "testfiles/select"
129 self.assertRaises(FilePrefixError,130 self.assertRaises(FilePrefixError,
130 self.Select.glob_get_sf, "testfiles/whatever", 1)131 self.Select.glob_get_sf, u"testfiles/whatever", 1)
131 self.assertRaises(FilePrefixError,132 self.assertRaises(FilePrefixError,
132 self.Select.glob_get_sf, "testfiles/?hello", 0)133 self.Select.glob_get_sf, u"testfiles/?hello", 0)
133134
134 def test_scan(self):135 def test_scan(self):
135 """Tests what is returned for selection tests regarding directory scanning"""136 """Tests what is returned for selection tests regarding directory scanning"""
136 select = Select(Path("/"))137 select = Select(Path(u"/"))
137138
138 assert select.glob_get_sf("**.py", 1)(Path("/")) == 2139 assert select.glob_get_sf(u"**.py", 1)(Path(u"/")) == 2
139 assert select.glob_get_sf("**.py", 1)(Path("foo")) == 2140 assert select.glob_get_sf(u"**.py", 1)(Path(u"foo")) == 2
140 assert select.glob_get_sf("**.py", 1)(Path("usr/local/bin")) == 2141 assert select.glob_get_sf(u"**.py", 1)(Path(u"usr/local/bin")) == 2
141 assert select.glob_get_sf("/testfiles/select/**.py", 1)(Path("/testfiles/select")) == 2142 assert select.glob_get_sf(u"/testfiles/select/**.py", 1)(Path(u"/testfiles/select")) == 2
142 assert select.glob_get_sf("/testfiles/select/test.py", 1)(Path("/testfiles/select")) == 2143 assert select.glob_get_sf(u"/testfiles/select/test.py", 1)(Path(u"/testfiles/select")) == 2
143 assert select.glob_get_normal_sf("/testfiles/se?ect/test.py", 1)(Path("/testfiles/select")) == 2144 assert select.glob_get_normal_sf(u"/testfiles/se?ect/test.py", 1)(Path(u"/testfiles/select")) == 2
144 assert select.glob_get_sf("/testfiles/select/test.py", 0)(Path("/testfiles/select")) is None145 assert select.glob_get_sf(u"/testfiles/select/test.py", 0)(Path(u"/testfiles/select")) is None
145 assert select.glob_get_normal_sf("/testfiles/select/test.py", 0)(Path("/testfiles/select")) is None146 assert select.glob_get_normal_sf(u"/testfiles/select/test.py", 0)(Path(u"/testfiles/select")) is None
146147
147 def test_ignore_case(self):148 def test_ignore_case(self):
148 """test_ignore_case - try a few expressions with ignorecase:"""149 """test_ignore_case - try a few expressions with ignorecase:"""
149150
150 sf = self.Select.glob_get_sf("ignorecase:testfiles/SeLect/foo/bar", 1)151 sf = self.Select.glob_get_sf(u"ignorecase:testfiles/SeLect/foo/bar", 1)
151 assert sf(self.makeext("FOO/BAR")) == 1152 assert sf(self.makeext(u"FOO/BAR")) == 1
152 assert sf(self.makeext("foo/bar")) == 1153 assert sf(self.makeext(u"foo/bar")) == 1
153 assert sf(self.makeext("fOo/BaR")) == 1154 assert sf(self.makeext(u"fOo/BaR")) == 1
154 self.assertRaises(FilePrefixError, self.Select.glob_get_sf, "ignorecase:tesfiles/sect/foo/bar", 1)155 self.assertRaises(FilePrefixError, self.Select.glob_get_sf, u"ignorecase:tesfiles/sect/foo/bar", 1)
155156
156 def test_root(self):157 def test_root(self):
157 """test_root - / may be a counterexample to several of these.."""158 """test_root - / may be a counterexample to several of these.."""
158 root = Path("/")159 root = Path(u"/")
159 select = Select(root)160 select = Select(root)
160161
161 self.assertEqual(select.glob_get_sf("/", 1)(root), 1)162 self.assertEqual(select.glob_get_sf(u"/", 1)(root), 1)
162 self.assertEqual(select.glob_get_sf("/foo", 1)(root), 2)163 self.assertEqual(select.glob_get_sf(u"/foo", 1)(root), 2)
163 self.assertEqual(select.glob_get_sf("/foo/bar", 1)(root), 2)164 self.assertEqual(select.glob_get_sf(u"/foo/bar", 1)(root), 2)
164 self.assertEqual(select.glob_get_sf("/", 0)(root), 0)165 self.assertEqual(select.glob_get_sf(u"/", 0)(root), 0)
165 self.assertEqual(select.glob_get_sf("/foo", 0)(root), None)166 self.assertEqual(select.glob_get_sf(u"/foo", 0)(root), None)
166167
167 assert select.glob_get_sf("**.py", 1)(root) == 2168 assert select.glob_get_sf(u"**.py", 1)(root) == 2
168 assert select.glob_get_sf("**", 1)(root) == 1169 assert select.glob_get_sf(u"**", 1)(root) == 1
169 assert select.glob_get_sf("ignorecase:/", 1)(root) == 1170 assert select.glob_get_sf(u"ignorecase:/", 1)(root) == 1
170 assert select.glob_get_sf("**.py", 0)(root) is None171 assert select.glob_get_sf(u"**.py", 0)(root) is None
171 assert select.glob_get_sf("**", 0)(root) == 0172 assert select.glob_get_sf(u"**", 0)(root) == 0
172 assert select.glob_get_sf("/foo/*", 0)(root) is None173 assert select.glob_get_sf(u"/foo/*", 0)(root) is None
173174
174 def test_other_filesystems(self):175 def test_other_filesystems(self):
175 """Test to see if --exclude-other-filesystems works correctly"""176 """Test to see if --exclude-other-filesystems works correctly"""
176 root = Path("/")177 root = Path(u"/")
177 select = Select(root)178 select = Select(root)
178 sf = select.other_filesystems_get_sf(0)179 sf = select.other_filesystems_get_sf(0)
179 assert sf(root) is None180 assert sf(root) is None
180 if os.path.ismount("/usr/bin"):181 if os.path.ismount(u"/usr/bin"):
181 sfval = 0182 sfval = 0
182 else:183 else:
183 sfval = None184 sfval = None
184 assert sf(Path("/usr/bin")) == sfval, \185 assert sf(Path(u"/usr/bin")) == sfval, \
185 "Assumption: /usr/bin is on the same filesystem as /"186 u"Assumption: /usr/bin is on the same filesystem as /"
186 if os.path.ismount("/dev"):187 if os.path.ismount(u"/dev"):
187 sfval = 0188 sfval = 0
188 else:189 else:
189 sfval = None190 sfval = None
190 assert sf(Path("/dev")) == sfval, \191 assert sf(Path(u"/dev")) == sfval, \
191 "Assumption: /dev is on a different filesystem"192 u"Assumption: /dev is on a different filesystem"
192 if os.path.ismount("/proc"):193 if os.path.ismount(u"/proc"):
193 sfval = 0194 sfval = 0
194 else:195 else:
195 sfval = None196 sfval = None
196 assert sf(Path("/proc")) == sfval, \197 assert sf(Path(u"/proc")) == sfval, \
197 "Assumption: /proc is on a different filesystem"198 u"Assumption: /proc is on a different filesystem"
198199
199200
200class ParseArgsTest(UnitTestCase):201class ParseArgsTest(UnitTestCase):
@@ -203,24 +204,34 @@
203 super(ParseArgsTest, self).setUp()204 super(ParseArgsTest, self).setUp()
204 self.unpack_testfiles()205 self.unpack_testfiles()
205 self.root = None206 self.root = None
206 self.expected_restored_tree = [(), ('1',), ('1', '1sub1'), ('1', '1sub1', '1sub1sub1'),207 self.expected_restored_tree = [(), (u"1",), (u"1", u"1sub1"), (u"1", u"1sub1", u"1sub1sub1"),
207 ('1', '1sub1', '1sub1sub1', '1sub1sub1_file.txt'), ('1', '1sub1', '1sub1sub3'),208 (u"1", u"1sub1", u"1sub1sub1", u"1sub1sub1_file.txt"),
208 ('1', '1sub2'), ('1', '1sub2', '1sub2sub1'), ('1', '1sub3'),209 (u"1", u"1sub1", u"1sub1sub3"), (u"1", u"1sub2"), (u"1", u"1sub2", u"1sub2sub1"),
209 ('1', '1sub3', '1sub3sub3'), ('1.py',), ('2',), ('2', '2sub1'),210 (u"1", u"1sub3"), (u"1", u"1sub3", u"1sub3sub3"), (u"1.py",), (u"2",),
210 ('2', '2sub1', '2sub1sub1'), ('2', '2sub1', '2sub1sub1', '2sub1sub1_file.txt'),211 (u"2", u"2sub1"), (u"2", u"2sub1", u"2sub1sub1"),
211 ('3',), ('3', '3sub2'), ('3', '3sub2', '3sub2sub1'),212 (u"2", u"2sub1", u"2sub1sub1", u"2sub1sub1_file.txt"),
212 ('3', '3sub2', '3sub2sub2'), ('3', '3sub2', '3sub2sub3'), ('3', '3sub3'),213 (u"3",), (u"3", u"3sub2"), (u"3", u"3sub2", u"3sub2sub1"),
213 ('3', '3sub3', '3sub3sub1'), ('3', '3sub3', '3sub3sub2'),214 (u"3", u"3sub2", u"3sub2sub2"), (u"3", u"3sub2", u"3sub2sub3"), (u"3", u"3sub3"),
214 ('3', '3sub3', '3sub3sub2', '3sub3sub2_file.txt'), ('3', '3sub3', '3sub3sub3')]215 (u"3", u"3sub3", u"3sub3sub1"), (u"3", u"3sub3", u"3sub3sub2"),
216 (u"3", u"3sub3", u"3sub3sub2", u"3sub3sub2_file.txt"),
217 (u"3", u"3sub3", u"3sub3sub3")]
218
219 def uc_index_from_path(self, path):
220 """Takes a path type and returns path.index, with each element converted into unicode"""
221 uindex = tuple([element.decode(sys.getfilesystemencoding(), "strict") for element in path.index])
222 return uindex
215223
216 def ParseTest(self, tuplelist, indicies, filelists=[]):224 def ParseTest(self, tuplelist, indicies, filelists=[]):
217 """No error if running select on tuple goes over indicies"""225 """No error if running select on tuple goes over indicies"""
218 if not self.root:226 if not self.root:
219 self.root = Path("testfiles/select")227 self.root = Path(u"testfiles/select")
220 self.Select = Select(self.root)228 self.Select = Select(self.root)
221 self.Select.ParseArgs(tuplelist, self.remake_filelists(filelists))229 self.Select.ParseArgs(tuplelist, self.remake_filelists(filelists))
222 self.Select.set_iter()230 self.Select.set_iter()
223 results_as_list = list(Iter.map(lambda path: path.index, self.Select))231
232 # Create a list of the paths returned by the select function, converted
233 # into path.index styled tuples
234 results_as_list = list(Iter.map(self.uc_index_from_path, self.Select))
224 # print(results_as_list)235 # print(results_as_list)
225 self.assertEqual(indicies, results_as_list)236 self.assertEqual(indicies, results_as_list)
226237
@@ -228,7 +239,7 @@
228 """Turn strings in filelist into fileobjs"""239 """Turn strings in filelist into fileobjs"""
229 new_filelists = []240 new_filelists = []
230 for f in filelist:241 for f in filelist:
231 if isinstance(f, types.StringType):242 if isinstance(f, unicode):
232 new_filelists.append(StringIO.StringIO(f))243 new_filelists.append(StringIO.StringIO(f))
233 else:244 else:
234 new_filelists.append(f)245 new_filelists.append(f)
@@ -236,629 +247,645 @@
236247
237 def test_parse(self):248 def test_parse(self):
238 """Test just one include, all exclude"""249 """Test just one include, all exclude"""
239 self.ParseTest([("--include", "testfiles/select/1/1"),250 self.ParseTest([(u"--include", u"testfiles/select/1/1"),
240 ("--exclude", "**")],251 (u"--exclude", u"**")],
241 [(), ('1',), ("1", "1"), ("1", '1', '1'),252 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"1"),
242 ('1', '1', '2'), ('1', '1', '3')])253 (u"1", u"1", u"2"), (u"1", u"1", u"3")])
243254
244 def test_parse2(self):255 def test_parse2(self):
245 """Test three level include/exclude"""256 """Test three level include/exclude"""
246 self.ParseTest([("--exclude", "testfiles/select/1/1/1"),257 self.ParseTest([(u"--exclude", u"testfiles/select/1/1/1"),
247 ("--include", "testfiles/select/1/1"),258 (u"--include", u"testfiles/select/1/1"),
248 ("--exclude", "testfiles/select/1"),259 (u"--exclude", u"testfiles/select/1"),
249 ("--exclude", "**")],260 (u"--exclude", u"**")],
250 [(), ('1',), ('1', '1'), ('1', '1', '2'),261 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
251 ('1', '1', '3')])262 (u"1", u"1", u"3")])
252263
253 def test_filelist(self):264 def test_filelist(self):
254 """Filelist glob test similar to above testParse2"""265 """Filelist glob test similar to above testParse2"""
255 self.ParseTest([("--include-filelist", "file")],266 self.ParseTest([(u"--include-filelist", u"file")],
256 [(), ('1',), ('1', '1'), ('1', '1', '2'),267 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
257 ('1', '1', '3')],268 (u"1", u"1", u"3")],
258 ["- testfiles/select/1/1/1\n"269 [u"- testfiles/select/1/1/1\n"
259 "testfiles/select/1/1\n"270 u"testfiles/select/1/1\n"
260 "- testfiles/select/1\n"271 u"- testfiles/select/1\n"
261 "- **"])272 u"- **"])
262273
263 def test_include_filelist_1_trailing_whitespace(self):274 def test_include_filelist_1_trailing_whitespace(self):
264 """Filelist glob test similar to globbing filelist, but with 1 trailing whitespace on include"""275 """Filelist glob test similar to globbing filelist, but with 1 trailing whitespace on include"""
265 self.ParseTest([("--include-filelist", "file")],276 self.ParseTest([(u"--include-filelist", u"file")],
266 [(), ('1',), ('1', '1'), ('1', '1', '2'),277 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
267 ('1', '1', '3')],278 (u"1", u"1", u"3")],
268 ["- testfiles/select/1/1/1\n"279 [u"- testfiles/select/1/1/1\n"
269 "testfiles/select/1/1 \n"280 u"testfiles/select/1/1 \n"
270 "- testfiles/select/1\n"281 u"- testfiles/select/1\n"
271 "- **"])282 u"- **"])
272283
273 def test_include_filelist_2_trailing_whitespaces(self):284 def test_include_filelist_2_trailing_whitespaces(self):
274 """Filelist glob test similar to globbing filelist, but with 2 trailing whitespaces on include"""285 """Filelist glob test similar to globbing filelist, but with 2 trailing whitespaces on include"""
275 self.ParseTest([("--include-filelist", "file")],286 self.ParseTest([(u"--include-filelist", u"file")],
276 [(), ('1',), ('1', '1'), ('1', '1', '2'),287 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
277 ('1', '1', '3')],288 (u"1", u"1", u"3")],
278 ["- testfiles/select/1/1/1\n"289 [u"- testfiles/select/1/1/1\n"
279 "testfiles/select/1/1 \n"290 u"testfiles/select/1/1 \n"
280 "- testfiles/select/1\n"291 u"- testfiles/select/1\n"
281 "- **"])292 u"- **"])
282293
283 def test_include_filelist_1_leading_whitespace(self):294 def test_include_filelist_1_leading_whitespace(self):
284 """Filelist glob test similar to globbing filelist, but with 1 leading whitespace on include"""295 """Filelist glob test similar to globbing filelist, but with 1 leading whitespace on include"""
285 self.ParseTest([("--include-filelist", "file")],296 self.ParseTest([(u"--include-filelist", u"file")],
286 [(), ('1',), ('1', '1'), ('1', '1', '2'),297 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
287 ('1', '1', '3')],298 (u"1", u"1", u"3")],
288 ["- testfiles/select/1/1/1\n"299 [u"- testfiles/select/1/1/1\n"
289 " testfiles/select/1/1\n"300 u" testfiles/select/1/1\n"
290 "- testfiles/select/1\n"301 u"- testfiles/select/1\n"
291 "- **"])302 u"- **"])
292303
293 def test_include_filelist_2_leading_whitespaces(self):304 def test_include_filelist_2_leading_whitespaces(self):
294 """Filelist glob test similar to globbing filelist, but with 2 leading whitespaces on include"""305 """Filelist glob test similar to globbing filelist, but with 2 leading whitespaces on include"""
295 self.ParseTest([("--include-filelist", "file")],306 self.ParseTest([(u"--include-filelist", u"file")],
296 [(), ('1',), ('1', '1'), ('1', '1', '2'),307 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
297 ('1', '1', '3')],308 (u"1", u"1", u"3")],
298 ["- testfiles/select/1/1/1\n"309 [u"- testfiles/select/1/1/1\n"
299 " testfiles/select/1/1\n"310 u" testfiles/select/1/1\n"
300 "- testfiles/select/1\n"311 u"- testfiles/select/1\n"
301 "- **"])312 u"- **"])
302313
303 def test_include_filelist_1_trailing_whitespace_exclude(self):314 def test_include_filelist_1_trailing_whitespace_exclude(self):
304 """Filelist glob test similar to globbing filelist, but with 1 trailing whitespace on exclude"""315 """Filelist glob test similar to globbing filelist, but with 1 trailing whitespace on exclude"""
305 self.ParseTest([("--include-filelist", "file")],316 self.ParseTest([(u"--include-filelist", u"file")],
306 [(), ('1',), ('1', '1'), ('1', '1', '2'),317 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
307 ('1', '1', '3')],318 (u"1", u"1", u"3")],
308 ["- testfiles/select/1/1/1 \n"319 [u"- testfiles/select/1/1/1 \n"
309 "testfiles/select/1/1\n"320 u"testfiles/select/1/1\n"
310 "- testfiles/select/1\n"321 u"- testfiles/select/1\n"
311 "- **"])322 u"- **"])
312323
313 def test_include_filelist_2_trailing_whitespace_exclude(self):324 def test_include_filelist_2_trailing_whitespace_exclude(self):
314 """Filelist glob test similar to globbing filelist, but with 2 trailing whitespaces on exclude"""325 """Filelist glob test similar to globbing filelist, but with 2 trailing whitespaces on exclude"""
315 self.ParseTest([("--include-filelist", "file")],326 self.ParseTest([(u"--include-filelist", u"file")],
316 [(), ('1',), ('1', '1'), ('1', '1', '2'),327 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
317 ('1', '1', '3')],328 (u"1", u"1", u"3")],
318 ["- testfiles/select/1/1/1 \n"329 [u"- testfiles/select/1/1/1 \n"
319 "testfiles/select/1/1\n"330 u"testfiles/select/1/1\n"
320 "- testfiles/select/1\n"331 u"- testfiles/select/1\n"
321 "- **"])332 u"- **"])
322333
323 def test_include_filelist_1_leading_whitespace_exclude(self):334 def test_include_filelist_1_leading_whitespace_exclude(self):
324 """Filelist glob test similar to globbing filelist, but with 1 leading whitespace on exclude"""335 """Filelist glob test similar to globbing filelist, but with 1 leading whitespace on exclude"""
325 self.ParseTest([("--include-filelist", "file")],336 self.ParseTest([(u"--include-filelist", u"file")],
326 [(), ('1',), ('1', '1'), ('1', '1', '2'),337 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
327 ('1', '1', '3')],338 (u"1", u"1", u"3")],
328 [" - testfiles/select/1/1/1\n"339 [u" - testfiles/select/1/1/1\n"
329 "testfiles/select/1/1\n"340 u"testfiles/select/1/1\n"
330 "- testfiles/select/1\n"341 u"- testfiles/select/1\n"
331 "- **"])342 u"- **"])
332343
333 def test_include_filelist_2_leading_whitespaces_exclude(self):344 def test_include_filelist_2_leading_whitespaces_exclude(self):
334 """Filelist glob test similar to globbing filelist, but with 2 leading whitespaces on exclude"""345 """Filelist glob test similar to globbing filelist, but with 2 leading whitespaces on exclude"""
335 self.ParseTest([("--include-filelist", "file")],346 self.ParseTest([(u"--include-filelist", u"file")],
336 [(), ('1',), ('1', '1'), ('1', '1', '2'),347 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
337 ('1', '1', '3')],348 (u"1", u"1", u"3")],
338 [" - testfiles/select/1/1/1\n"349 [u" - testfiles/select/1/1/1\n"
339 "testfiles/select/1/1\n"350 u"testfiles/select/1/1\n"
340 "- testfiles/select/1\n"351 u"- testfiles/select/1\n"
341 "- **"])352 u"- **"])
342353
343 def test_include_filelist_check_excluded_folder_included_for_contents(self):354 def test_include_filelist_check_excluded_folder_included_for_contents(self):
344 """Filelist glob test to check excluded folder is included if contents are"""355 """Filelist glob test to check excluded folder is included if contents are"""
345 self.ParseTest([("--include-filelist", "file")],356 self.ParseTest([(u"--include-filelist", u"file")],
346 [(), ('1',), ('1', '1'), ('1', '1', '1'), ('1', '1', '2'),357 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"1"), (u"1", u"1", u"2"),
347 ('1', '1', '3'), ('1', '2'), ('1', '2', '1'), ('1', '3'), ('1', '3', '1'), ('1', '3', '2'),358 (u"1", u"1", u"3"), (u"1", u"2"), (u"1", u"2", u"1"), (u"1", u"3"), (u"1", u"3", u"1"),
348 ('1', '3', '3')],359 (u"1", u"3", u"2"), (u"1", u"3", u"3")],
349 ["+ testfiles/select/1/2/1\n"360 [u"+ testfiles/select/1/2/1\n"
350 "- testfiles/select/1/2\n"361 u"- testfiles/select/1/2\n"
351 "testfiles/select/1\n"362 u"testfiles/select/1\n"
352 "- **"])363 u"- **"])
353364
354 def test_include_filelist_with_unnecessary_quotes(self):365 def test_include_filelist_with_unnecessary_quotes(self):
355 """Filelist glob test similar to globbing filelist, but with quotes around one of the paths."""366 """Filelist glob test similar to globbing filelist, but with quotes around one of the paths."""
356 self.ParseTest([("--include-filelist", "file")],367 self.ParseTest([(u"--include-filelist", u"file")],
357 [(), ('1',), ('1', '1'), ('1', '1', '2'),368 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
358 ('1', '1', '3')],369 (u"1", u"1", u"3")],
359 ["- 'testfiles/select/1/1/1'\n"370 [u"- 'testfiles/select/1/1/1'\n"
360 "testfiles/select/1/1\n"371 u"testfiles/select/1/1\n"
361 "- testfiles/select/1\n"372 u"- testfiles/select/1\n"
362 "- **"])373 u"- **"])
363374
364 def test_include_filelist_with_unnecessary_double_quotes(self):375 def test_include_filelist_with_unnecessary_double_quotes(self):
365 """Filelist glob test similar to globbing filelist, but with double quotes around one of the paths."""376 """Filelist glob test similar to globbing filelist, but with double quotes around one of the paths."""
366 self.ParseTest([("--include-filelist", "file")],377 self.ParseTest([(u"--include-filelist", u"file")],
367 [(), ('1',), ('1', '1'), ('1', '1', '2'),378 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
368 ('1', '1', '3')],379 (u"1", u"1", u"3")],
369 ['- "testfiles/select/1/1/1"\n'380 [u'- "testfiles/select/1/1/1"\n'
370 'testfiles/select/1/1\n'381 u"testfiles/select/1/1\n"
371 '- testfiles/select/1\n'382 u"- testfiles/select/1\n"
372 '- **'])383 u"- **"])
373384
374 def test_include_filelist_with_full_line_comment(self):385 def test_include_filelist_with_full_line_comment(self):
375 """Filelist glob test similar to globbing filelist, but with a full-line comment."""386 """Filelist glob test similar to globbing filelist, but with a full-line comment."""
376 self.ParseTest([("--include-filelist", "file")],387 self.ParseTest([(u"--include-filelist", u"file")],
377 [(), ('1',), ('1', '1'), ('1', '1', '2'),388 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
378 ('1', '1', '3')],389 (u"1", u"1", u"3")],
379 ['- testfiles/select/1/1/1\n'390 [u"- testfiles/select/1/1/1\n"
380 '# This is a test\n'391 u"# This is a test\n"
381 'testfiles/select/1/1\n'392 u"testfiles/select/1/1\n"
382 '- testfiles/select/1\n'393 u"- testfiles/select/1\n"
383 '- **'])394 u"- **"])
384395
385 def test_include_filelist_with_blank_line(self):396 def test_include_filelist_with_blank_line(self):
386 """Filelist glob test similar to globbing filelist, but with a blank line."""397 """Filelist glob test similar to globbing filelist, but with a blank line."""
387 self.ParseTest([("--include-filelist", "file")],398 self.ParseTest([(u"--include-filelist", u"file")],
388 [(), ('1',), ('1', '1'), ('1', '1', '2'),399 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
389 ('1', '1', '3')],400 (u"1", u"1", u"3")],
390 ['- testfiles/select/1/1/1\n'401 [u"- testfiles/select/1/1/1\n"
391 '\n'402 u"\n"
392 'testfiles/select/1/1\n'403 u"testfiles/select/1/1\n"
393 '- testfiles/select/1\n'404 u"- testfiles/select/1\n"
394 '- **'])405 u"- **"])
395406
396 def test_include_filelist_with_blank_line_and_whitespace(self):407 def test_include_filelist_with_blank_line_and_whitespace(self):
397 """Filelist glob test similar to globbing filelist, but with a blank line and whitespace."""408 """Filelist glob test similar to globbing filelist, but with a blank line and whitespace."""
398 self.ParseTest([("--include-filelist", "file")],409 self.ParseTest([(u"--include-filelist", u"file")],
399 [(), ('1',), ('1', '1'), ('1', '1', '2'),410 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
400 ('1', '1', '3')],411 (u"1", u"1", u"3")],
401 ['- testfiles/select/1/1/1\n'412 [u"- testfiles/select/1/1/1\n"
402 ' \n'413 u" \n"
403 'testfiles/select/1/1\n'414 u"testfiles/select/1/1\n"
404 '- testfiles/select/1\n'415 u"- testfiles/select/1\n"
405 '- **'])416 u"- **"])
406417
407 def test_include_filelist_asterisk(self):418 def test_include_filelist_asterisk(self):
408 """Filelist glob test with * instead of 'testfiles'"""419 """Filelist glob test with * instead of 'testfiles'"""
409 # Thank you to Elifarley Cruz for this test case420 # Thank you to Elifarley Cruz for this test case
410 # (https://bugs.launchpad.net/duplicity/+bug/884371).421 # (https://bugs.launchpad.net/duplicity/+bug/884371).
411 self.ParseTest([("--include-filelist", "file")],422 self.ParseTest([(u"--include-filelist", u"file")],
412 [(), ('1',), ('1', '1'), ('1', '1', '1'),423 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"1"),
413 ('1', '1', '2'), ('1', '1', '3')],424 (u"1", u"1", u"2"), (u"1", u"1", u"3")],
414 ["*/select/1/1\n"425 [u"*/select/1/1\n"
415 "- **"])426 u"- **"])
416427
417 def test_include_filelist_asterisk_2(self):428 def test_include_filelist_asterisk_2(self):
418 """Identical to test_filelist, but with the exclude 'select' replaced with '*'"""429 """Identical to test_filelist, but with the exclude "select" replaced with '*'"""
419 self.ParseTest([("--include-filelist", "file")],430 self.ParseTest([(u"--include-filelist", u"file")],
420 [(), ('1',), ('1', '1'), ('1', '1', '2'),431 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
421 ('1', '1', '3')],432 (u"1", u"1", u"3")],
422 ["- testfiles/*/1/1/1\n"433 [u"- testfiles/*/1/1/1\n"
423 "testfiles/select/1/1\n"434 u"testfiles/select/1/1\n"
424 "- testfiles/select/1\n"435 u"- testfiles/select/1\n"
425 "- **"])436 u"- **"])
426437
427 def test_include_filelist_asterisk_3(self):438 def test_include_filelist_asterisk_3(self):
428 """Identical to test_filelist, but with the auto-include 'select' replaced with '*'"""439 """Identical to test_filelist, but with the auto-include "select" replaced with '*'"""
429 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)440 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
430 self.ParseTest([("--include-filelist", "file")],441 self.ParseTest([(u"--include-filelist", u"file")],
431 [(), ('1',), ('1', '1'), ('1', '1', '2'),442 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
432 ('1', '1', '3')],443 (u"1", u"1", u"3")],
433 ["- testfiles/select/1/1/1\n"444 [u"- testfiles/select/1/1/1\n"
434 "testfiles/*/1/1\n"445 u"testfiles/*/1/1\n"
435 "- testfiles/select/1\n"446 u"- testfiles/select/1\n"
436 "- **"])447 u"- **"])
437448
438 def test_include_filelist_asterisk_4(self):449 def test_include_filelist_asterisk_4(self):
439 """Identical to test_filelist, but with a specific include 'select' replaced with '*'"""450 """Identical to test_filelist, but with a specific include "select" replaced with '*'"""
440 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)451 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
441 self.ParseTest([("--include-filelist", "file")],452 self.ParseTest([(u"--include-filelist", u"file")],
442 [(), ('1',), ('1', '1'), ('1', '1', '2'),453 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
443 ('1', '1', '3')],454 (u"1", u"1", u"3")],
444 ["- testfiles/select/1/1/1\n"455 [u"- testfiles/select/1/1/1\n"
445 "+ testfiles/*/1/1\n"456 u"+ testfiles/*/1/1\n"
446 "- testfiles/select/1\n"457 u"- testfiles/select/1\n"
447 "- **"])458 u"- **"])
448459
449 def test_include_filelist_asterisk_5(self):460 def test_include_filelist_asterisk_5(self):
450 """Identical to test_filelist, but with all 'select's replaced with '*'"""461 """Identical to test_filelist, but with all 'select's replaced with '*'"""
451 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)462 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
452 self.ParseTest([("--include-filelist", "file")],463 self.ParseTest([(u"--include-filelist", u"file")],
453 [(), ('1',), ('1', '1'), ('1', '1', '2'),464 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
454 ('1', '1', '3')],465 (u"1", u"1", u"3")],
455 ["- testfiles/*/1/1/1\n"466 [u"- testfiles/*/1/1/1\n"
456 "+ testfiles/*/1/1\n"467 u"+ testfiles/*/1/1\n"
457 "- testfiles/*/1\n"468 u"- testfiles/*/1\n"
458 "- **"])469 u"- **"])
459470
460 def test_include_filelist_asterisk_6(self):471 def test_include_filelist_asterisk_6(self):
461 """Identical to test_filelist, but with numerous excluded folders replaced with '*'"""472 """Identical to test_filelist, but with numerous excluded folders replaced with '*'"""
462 self.ParseTest([("--include-filelist", "file")],473 self.ParseTest([(u"--include-filelist", u"file")],
463 [(), ('1',), ('1', '1'), ('1', '1', '2'),474 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
464 ('1', '1', '3')],475 (u"1", u"1", u"3")],
465 ["- */*/1/1/1\n"476 [u"- */*/1/1/1\n"
466 "+ testfiles/select/1/1\n"477 u"+ testfiles/select/1/1\n"
467 "- */*/1\n"478 u"- */*/1\n"
468 "- **"])479 u"- **"])
469480
470 def test_include_filelist_asterisk_7(self):481 def test_include_filelist_asterisk_7(self):
471 """Identical to test_filelist, but with numerous included/excluded folders replaced with '*'"""482 """Identical to test_filelist, but with numerous included/excluded folders replaced with '*'"""
472 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)483 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
473 self.ParseTest([("--include-filelist", "file")],484 self.ParseTest([(u"--include-filelist", u"file")],
474 [(), ('1',), ('1', '1'), ('1', '1', '2'),485 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
475 ('1', '1', '3')],486 (u"1", u"1", u"3")],
476 ["- */*/1/1/1\n"487 [u"- */*/1/1/1\n"
477 "+ */*/1/1\n"488 u"+ */*/1/1\n"
478 "- */*/1\n"489 u"- */*/1\n"
479 "- **"])490 u"- **"])
480491
481 def test_include_filelist_double_asterisk_1(self):492 def test_include_filelist_double_asterisk_1(self):
482 """Identical to test_filelist, but with the exclude 'select' replaced with '**'"""493 """Identical to test_filelist, but with the exclude "select' replaced with '**'"""
483 self.ParseTest([("--include-filelist", "file")],494 self.ParseTest([(u"--include-filelist", u"file")],
484 [(), ('1',), ('1', '1'), ('1', '1', '2'),495 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
485 ('1', '1', '3')],496 (u"1", u"1", u"3")],
486 ["- testfiles/**/1/1/1\n"497 [u"- testfiles/**/1/1/1\n"
487 "testfiles/select/1/1\n"498 u"testfiles/select/1/1\n"
488 "- testfiles/select/1\n"499 u"- testfiles/select/1\n"
489 "- **"])500 u"- **"])
490501
491 def test_include_filelist_double_asterisk_2(self):502 def test_include_filelist_double_asterisk_2(self):
492 """Identical to test_filelist, but with the include 'select' replaced with '**'"""503 """Identical to test_filelist, but with the include 'select' replaced with '**'"""
493 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)504 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
494 self.ParseTest([("--include-filelist", "file")],505 self.ParseTest([(u"--include-filelist", u"file")],
495 [(), ('1',), ('1', '1'), ('1', '1', '2'),506 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
496 ('1', '1', '3')],507 (u"1", u"1", u"3")],
497 ["- testfiles/select/1/1/1\n"508 [u"- testfiles/select/1/1/1\n"
498 "**ct/1/1\n"509 u"**ct/1/1\n"
499 "- testfiles/select/1\n"510 u"- testfiles/select/1\n"
500 "- **"])511 u"- **"])
501512
502 def test_include_filelist_double_asterisk_3(self):513 def test_include_filelist_double_asterisk_3(self):
503 """Identical to test_filelist, but with the exclude 'testfiles/select' replaced with '**'"""514 """Identical to test_filelist, but with the exclude 'testfiles/select' replaced with '**'"""
504 self.ParseTest([("--include-filelist", "file")],515 self.ParseTest([(u"--include-filelist", u"file")],
505 [(), ('1',), ('1', '1'), ('1', '1', '2'),516 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
506 ('1', '1', '3')],517 (u"1", u"1", u"3")],
507 ["- **/1/1/1\n"518 [u"- **/1/1/1\n"
508 "testfiles/select/1/1\n"519 u"testfiles/select/1/1\n"
509 "- testfiles/select/1\n"520 u"- testfiles/select/1\n"
510 "- **"])521 u"- **"])
511522
512 def test_include_filelist_double_asterisk_4(self):523 def test_include_filelist_double_asterisk_4(self):
513 """Identical to test_filelist, but with the include 'testfiles/select' replaced with '**'"""524 """Identical to test_filelist, but with the include 'testfiles/select' replaced with '**'"""
514 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)525 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
515 self.ParseTest([("--include-filelist", "file")],526 self.ParseTest([(u"--include-filelist", u"file")],
516 [(), ('1',), ('1', '1'), ('1', '1', '2'),527 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
517 ('1', '1', '3')],528 (u"1", u"1", u"3")],
518 ["- testfiles/select/1/1/1\n"529 [u"- testfiles/select/1/1/1\n"
519 "**t/1/1\n"530 u"**t/1/1\n"
520 "- testfiles/select/1\n"531 u"- testfiles/select/1\n"
521 "- **"])532 u"- **"])
522533
523 def test_include_filelist_double_asterisk_5(self):534 def test_include_filelist_double_asterisk_5(self):
524 """Identical to test_filelist, but with all 'testfiles/select's replaced with '**'"""535 """Identical to test_filelist, but with all 'testfiles/select's replaced with '**'"""
525 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)536 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
526 self.ParseTest([("--include-filelist", "file")],537 self.ParseTest([(u"--include-filelist", u"file")],
527 [(), ('1',), ('1', '1'), ('1', '1', '2'),538 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
528 ('1', '1', '3')],539 (u"1", u"1", u"3")],
529 ["- **/1/1/1\n"540 [u"- **/1/1/1\n"
530 "**t/1/1\n"541 u"**t/1/1\n"
531 "- **t/1\n"542 u"- **t/1\n"
532 "- **"])543 u"- **"])
533544
534 def test_include_filelist_trailing_slashes(self):545 def test_include_filelist_trailing_slashes(self):
535 """Filelist glob test similar to globbing filelist, but with trailing slashes"""546 """Filelist glob test similar to globbing filelist, but with trailing slashes"""
536 self.ParseTest([("--include-filelist", "file")],547 self.ParseTest([(u"--include-filelist", u"file")],
537 [(), ('1',), ('1', '1'), ('1', '1', '2'),548 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
538 ('1', '1', '3')],549 (u"1", u"1", u"3")],
539 ["- testfiles/select/1/1/1/\n"550 [u"- testfiles/select/1/1/1/\n"
540 "testfiles/select/1/1/\n"551 u"testfiles/select/1/1/\n"
541 "- testfiles/select/1/\n"552 u"- testfiles/select/1/\n"
542 "- **"])553 u"- **"])
543554
544 def test_include_filelist_trailing_slashes_and_single_asterisks(self):555 def test_include_filelist_trailing_slashes_and_single_asterisks(self):
545 """Filelist glob test similar to globbing filelist, but with trailing slashes and single asterisks"""556 """Filelist glob test similar to globbing filelist, but with trailing slashes and single asterisks"""
546 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)557 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
547 self.ParseTest([("--include-filelist", "file")],558 self.ParseTest([(u"--include-filelist", u"file")],
548 [(), ('1',), ('1', '1'), ('1', '1', '2'),559 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
549 ('1', '1', '3')],560 (u"1", u"1", u"3")],
550 ["- */select/1/1/1/\n"561 [u"- */select/1/1/1/\n"
551 "testfiles/select/1/1/\n"562 u"testfiles/select/1/1/\n"
552 "- testfiles/*/1/\n"563 u"- testfiles/*/1/\n"
553 "- **"])564 u"- **"])
554565
555 def test_include_filelist_trailing_slashes_and_double_asterisks(self):566 def test_include_filelist_trailing_slashes_and_double_asterisks(self):
556 """Filelist glob test similar to globbing filelist, but with trailing slashes and double asterisks"""567 """Filelist glob test similar to globbing filelist, but with trailing slashes and double asterisks"""
557 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)568 # Regression test for Bug #932482 (https://bugs.launchpad.net/duplicity/+bug/932482)
558 self.ParseTest([("--include-filelist", "file")],569 self.ParseTest([(u"--include-filelist", u"file")],
559 [(), ('1',), ('1', '1'), ('1', '1', '2'),570 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
560 ('1', '1', '3')],571 (u"1", u"1", u"3")],
561 ["- **/1/1/1/\n"572 [u"- **/1/1/1/\n"
562 "testfiles/select/1/1/\n"573 u"testfiles/select/1/1/\n"
563 "- **t/1/\n"574 u"- **t/1/\n"
564 "- **"])575 u"- **"])
565576
566 def test_filelist_null_separator(self):577 def test_filelist_null_separator(self):
567 """test_filelist, but with null_separator set"""578 """test_filelist, but with null_separator set"""
568 self.set_global('null_separator', 1)579 self.set_global(u"null_separator", 1)
569 self.ParseTest([("--include-filelist", "file")],580 self.ParseTest([(u"--include-filelist", u"file")],
570 [(), ('1',), ('1', '1'), ('1', '1', '2'),581 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
571 ('1', '1', '3')],582 (u"1", u"1", u"3")],
572 ["\0- testfiles/select/1/1/1\0testfiles/select/1/1\0- testfiles/select/1\0- **\0"])583 [u"\0- testfiles/select/1/1/1\0testfiles/select/1/1\0- testfiles/select/1\0- **\0"])
573584
574 def test_exclude_filelist(self):585 def test_exclude_filelist(self):
575 """Exclude version of test_filelist"""586 """Exclude version of test_filelist"""
576 self.ParseTest([("--exclude-filelist", "file")],587 self.ParseTest([(u"--exclude-filelist", u"file")],
577 [(), ('1',), ('1', '1'), ('1', '1', '2'),588 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
578 ('1', '1', '3')],589 (u"1", u"1", u"3")],
579 ["testfiles/select/1/1/1\n"590 [u"testfiles/select/1/1/1\n"
580 "+ testfiles/select/1/1\n"591 u"+ testfiles/select/1/1\n"
581 "testfiles/select/1\n"592 u"testfiles/select/1\n"
582 "- **"])593 u"- **"])
583594
584 def test_exclude_filelist_asterisk_1(self):595 def test_exclude_filelist_asterisk_1(self):
585 """Exclude version of test_include_filelist_asterisk"""596 """Exclude version of test_include_filelist_asterisk"""
586 self.ParseTest([("--exclude-filelist", "file")],597 self.ParseTest([(u"--exclude-filelist", u"file")],
587 [(), ('1',), ('1', '1'), ('1', '1', '1'),598 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"1"),
588 ('1', '1', '2'), ('1', '1', '3')],599 (u"1", u"1", u"2"), (u"1", u"1", u"3")],
589 ["+ */select/1/1\n"600 [u"+ */select/1/1\n"
590 "- **"])601 u"- **"])
591602
592 def test_exclude_filelist_asterisk_2(self):603 def test_exclude_filelist_asterisk_2(self):
593 """Identical to test_exclude_filelist, but with the exclude 'select' replaced with '*'"""604 """Identical to test_exclude_filelist, but with the exclude "select" replaced with '*'"""
594 self.ParseTest([("--exclude-filelist", "file")],605 self.ParseTest([(u"--exclude-filelist", u"file")],
595 [(), ('1',), ('1', '1'), ('1', '1', '2'),606 [(), (u"1",), (u"1", "1"), (u"1", u"1", u"2"),
596 ('1', '1', '3')],607 (u"1", u"1", u"3")],
597 ["testfiles/*/1/1/1\n"608 [u"testfiles/*/1/1/1\n"
598 "+ testfiles/select/1/1\n"609 u"+ testfiles/select/1/1\n"
599 "testfiles/select/1\n"610 u"testfiles/select/1\n"
600 "- **"])611 u"- **"])
601612
602 def test_exclude_filelist_asterisk_3(self):613 def test_exclude_filelist_asterisk_3(self):
603 """Identical to test_exclude_filelist, but with the include 'select' replaced with '*'"""614 """Identical to test_exclude_filelist, but with the include "select" replaced with '*'"""
604 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)615 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
605 self.ParseTest([("--exclude-filelist", "file")],616 self.ParseTest([(u"--exclude-filelist", u"file")],
606 [(), ('1',), ('1', '1'), ('1', '1', '2'),617 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
607 ('1', '1', '3')],618 (u"1", u"1", u"3")],
608 ["testfiles/select/1/1/1\n"619 [u"testfiles/select/1/1/1\n"
609 "+ testfiles/*/1/1\n"620 u"+ testfiles/*/1/1\n"
610 "testfiles/select/1\n"621 u"testfiles/select/1\n"
611 "- **"])622 u"- **"])
612623
613 def test_exclude_filelist_asterisk_4(self):624 def test_exclude_filelist_asterisk_4(self):
614 """Identical to test_exclude_filelist, but with numerous excluded folders replaced with '*'"""625 """Identical to test_exclude_filelist, but with numerous excluded folders replaced with '*'"""
615 self.ParseTest([("--exclude-filelist", "file")],626 self.ParseTest([(u"--exclude-filelist", u"file")],
616 [(), ('1',), ('1', '1'), ('1', '1', '2'),627 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
617 ('1', '1', '3')],628 (u"1", u"1", u"3")],
618 ["*/select/1/1/1\n"629 [u"*/select/1/1/1\n"
619 "+ testfiles/select/1/1\n"630 u"+ testfiles/select/1/1\n"
620 "*/*/1\n"631 u"*/*/1\n"
621 "- **"])632 u"- **"])
622633
623 def test_exclude_filelist_asterisk_5(self):634 def test_exclude_filelist_asterisk_5(self):
624 """Identical to test_exclude_filelist, but with numerous included/excluded folders replaced with '*'"""635 """Identical to test_exclude_filelist, but with numerous included/excluded folders replaced with '*'"""
625 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)636 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
626 self.ParseTest([("--exclude-filelist", "file")],637 self.ParseTest([(u"--exclude-filelist", u"file")],
627 [(), ('1',), ('1', '1'), ('1', '1', '2'),638 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
628 ('1', '1', '3')],639 (u"1", u"1", u"3")],
629 ["*/select/1/1/1\n"640 [u"*/select/1/1/1\n"
630 "+ */*/1/1\n"641 u"+ */*/1/1\n"
631 "*/*/1\n"642 u"*/*/1\n"
632 "- **"])643 u"- **"])
633644
634 def test_exclude_filelist_double_asterisk(self):645 def test_exclude_filelist_double_asterisk(self):
635 """Identical to test_exclude_filelist, but with all included/excluded folders replaced with '**'"""646 """Identical to test_exclude_filelist, but with all included/excluded folders replaced with '**'"""
636 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)647 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
637 self.ParseTest([("--exclude-filelist", "file")],648 self.ParseTest([(u"--exclude-filelist", u"file")],
638 [(), ('1',), ('1', '1'), ('1', '1', '2'),649 [(), (u"1",), (u"1", u"1"), (u"1", u"1", u"2"),
639 ('1', '1', '3')],650 (u"1", u"1", u"3")],
640 ["**/1/1/1\n"651 [u"**/1/1/1\n"
641 "+ **t/1/1\n"652 u"+ **t/1/1\n"
642 "**t/1\n"653 u"**t/1\n"
643 "- **"])654 u"- **"])
644655
645 def test_exclude_filelist_single_asterisk_at_beginning(self):656 def test_exclude_filelist_single_asterisk_at_beginning(self):
646 """Exclude filelist testing limited functionality of functional test"""657 """Exclude filelist testing limited functionality of functional test"""
647 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)658 # Regression test for Bug #884371 (https://bugs.launchpad.net/duplicity/+bug/884371)
648 self.root = Path("testfiles/select/1")659 self.root = Path(u"testfiles/select/1")
649 self.ParseTest([("--exclude-filelist", "file")],660 self.ParseTest([(u"--exclude-filelist", u"file")],
650 [(), ('2',), ('2', '1')],661 [(), (u"2",), (u"2", u"1")],
651 ["+ */select/1/2/1\n"662 [u"+ */select/1/2/1\n"
652 "- testfiles/select/1/2\n"663 u"- testfiles/select/1/2\n"
653 "- testfiles/*/1/1\n"664 u"- testfiles/*/1/1\n"
654 "- testfiles/select/1/3"])665 u"- testfiles/select/1/3"])
655666
656 def test_commandline_asterisks_double_both(self):667 def test_commandline_asterisks_double_both(self):
657 """Unit test the functional test TestAsterisks.test_commandline_asterisks_double_both"""668 """Unit test the functional test TestAsterisks.test_commandline_asterisks_double_both"""
658 self.root = Path("testfiles/select/1")669 self.root = Path(u"testfiles/select/1")
659 self.ParseTest([("--include", "**/1/2/1"),670 self.ParseTest([(u"--include", u"**/1/2/1"),
660 ("--exclude", "**t/1/2"),671 (u"--exclude", u"**t/1/2"),
661 ("--exclude", "**t/1/1"),672 (u"--exclude", u"**t/1/1"),
662 ("--exclude", "**t/1/3")],673 (u"--exclude", u"**t/1/3")],
663 [(), ('2',), ('2', '1')])674 [(), (u"2",), (u"2", u"1")])
664675
665 def test_includes_files(self):676 def test_includes_files(self):
666 """Unit test the functional test test_includes_files"""677 """Unit test the functional test test_includes_files"""
667 # Test for Bug 1624725678 # Test for Bug 1624725
668 # https://bugs.launchpad.net/duplicity/+bug/1624725679 # https://bugs.launchpad.net/duplicity/+bug/1624725
669 self.root = Path("testfiles/select2/1/1sub1")680 self.root = Path(u"testfiles/select2/1/1sub1")
670 self.ParseTest([("--include", "testfiles/select2/1/1sub1/1sub1sub1"),681 self.ParseTest([(u"--include", u"testfiles/select2/1/1sub1/1sub1sub1"),
671 ("--exclude", "**")],682 (u"--exclude", u"**")],
672 [(), ('1sub1sub1',), ('1sub1sub1',683 [(), (u"1sub1sub1",), (u"1sub1sub1",
673 '1sub1sub1_file.txt')])684 u"1sub1sub1_file.txt")])
674685
675 def test_includes_files_trailing_slash(self):686 def test_includes_files_trailing_slash(self):
676 """Unit test the functional test test_includes_files_trailing_slash"""687 """Unit test the functional test test_includes_files_trailing_slash"""
677 # Test for Bug 1624725688 # Test for Bug 1624725
678 # https://bugs.launchpad.net/duplicity/+bug/1624725689 # https://bugs.launchpad.net/duplicity/+bug/1624725
679 self.root = Path("testfiles/select2/1/1sub1")690 self.root = Path(u"testfiles/select2/1/1sub1")
680 self.ParseTest([("--include", "testfiles/select2/1/1sub1/1sub1sub1/"),691 self.ParseTest([(u"--include", u"testfiles/select2/1/1sub1/1sub1sub1/"),
681 ("--exclude", "**")],692 (u"--exclude", u"**")],
682 [(), ('1sub1sub1',), ('1sub1sub1',693 [(), (u"1sub1sub1",), (u"1sub1sub1",
683 '1sub1sub1_file.txt')])694 u"1sub1sub1_file.txt")])
684695
685 def test_includes_files_trailing_slash_globbing_chars(self):696 def test_includes_files_trailing_slash_globbing_chars(self):
686 """Unit test functional test_includes_files_trailing_slash_globbing_chars"""697 """Unit test functional test_includes_files_trailing_slash_globbing_chars"""
687 # Test for Bug 1624725698 # Test for Bug 1624725
688 # https://bugs.launchpad.net/duplicity/+bug/1624725699 # https://bugs.launchpad.net/duplicity/+bug/1624725
689 self.root = Path("testfiles/select2/1/1sub1")700 self.root = Path(u"testfiles/select2/1/1sub1")
690 self.ParseTest([("--include", "testfiles/s?lect2/1/1sub1/1sub1sub1/"),701 self.ParseTest([(u"--include", u"testfiles/s?lect2/1/1sub1/1sub1sub1/"),
691 ("--exclude", "**")],702 (u"--exclude", u"**")],
692 [(), ('1sub1sub1',), ('1sub1sub1',703 [(), (u"1sub1sub1",), (u"1sub1sub1",
693 '1sub1sub1_file.txt')])704 u"1sub1sub1_file.txt")])
694705
695 def test_glob(self):706 def test_glob(self):
696 """Test globbing expression"""707 """Test globbing expression"""
697 self.ParseTest([("--exclude", "**[3-5]"),708 self.ParseTest([(u"--exclude", u"**[3-5]"),
698 ("--include", "testfiles/select/1"),709 (u"--include", u"testfiles/select/1"),
699 ("--exclude", "**")],710 (u"--exclude", u"**")],
700 [(), ('1',), ('1', '1'),711 [(), (u"1",), (u"1", u"1"),
701 ('1', '1', '1'), ('1', '1', '2'),712 (u"1", u"1", u"1"), (u"1", u"1", u"2"),
702 ('1', '2'), ('1', '2', '1'), ('1', '2', '2')])713 (u"1", u"2"), (u"1", u"2", u"1"), (u"1", u"2", u"2")])
703 self.ParseTest([("--include", "testfiles/select**/2"),714 self.ParseTest([(u"--include", u"testfiles/select**/2"),
704 ("--exclude", "**")],715 (u"--exclude", u"**")],
705 [(), ('1',), ('1', '1'),716 [(), (u"1",), (u"1", u"1"),
706 ('1', '1', '2'),717 (u"1", u"1", u"2"),
707 ('1', '2'),718 (u"1", u"2"),
708 ('1', '2', '1'), ('1', '2', '2'), ('1', '2', '3'),719 (u"1", u"2", u"1"), (u"1", u"2", u"2"), (u"1", u"2", u"3"),
709 ('1', '3'),720 (u"1", u"3"),
710 ('1', '3', '2'),721 (u"1", u"3", u"2"),
711 ('2',), ('2', '1'),722 (u"2",), (u"2", u"1"),
712 ('2', '1', '1'), ('2', '1', '2'), ('2', '1', '3'),723 (u"2", u"1", u"1"), (u"2", u"1", u"2"), (u"2", u"1", u"3"),
713 ('2', '2'),724 (u"2", u"2"),
714 ('2', '2', '1'), ('2', '2', '2'), ('2', '2', '3'),725 (u"2", u"2", u"1"), (u"2", u"2", u"2"), (u"2", u"2", u"3"),
715 ('2', '3'),726 (u"2", u"3"),
716 ('2', '3', '1'), ('2', '3', '2'), ('2', '3', '3'),727 (u"2", u"3", u"1"), (u"2", u"3", u"2"), (u"2", u"3", u"3"),
717 ('3',), ('3', '1'),728 (u"3",), (u"3", u"1"),
718 ('3', '1', '2'),729 (u"3", u"1", u"2"),
719 ('3', '2'),730 (u"3", u"2"),
720 ('3', '2', '1'), ('3', '2', '2'), ('3', '2', '3'),731 (u"3", u"2", u"1"), (u"3", u"2", u"2"), (u"3", u"2", u"3"),
721 ('3', '3'),732 (u"3", u"3"),
722 ('3', '3', '2')])733 (u"3", u"3", u"2")])
723734
724 def test_filelist2(self):735 def test_filelist2(self):
725 """Filelist glob test similar to above testGlob"""736 """Filelist glob test similar to above testGlob"""
726 self.ParseTest([("--exclude-filelist", "asoeuth")],737 self.ParseTest([(u"--exclude-filelist", u"asoeuth")],
727 [(), ('1',), ('1', '1'),738 [(), (u"1",), (u"1", u"1"),
728 ('1', '1', '1'), ('1', '1', '2'),739 (u"1", u"1", u"1"), (u"1", u"1", u"2"),
729 ('1', '2'), ('1', '2', '1'), ('1', '2', '2')],740 (u"1", u"2"), (u"1", u"2", u"1"), (u"1", u"2", u"2")],
730 ["""741 [u"""
731**[3-5]742**[3-5]
732+ testfiles/select/1743+ testfiles/select/1
733**744**
734"""])745"""])
735 self.ParseTest([("--include-filelist", "file")],746 self.ParseTest([(u"--include-filelist", u"file")],
736 [(), ('1',), ('1', '1'),747 [(), (u"1",), (u"1", u"1"),
737 ('1', '1', '2'),748 (u"1", u"1", u"2"),
738 ('1', '2'),749 (u"1", u"2"),
739 ('1', '2', '1'), ('1', '2', '2'), ('1', '2', '3'),750 (u"1", u"2", u"1"), (u"1", u"2", u"2"), (u"1", u"2", u"3"),
740 ('1', '3'),751 (u"1", u"3"),
741 ('1', '3', '2'),752 (u"1", u"3", u"2"),
742 ('2',), ('2', '1'),753 (u"2",), (u"2", u"1"),
743 ('2', '1', '1'), ('2', '1', '2'), ('2', '1', '3'),754 (u"2", u"1", u"1"), (u"2", u"1", u"2"), (u"2", u"1", u"3"),
744 ('2', '2'),755 (u"2", u"2"),
745 ('2', '2', '1'), ('2', '2', '2'), ('2', '2', '3'),756 (u"2", u"2", u"1"), (u"2", u"2", u"2"), (u"2", u"2", u"3"),
746 ('2', '3'),757 (u"2", u"3"),
747 ('2', '3', '1'), ('2', '3', '2'), ('2', '3', '3'),758 (u"2", u"3", u"1"), (u"2", u"3", u"2"), (u"2", u"3", u"3"),
748 ('3',), ('3', '1'),759 (u"3",), (u"3", u"1"),
749 ('3', '1', '2'),760 (u"3", u"1", u"2"),
750 ('3', '2'),761 (u"3", u"2"),
751 ('3', '2', '1'), ('3', '2', '2'), ('3', '2', '3'),762 (u"3", u"2", u"1"), (u"3", u"2", u"2"), (u"3", u"2", u"3"),
752 ('3', '3'),763 (u"3", u"3"),
753 ('3', '3', '2')],764 (u"3", u"3", u"2")],
754 ["""765 [u"""
755testfiles/select**/2766testfiles/select**/2
756- **767- **
757"""])768"""])
758769
759 def test_glob2(self):770 def test_glob2(self):
760 """Test more globbing functions"""771 """Test more globbing functions"""
761 self.ParseTest([("--include", "testfiles/select/*foo*/p*"),772 self.ParseTest([(u"--include", u"testfiles/select/*foo*/p*"),
762 ("--exclude", "**")],773 (u"--exclude", u"**")],
763 [(), ('efools',), ('efools', 'ping'),774 [(), (u"efools",), (u"efools", u"ping"),
764 ('foobar',), ('foobar', 'pong')])775 (u"foobar",), (u"foobar", u"pong")])
765 self.ParseTest([("--exclude", "testfiles/select/1/1/*"),776 self.ParseTest([(u"--exclude", u"testfiles/select/1/1/*"),
766 ("--exclude", "testfiles/select/1/2/**"),777 (u"--exclude", u"testfiles/select/1/2/**"),
767 ("--exclude", "testfiles/select/1/3**"),778 (u"--exclude", u"testfiles/select/1/3**"),
768 ("--include", "testfiles/select/1"),779 (u"--include", u"testfiles/select/1"),
769 ("--exclude", "**")],780 (u"--exclude", u"**")],
770 [(), ('1',), ('1', '1'), ('1', '2')])781 [(), (u"1",), (u"1", u"1"), (u"1", u"2")])
771782
772 def test_glob3(self):783 def test_glob3(self):
773 """ regression test for bug 25230 """784 """ regression test for bug 25230 """
774 self.ParseTest([("--include", "testfiles/select/**1"),785 self.ParseTest([(u"--include", u"testfiles/select/**1"),
775 ("--include", "testfiles/select/**2"),786 (u"--include", u"testfiles/select/**2"),
776 ("--exclude", "**")],787 (u"--exclude", u"**")],
777 [(), ('1',), ('1', '1'),788 [(), (u"1",), (u"1", u"1"),
778 ('1', '1', '1'), ('1', '1', '2'), ('1', '1', '3'),789 (u"1", u"1", u"1"), (u"1", u"1", u"2"), (u"1", u"1", u"3"),
779 ('1', '2'),790 (u"1", u"2"),
780 ('1', '2', '1'), ('1', '2', '2'), ('1', '2', '3'),791 (u"1", u"2", u"1"), (u"1", u"2", u"2"), (u"1", u"2", u"3"),
781 ('1', '3'),792 (u"1", u"3"),
782 ('1', '3', '1'), ('1', '3', '2'), ('1', '3', '3'),793 (u"1", u"3", u"1"), (u"1", u"3", u"2"), (u"1", u"3", u"3"),
783 ('2',), ('2', '1'),794 (u"2",), (u"2", u"1"),
784 ('2', '1', '1'), ('2', '1', '2'), ('2', '1', '3'),795 (u"2", u"1", u"1"), (u"2", u"1", u"2"), (u"2", u"1", u"3"),
785 ('2', '2'),796 (u"2", u"2"),
786 ('2', '2', '1'), ('2', '2', '2'), ('2', '2', '3'),797 (u"2", u"2", u"1"), (u"2", u"2", u"2"), (u"2", u"2", u"3"),
787 ('2', '3'),798 (u"2", u"3"),
788 ('2', '3', '1'), ('2', '3', '2'), ('2', '3', '3'),799 (u"2", u"3", u"1"), (u"2", u"3", u"2"), (u"2", u"3", u"3"),
789 ('3',), ('3', '1'),800 (u"3",), (u"3", u"1"),
790 ('3', '1', '1'), ('3', '1', '2'), ('3', '1', '3'),801 (u"3", u"1", u"1"), (u"3", u"1", u"2"), (u"3", u"1", u"3"),
791 ('3', '2'),802 (u"3", u"2"),
792 ('3', '2', '1'), ('3', '2', '2'), ('3', '2', '3'),803 (u"3", u"2", u"1"), (u"3", u"2", u"2"), (u"3", u"2", u"3"),
793 ('3', '3'),804 (u"3", u"3"),
794 ('3', '3', '1'), ('3', '3', '2')])805 (u"3", u"3", u"1"), (u"3", u"3", u"2")])
795806
796 def test_alternate_root(self):807 def test_alternate_root(self):
797 """Test select with different root"""808 """Test select with different root"""
798 self.root = Path("testfiles/select/1")809 self.root = Path(u"testfiles/select/1")
799 self.ParseTest([("--exclude", "testfiles/select/1/[23]")],810 self.ParseTest([(u"--exclude", u"testfiles/select/1/[23]")],
800 [(), ('1',), ('1', '1'), ('1', '2'), ('1', '3')])811 [(), (u"1",), (u"1", u"1"), (u"1", u"2"), (u"1", u"3")])
801812
802 self.root = Path("/")813 self.root = Path(u"/")
803 self.ParseTest([("--exclude", "/tmp/*"),814 self.ParseTest([(u"--exclude", u"/tmp/*"),
804 ("--include", "/tmp"),815 (u"--include", u"/tmp"),
805 ("--exclude", "/")],816 (u"--exclude", u"/")],
806 [(), ("tmp",)])817 [(), (u"tmp",)])
807818
808 def test_exclude_after_scan(self):819 def test_exclude_after_scan(self):
809 """Test select with an exclude after a pattern that would return a scan for that file"""820 """Test select with an exclude after a pattern that would return a scan for that file"""
810 self.root = Path("testfiles/select2/3")821 self.root = Path(u"testfiles/select2/3")
811 self.ParseTest([("--include", "testfiles/select2/3/**file.txt"),822 self.ParseTest([(u"--include", u"testfiles/select2/3/**file.txt"),
812 ("--exclude", "testfiles/select2/3/3sub2"),823 (u"--exclude", u"testfiles/select2/3/3sub2"),
813 ("--include", "testfiles/select2/3/3sub1"),824 (u"--include", u"testfiles/select2/3/3sub1"),
814 ("--exclude", "**")],825 (u"--exclude", u"**")],
815 [(), ('3sub1',), ('3sub1', '3sub1sub1'), ('3sub1', '3sub1sub2'), ('3sub1', '3sub1sub3'),826 [(), (u"3sub1",), (u"3sub1", u"3sub1sub1"), (u"3sub1", u"3sub1sub2"), (u"3sub1", u"3sub1sub3"),
816 ('3sub3',), ('3sub3', '3sub3sub2'), ('3sub3', '3sub3sub2', '3sub3sub2_file.txt')])827 (u"3sub3",), (u"3sub3", u"3sub3sub2"), (u"3sub3", u"3sub3sub2", u"3sub3sub2_file.txt")])
817828
818 def test_include_exclude_basic(self):829 def test_include_exclude_basic(self):
819 """Test functional test test_include_exclude_basic as a unittest"""830 """Test functional test test_include_exclude_basic as a unittest"""
820 self.root = Path("testfiles/select2")831 self.root = Path(u"testfiles/select2")
821 self.ParseTest([("--include", "testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"),832 self.ParseTest([(u"--include", u"testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt"),
822 ("--exclude", "testfiles/select2/3/3sub3/3sub3sub2"),833 (u"--exclude", u"testfiles/select2/3/3sub3/3sub3sub2"),
823 ("--include", "testfiles/select2/3/3sub2/3sub2sub2"),834 (u"--include", u"testfiles/select2/3/3sub2/3sub2sub2"),
824 ("--include", "testfiles/select2/3/3sub3"),835 (u"--include", u"testfiles/select2/3/3sub3"),
825 ("--exclude", "testfiles/select2/3/3sub1"),836 (u"--exclude", u"testfiles/select2/3/3sub1"),
826 ("--exclude", "testfiles/select2/2/2sub1/2sub1sub3"),837 (u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub3"),
827 ("--exclude", "testfiles/select2/2/2sub1/2sub1sub2"),838 (u"--exclude", u"testfiles/select2/2/2sub1/2sub1sub2"),
828 ("--include", "testfiles/select2/2/2sub1"),839 (u"--include", u"testfiles/select2/2/2sub1"),
829 ("--exclude", "testfiles/select2/1/1sub3/1sub3sub2"),840 (u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub2"),
830 ("--exclude", "testfiles/select2/1/1sub3/1sub3sub1"),841 (u"--exclude", u"testfiles/select2/1/1sub3/1sub3sub1"),
831 ("--exclude", "testfiles/select2/1/1sub2/1sub2sub3"),842 (u"--exclude", u"testfiles/select2/1/1sub2/1sub2sub3"),
832 ("--include", "testfiles/select2/1/1sub2/1sub2sub1"),843 (u"--include", u"testfiles/select2/1/1sub2/1sub2sub1"),
833 ("--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"),844 (u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt"),
834 ("--exclude", "testfiles/select2/1/1sub1/1sub1sub2"),845 (u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub2"),
835 ("--exclude", "testfiles/select2/1/1sub2"),846 (u"--exclude", u"testfiles/select2/1/1sub2"),
836 ("--include", "testfiles/select2/1.py"),847 (u"--include", u"testfiles/select2/1.py"),
837 ("--include", "testfiles/select2/3"),848 (u"--include", u"testfiles/select2/3"),
838 ("--include", "testfiles/select2/1"),849 (u"--include", u"testfiles/select2/1"),
839 ("--exclude", "testfiles/select2/**")],850 (u"--exclude", u"testfiles/select2/**")],
840 self.expected_restored_tree)851 self.expected_restored_tree)
841852
842 def test_globbing_replacement(self):853 def test_globbing_replacement(self):
843 """Test functional test test_globbing_replacement as a unittest"""854 """Test functional test test_globbing_replacement as a unittest"""
844 self.root = Path("testfiles/select2")855 self.root = Path(u"testfiles/select2")
845 self.ParseTest([("--include", "testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt"),856 self.ParseTest([(u"--include", u"testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt"),
846 ("--exclude", "testfiles/select2/*/3s*1"),857 (u"--exclude", u"testfiles/select2/*/3s*1"),
847 ("--exclude", "testfiles/select2/**/2sub1sub3"),858 (u"--exclude", u"testfiles/select2/**/2sub1sub3"),
848 ("--exclude", "ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2"),859 (u"--exclude", u"ignorecase:testfiles/select2/2/2sub1/2Sub1Sub2"),
849 ("--include", "ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1"),860 (u"--include", u"ignorecase:testfiles/sel[w,u,e,q]ct2/2/2S?b1"),
850 ("--exclude", "testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2"),861 (u"--exclude", u"testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2"),
851 ("--exclude", "testfiles/select2/1/1sub[1-4]/1sub3sub1"),862 (u"--exclude", u"testfiles/select2/1/1sub[1-4]/1sub3sub1"),
852 ("--include", "testfiles/select2/1/1sub2/1sub2sub1"),863 (u"--include", u"testfiles/select2/1/1sub2/1sub2sub1"),
853 ("--exclude", "testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt"),864 (u"--exclude", u"testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt"),
854 ("--exclude", "testfiles/select2/1/1*1/1sub1sub2"),865 (u"--exclude", u"testfiles/select2/1/1*1/1sub1sub2"),
855 ("--exclude", "testfiles/select2/1/1sub2"),866 (u"--exclude", u"testfiles/select2/1/1sub2"),
856 ("--include", "testfiles/select[2-4]/*.py"),867 (u"--include", u"testfiles/select[2-4]/*.py"),
857 ("--include", "testfiles/*2/3"),868 (u"--include", u"testfiles/*2/3"),
858 ("--include", "**/select2/1"),869 (u"--include", u"**/select2/1"),
859 ("--exclude", "testfiles/select2/**")],870 (u"--exclude", u"testfiles/select2/**")],
860 self.expected_restored_tree)871 self.expected_restored_tree)
861872
873 def test_unicode_paths_non_globbing(self):
874 """Test functional test test_unicode_paths_non_globbing as a unittest"""
875 self.root = Path(u"testfiles/select-unicode")
876 self.ParseTest([(u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/Παράδειγμα/उदाहरण.txt"),
877 (u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/Παράδειγμα/דוגמא.txt"),
878 (u"--exclude", u"testfiles/select-unicode/прыклад/пример/例/მაგალითი/"),
879 (u"--include", u"testfiles/select-unicode/прыклад/пример/例/"),
880 (u"--exclude", u"testfiles/select-unicode/прыклад/пример/"),
881 (u"--include", u"testfiles/select-unicode/прыклад/"),
882 (u"--include", u"testfiles/select-unicode/օրինակ.txt"),
883 (u"--exclude", u"testfiles/select-unicode/**")],
884 [(), (u"прыклад",), (u"прыклад", u"пример"), (u"прыклад", u"пример", u"例"),
885 (u"прыклад", u"пример", u"例", u"Παράδειγμα"),
886 (u"прыклад", u"пример", u"例", u"Παράδειγμα", u"ઉદાહરણ.log"),
887 (u"прыклад", u"উদাহরণ"), (u"օրինակ.txt",)])
888
862889
863class TestGlobGetNormalSf(UnitTestCase):890class TestGlobGetNormalSf(UnitTestCase):
864 """Test glob parsing of the test_glob_get_normal_sf function. Indirectly test behaviour of glob_to_re."""891 """Test glob parsing of the test_glob_get_normal_sf function. Indirectly test behaviour of glob_to_re."""
@@ -877,152 +904,152 @@
877 path = Path(path)904 path = Path(path)
878 return selection_function(path)905 return selection_function(path)
879906
880 def include_glob_tester(self, path, glob_string, root_path="/"):907 def include_glob_tester(self, path, glob_string, root_path=u"/"):
881 return self.glob_tester(path, glob_string, 1, root_path)908 return self.glob_tester(path, glob_string, 1, root_path)
882909
883 def exclude_glob_tester(self, path, glob_string, root_path="/"):910 def exclude_glob_tester(self, path, glob_string, root_path=u"/"):
884 return self.glob_tester(path, glob_string, 0, root_path)911 return self.glob_tester(path, glob_string, 0, root_path)
885912
886 def test_glob_get_normal_sf_exclude(self):913 def test_glob_get_normal_sf_exclude(self):
887 """Test simple exclude."""914 """Test simple exclude."""
888 self.assertEqual(self.exclude_glob_tester("/testfiles/select2/3", "/testfiles/select2"), 0)915 self.assertEqual(self.exclude_glob_tester(u"/testfiles/select2/3", u"/testfiles/select2"), 0)
889 self.assertEqual(self.exclude_glob_tester("/testfiles/.git", "/testfiles"), 0)916 self.assertEqual(self.exclude_glob_tester(u"/testfiles/.git", u"/testfiles"), 0)
890917
891 def test_glob_get_normal_sf_exclude_root(self):918 def test_glob_get_normal_sf_exclude_root(self):
892 """Test simple exclude with / as the glob."""919 """Test simple exclude with / as the glob."""
893 self.assertEqual(self.exclude_glob_tester("/.git", "/"), 0)920 self.assertEqual(self.exclude_glob_tester(u"/.git", u"/"), 0)
894 self.assertEqual(self.exclude_glob_tester("/testfile", "/"), 0)921 self.assertEqual(self.exclude_glob_tester(u"/testfile", u"/"), 0)
895922
896 def test_glob_get_normal_sf_2(self):923 def test_glob_get_normal_sf_2(self):
897 """Test same behaviour as the functional test test_globbing_replacement."""924 """Test same behaviour as the functional test test_globbing_replacement."""
898 self.assertEqual(self.include_glob_tester("/testfiles/select2/3/3sub3/3sub3sub2/3sub3sub2_file.txt",
899 "/testfiles/select2/**/3sub3sub2/3sub3su?2_file.txt"), 1)
900 self.assertEqual(self.include_glob_tester("/testfiles/select2/3/3sub1", "/testfiles/select2/*/3s*1"), 1)
901 self.assertEqual(self.include_glob_tester("/testfiles/select2/2/2sub1/2sub1sub3",
902 "/testfiles/select2/**/2sub1sub3"), 1)
903 self.assertEqual(self.include_glob_tester("/testfiles/select2/2/2sub1",
904 "/testfiles/sel[w,u,e,q]ct2/2/2s?b1"), 1)
905 self.assertEqual(self.include_glob_tester("/testfiles/select2/1/1sub3/1sub3sub2",
906 "/testfiles/select2/1/1sub3/1s[w,u,p,q]b3sub2"), 1)
907 self.assertEqual(self.exclude_glob_tester("/testfiles/select2/1/1sub3/1sub3sub1",
908 "/testfiles/select2/1/1sub[1-4]/1sub3sub1"), 0)
909 self.assertEqual(self.include_glob_tester("/testfiles/select2/1/1sub2/1sub2sub1",
910 "/testfiles/select2/*/1sub2/1s[w,u,p,q]b2sub1"), 1)
911 self.assertEqual(self.include_glob_tester("/testfiles/select2/1/1sub1/1sub1sub3/1sub1sub3_file.txt",
912 "/testfiles/select2/1/1sub1/1sub1sub3/1su?1sub3_file.txt"), 1)
913 self.assertEqual(self.exclude_glob_tester("/testfiles/select2/1/1sub1/1sub1sub2",
914 "/testfiles/select2/1/1*1/1sub1sub2"), 0)
915 self.assertEqual(self.include_glob_tester("/testfiles/select2/1/1sub2", "/testfiles/select2/1/1sub2"), 1)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches