Thread: [cedar-backup-svn] SF.net SVN: cedar-backup: [913] cedar-backup2/trunk (Page 3)
Brought to you by:
pronovic
|
From: <pro...@us...> - 2008-04-28 02:38:12
|
Revision: 913
http://cedar-backup.svn.sourceforge.net/cedar-backup/?rev=913&view=rev
Author: pronovic
Date: 2008-04-27 19:38:06 -0700 (Sun, 27 Apr 2008)
Log Message:
-----------
Implement the dereferenceLink() function
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/util.py
cedar-backup2/trunk/test/utiltests.py
Modified: cedar-backup2/trunk/CedarBackup2/util.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/util.py 2008-04-26 19:25:49 UTC (rev 912)
+++ cedar-backup2/trunk/CedarBackup2/util.py 2008-04-28 02:38:06 UTC (rev 913)
@@ -1987,3 +1987,22 @@
os.environ[LANG_VAR] = DEFAULT_LANGUAGE
return os.environ.copy()
+
+#############################
+# dereferenceLink() function
+#############################
+
+def dereferenceLink(path, absolute=True):
+ """
+ Deference a soft link, optionally normalizing it to an absolute path.
+ @param path: Path of link to dereference
+ @param absolute: Whether to normalize the result to an absolute path
+ @return: Dereferenced path, or original path if original is not a link.
+ """
+ if os.path.islink(path):
+ result = os.readlink(path)
+ if absolute and not os.path.isabs(result):
+ result = os.path.abspath(os.path.join(os.path.dirname(path), result))
+ return result
+ return path
+
Modified: cedar-backup2/trunk/test/utiltests.py
===================================================================
--- cedar-backup2/trunk/test/utiltests.py 2008-04-26 19:25:49 UTC (rev 912)
+++ cedar-backup2/trunk/test/utiltests.py 2008-04-28 02:38:06 UTC (rev 913)
@@ -82,13 +82,14 @@
import logging
from os.path import isdir
-from CedarBackup2.testutil import findResources, removedir, platformHasEcho, platformWindows, captureOutput
+from CedarBackup2.testutil import findResources, removedir, extractTar, buildPath, captureOutput
+from CedarBackup2.testutil import platformHasEcho, platformWindows, platformSupportsLinks
from CedarBackup2.util import UnorderedList, AbsolutePathList, ObjectTypeList
from CedarBackup2.util import RestrictedContentList, RegexMatchList, RegexList
from CedarBackup2.util import DirectedGraph, PathResolverSingleton, Diagnostics
from CedarBackup2.util import sortDict, resolveCommand, executeCommand, getFunctionReference, encodePath
from CedarBackup2.util import convertSize, UNIT_BYTES, UNIT_SECTORS, UNIT_KBYTES, UNIT_MBYTES, UNIT_GBYTES
-from CedarBackup2.util import displayBytes, deriveDayOfWeek, isStartOfWeek
+from CedarBackup2.util import displayBytes, deriveDayOfWeek, isStartOfWeek, dereferenceLink
from CedarBackup2.util import buildNormalizedPath, splitCommandLine, nullDevice
@@ -97,7 +98,7 @@
#######################################################################
DATA_DIRS = [ "./data", "./test/data" ]
-RESOURCES = [ "lotsoflines.py", ]
+RESOURCES = [ "lotsoflines.py", "tree10.tar.gz", ]
#######################################################################
@@ -2137,7 +2138,16 @@
except: pass
return name
+ def extractTar(self, tarname):
+ """Extracts a tarfile with a particular name."""
+ extractTar(self.tmpdir, self.resources['%s.tar.gz' % tarname])
+ def buildPath(self, components):
+ """Builds a complete search path from a list of components."""
+ components.insert(0, self.tmpdir)
+ return buildPath(components)
+
+
##################
# Test sortDict()
##################
@@ -3912,6 +3922,105 @@
self.failUnlessEqual(["cback", "'this", "is", "a", "really", "long", "single-quoted", "argument'", ], result)
+ #########################
+ # Test dereferenceLink()
+ #########################
+
+ def testDereferenceLink_001(self):
+ """
+ Test for a path that is a link, absolute=false.
+ """
+ self.extractTar("tree10")
+ path = self.buildPath(["tree10", "link002"])
+ if platformSupportsLinks():
+ expected = "file002"
+ else:
+ expected = path
+ actual = dereferenceLink(path, absolute=False)
+ self.failUnlessEqual(expected, actual)
+
+ def testDereferenceLink_002(self):
+ """
+ Test for a path that is a link, absolute=true.
+ """
+ self.extractTar("tree10")
+ path = self.buildPath(["tree10", "link002"])
+ if platformSupportsLinks():
+ expected = self.buildPath(["tree10", "file002"])
+ else:
+ expected = path
+ actual = dereferenceLink(path)
+ self.failUnlessEqual(expected, actual)
+ actual = dereferenceLink(path, absolute=True)
+ self.failUnlessEqual(expected, actual)
+
+ def testDereferenceLink_003(self):
+ """
+ Test for a path that is a file (not a link), absolute=false.
+ """
+ self.extractTar("tree10")
+ path = self.buildPath(["tree10", "file001"])
+ expected = path
+ actual = dereferenceLink(path, absolute=False)
+ self.failUnlessEqual(expected, actual)
+
+ def testDereferenceLink_004(self):
+ """
+ Test for a path that is a file (not a link), absolute=true.
+ """
+ self.extractTar("tree10")
+ path = self.buildPath(["tree10", "file001"])
+ expected = path
+ actual = dereferenceLink(path)
+ self.failUnlessEqual(expected, actual)
+ actual = dereferenceLink(path, absolute=True)
+ self.failUnlessEqual(expected, actual)
+
+ def testDereferenceLink_005(self):
+ """
+ Test for a path that is a directory (not a link), absolute=false.
+ """
+ self.extractTar("tree10")
+ path = self.buildPath(["tree10", "dir001"])
+ expected = path
+ actual = dereferenceLink(path, absolute=False)
+ self.failUnlessEqual(expected, actual)
+
+ def testDereferenceLink_006(self):
+ """
+ Test for a path that is a directory (not a link), absolute=true.
+ """
+ self.extractTar("tree10")
+ path = self.buildPath(["tree10", "dir001"])
+ expected = path
+ actual = dereferenceLink(path)
+ self.failUnlessEqual(expected, actual)
+ actual = dereferenceLink(path, absolute=True)
+ self.failUnlessEqual(expected, actual)
+
+ def testDereferenceLink_007(self):
+ """
+ Test for a path that does not exist, absolute=false.
+ """
+ self.extractTar("tree10")
+ path = self.buildPath(["tree10", "blech"])
+ expected = path
+ actual = dereferenceLink(path, absolute=False)
+ self.failUnlessEqual(expected, actual)
+
+ def testDereferenceLink_008(self):
+ """
+ Test for a path that does not exist, absolute=true.
+ """
+ self.extractTar("tree10")
+ path = self.buildPath(["tree10", "blech"])
+ expected = path
+ actual = dereferenceLink(path)
+ self.failUnlessEqual(expected, actual)
+ actual = dereferenceLink(path, absolute=True)
+ self.failUnlessEqual(expected, actual)
+
+
#######################################################################
# Suite definition
#######################################################################
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2008-04-28 02:40:07
|
Revision: 914
http://cedar-backup.svn.sourceforge.net/cedar-backup/?rev=914&view=rev
Author: pronovic
Date: 2008-04-27 19:40:04 -0700 (Sun, 27 Apr 2008)
Log Message:
-----------
Add dereference flag to FilesystemList.addDirContents()
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/filesystem.py
cedar-backup2/trunk/Changelog
cedar-backup2/trunk/test/filesystemtests.py
Added Paths:
-----------
cedar-backup2/trunk/test/data/tree22.tar.gz
Modified: cedar-backup2/trunk/CedarBackup2/filesystem.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/filesystem.py 2008-04-28 02:38:06 UTC (rev 913)
+++ cedar-backup2/trunk/CedarBackup2/filesystem.py 2008-04-28 02:40:04 UTC (rev 914)
@@ -59,7 +59,7 @@
# Cedar Backup modules
from CedarBackup2.knapsack import firstFit, bestFit, worstFit, alternateFit
from CedarBackup2.util import AbsolutePathList, ObjectTypeList, UnorderedList, RegexList
-from CedarBackup2.util import removeKeys, displayBytes, calculateFileAge, encodePath
+from CedarBackup2.util import removeKeys, displayBytes, calculateFileAge, encodePath, dereferenceLink
########################################################################
@@ -358,7 +358,7 @@
logger.debug("Added directory to list: [%s]" % path)
return 1
- def addDirContents(self, path, recursive=True, addSelf=True, linkDepth=0):
+ def addDirContents(self, path, recursive=True, addSelf=True, linkDepth=0, dereference=False):
"""
Adds the contents of a directory to the list.
@@ -387,6 +387,9 @@
@note: The L{excludeDirs} flag only controls whether any given directory
path itself is added to the list once it has been discovered. It does
I{not} modify any behavior related to directory recursion.
+
+ @note: If you call this method I{on a link to a directory} that link will
+ never be dereferenced (it may, however, be followed).
@param path: Directory path whose contents should be added to the list
@type path: String representing a path on disk
@@ -400,6 +403,9 @@
@param linkDepth: Maximum depth of the tree at which soft links should be followed
@type linkDepth: Integer value, where zero means not to follow any soft links
+ @param dereference: Indicates whether soft links, if followed, should be dereferenced
+ @type dereference: Boolean value
+
@return: Number of items recursively added to the list
@raise ValueError: If path is not a directory or does not exist.
@@ -407,9 +413,9 @@
"""
path = encodePath(path)
path = normalizeDir(path)
- return self._addDirContentsInternal(path, addSelf, recursive, linkDepth)
+ return self._addDirContentsInternal(path, addSelf, recursive, linkDepth, dereference)
- def _addDirContentsInternal(self, path, includePath=True, recursive=True, linkDepth=0):
+ def _addDirContentsInternal(self, path, includePath=True, recursive=True, linkDepth=0, dereference=False):
"""
Internal implementation of C{addDirContents}.
@@ -433,10 +439,14 @@
gets a little confused (it has a link and a directory with the same
name).
+ @note: If you call this method I{on a link to a directory} that link will
+ never be dereferenced (it may, however, be followed).
+
@param path: Directory path whose contents should be added to the list.
@param includePath: Indicates whether to include the path as well as contents.
@param recursive: Indicates whether directory contents should be added recursively.
@param linkDepth: Depth of soft links that should be followed
+ @param dereference: Indicates whether soft links, if followed, should be dereferenced
@return: Number of items recursively added to the list
@@ -465,18 +475,31 @@
for entry in os.listdir(path):
entrypath = os.path.join(path, entry)
if os.path.isfile(entrypath):
+ if linkDepth > 0 and dereference:
+ derefpath = dereferenceLink(entrypath)
+ if derefpath != entrypath:
+ added += self.addFile(derefpath)
added += self.addFile(entrypath)
elif os.path.isdir(entrypath):
if os.path.islink(entrypath):
- if recursive and linkDepth > 0:
- newDepth = linkDepth - 1;
- added += self._addDirContentsInternal(entrypath, includePath=False, linkDepth=newDepth)
+ if recursive:
+ if linkDepth > 0:
+ newDepth = linkDepth - 1;
+ if dereference:
+ derefpath = dereferenceLink(entrypath)
+ if derefpath != entrypath:
+ added += self._addDirContentsInternal(derefpath, True, recursive, newDepth, dereference)
+ added += self.addDir(entrypath)
+ else:
+ added += self._addDirContentsInternal(entrypath, False, recursive, newDepth, dereference)
+ else:
+ added += self.addDir(entrypath)
else:
added += self.addDir(entrypath)
else:
if recursive:
newDepth = linkDepth - 1;
- added += self._addDirContentsInternal(entrypath, linkDepth=newDepth)
+ added += self._addDirContentsInternal(entrypath, True, recursive, newDepth, dereference)
else:
added += self.addDir(entrypath)
return added
@@ -1221,7 +1244,7 @@
# Add methods
##############
- def addDirContents(self, path, recursive=True, addSelf=True, linkDepth=0):
+ def addDirContents(self, path, recursive=True, addSelf=True, linkDepth=0, dereference=False):
"""
Adds the contents of a directory to the list.
@@ -1255,6 +1278,9 @@
path itself is added to the list once it has been discovered. It does
I{not} modify any behavior related to directory recursion.
+ @note: If you call this method I{on a link to a directory} that link will
+ never be dereferenced (it may, however, be followed).
+
@param path: Directory path whose contents should be added to the list
@type path: String representing a path on disk
@@ -1266,6 +1292,9 @@
@param linkDepth: Depth of soft links that should be followed
@type linkDepth: Integer value, where zero means not to follow any soft links
+ @param dereference: Indicates whether soft links, if followed, should be dereferenced
+ @type dereference: Boolean value
+
@return: Number of items recursively added to the list
@raise ValueError: If path is not a directory or does not exist.
@@ -1273,7 +1302,7 @@
"""
path = encodePath(path)
path = normalizeDir(path)
- return super(PurgeItemList, self)._addDirContentsInternal(path, False, recursive, linkDepth)
+ return super(PurgeItemList, self)._addDirContentsInternal(path, False, recursive, linkDepth, dereference)
##################
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2008-04-28 02:38:06 UTC (rev 913)
+++ cedar-backup2/trunk/Changelog 2008-04-28 02:40:04 UTC (rev 914)
@@ -1,3 +1,9 @@
+Version 2.18.0 unreleased
+
+ * Add the ability to dereference links when following them.
+ - Add util.dereferenceLink() function
+ - Add dereference flag to FilesystemList.addDirContents()
+
Version 2.17.1 26 Apr 2008
* Updated copyright statement slightly.
Added: cedar-backup2/trunk/test/data/tree22.tar.gz
===================================================================
(Binary files differ)
Property changes on: cedar-backup2/trunk/test/data/tree22.tar.gz
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: cedar-backup2/trunk/test/filesystemtests.py
===================================================================
--- cedar-backup2/trunk/test/filesystemtests.py 2008-04-28 02:38:06 UTC (rev 913)
+++ cedar-backup2/trunk/test/filesystemtests.py 2008-04-28 02:40:04 UTC (rev 914)
@@ -131,7 +131,7 @@
DATA_DIRS = [ "./data", "./test/data" ]
RESOURCES = [ "tree1.tar.gz", "tree2.tar.gz", "tree3.tar.gz", "tree4.tar.gz", "tree5.tar.gz",
"tree6.tar.gz", "tree7.tar.gz", "tree8.tar.gz", "tree9.tar.gz", "tree10.tar.gz",
- "tree11.tar.gz", "tree12.tar.gz", "tree13.tar.gz", ]
+ "tree11.tar.gz", "tree12.tar.gz", "tree13.tar.gz", "tree22.tar.gz", ]
INVALID_FILE = "bogus" # This file name should never exist
NOMATCH_PATH = "/something" # This path should never match something we put in a file list
@@ -4758,10 +4758,11 @@
self.extractTar("tree6")
path = self.buildPath(["tree6"])
fsList = FilesystemList()
- count = fsList.addDirContents(path, addSelf=False, linkDepth=1)
+ count = fsList.addDirContents(path, linkDepth=1)
if not platformSupportsLinks():
- self.failUnlessEqual(121, count)
- self.failUnlessEqual(121, len(fsList))
+ self.failUnlessEqual(122, count)
+ self.failUnlessEqual(122, len(fsList))
+ self.failUnless(self.buildPath([ "tree6", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", "dir001", ]) in fsList)
@@ -4884,8 +4885,9 @@
self.failUnless(self.buildPath([ "tree6", "file002", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "link001", ]) in fsList)
else:
- self.failUnlessEqual(164, count)
- self.failUnlessEqual(164, len(fsList))
+ self.failUnlessEqual(165, count)
+ self.failUnlessEqual(165, len(fsList))
+ self.failUnless(self.buildPath([ "tree6", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", "dir001", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", "dir002", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", "dir003", ]) in fsList)
@@ -5058,10 +5060,11 @@
self.extractTar("tree6")
path = self.buildPath(["tree6"])
fsList = FilesystemList()
- count = fsList.addDirContents(path, addSelf=False, linkDepth=2)
+ count = fsList.addDirContents(path, linkDepth=2)
if not platformSupportsLinks():
- self.failUnlessEqual(121, count)
- self.failUnlessEqual(121, len(fsList))
+ self.failUnlessEqual(122, count)
+ self.failUnlessEqual(122, len(fsList))
+ self.failUnless(self.buildPath([ "tree6" ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", "dir001", ]) in fsList)
@@ -5184,8 +5187,9 @@
self.failUnless(self.buildPath([ "tree6", "file002", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "link001", ]) in fsList)
else:
- self.failUnlessEqual(240, count)
- self.failUnlessEqual(240, len(fsList))
+ self.failUnlessEqual(241, count)
+ self.failUnlessEqual(241, len(fsList))
+ self.failUnless(self.buildPath([ "tree6" ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", "dir001", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", "dir002", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "dir001", "dir001", "dir003", ]) in fsList)
@@ -5427,7 +5431,462 @@
self.failUnless(self.buildPath([ "tree6", "file002", ]) in fsList)
self.failUnless(self.buildPath([ "tree6", "link001", ]) in fsList)
+ def testAddDirContents_093(self):
+ """
+ Attempt to add a directory with linkDepth=0, dereference=False.
+ """
+ self.extractTar("tree22")
+ path = self.buildPath(["tree22", "dir003", ])
+ fsList = FilesystemList()
+ count = fsList.addDirContents(path, linkDepth=0, dereference=False)
+ if not platformSupportsLinks():
+ pass
+ else:
+ self.failUnlessEqual(12, count)
+ self.failUnlessEqual(12, len(fsList))
+ self.failUnless(self.buildPath(["tree22", "dir003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", ]) in fsList)
+ def testAddDirContents_094(self):
+ """
+ Attempt to add a directory with linkDepth=1, dereference=False.
+ """
+ self.extractTar("tree22")
+ path = self.buildPath(["tree22", "dir003", ])
+ fsList = FilesystemList()
+ count = fsList.addDirContents(path, linkDepth=1, dereference=False)
+ if not platformSupportsLinks():
+ pass
+ else:
+ self.failUnlessEqual(16, count)
+ self.failUnlessEqual(16, len(fsList))
+ self.failUnless(self.buildPath(["tree22", "dir003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link002", ]) in fsList)
+
+ def testAddDirContents_095(self):
+ """
+ Attempt to add a directory with linkDepth=2, dereference=False.
+ """
+ self.extractTar("tree22")
+ path = self.buildPath(["tree22", "dir003", ])
+ fsList = FilesystemList()
+ count = fsList.addDirContents(path, linkDepth=2, dereference=False)
+ if not platformSupportsLinks():
+ pass
+ else:
+ self.failUnlessEqual(20, count)
+ self.failUnlessEqual(20, len(fsList))
+ self.failUnless(self.buildPath(["tree22", "dir003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link001",]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link002",]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link002", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link002", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link002", "link002", ]) in fsList)
+
+ def testAddDirContents_096(self):
+ """
+ Attempt to add a directory with linkDepth=3, dereference=False.
+ """
+ self.extractTar("tree22")
+ path = self.buildPath(["tree22", "dir003", ])
+ fsList = FilesystemList()
+ count = fsList.addDirContents(path, linkDepth=3, dereference=False)
+ if not platformSupportsLinks():
+ pass
+ else:
+ self.failUnlessEqual(20, count)
+ self.failUnlessEqual(20, len(fsList))
+ self.failUnless(self.buildPath(["tree22", "dir003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link001",]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link002",]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link002", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link002", "link001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", "link002", "link002", ]) in fsList)
+
+ def testAddDirContents_097(self):
+ """
+ Attempt to add a directory with linkDepth=0, dereference=True.
+ """
+ self.extractTar("tree22")
+ path = self.buildPath(["tree22", "dir003", ])
+ fsList = FilesystemList()
+ count = fsList.addDirContents(path, linkDepth=0, dereference=True)
+ if not platformSupportsLinks():
+ pass
+ else:
+ self.failUnlessEqual(12, count)
+ self.failUnlessEqual(12, len(fsList))
+ self.failUnless(self.buildPath(["tree22", "dir003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", ]) in fsList)
+
+ def testAddDirContents_098(self):
+ """
+ Attempt to add a directory with linkDepth=1, dereference=True.
+ """
+ self.extractTar("tree22")
+ path = self.buildPath(["tree22", "dir003", ])
+ fsList = FilesystemList()
+ count = fsList.addDirContents(path, linkDepth=1, dereference=True)
+ if not platformSupportsLinks():
+ pass
+ else:
+ self.failUnlessEqual(20, count)
+ self.failUnlessEqual(20, len(fsList))
+ self.failUnless(self.buildPath(["tree22", "dir003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005" ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "link002", ]) in fsList)
+
+ def testAddDirContents_099(self):
+ """
+ Attempt to add a directory with linkDepth=2, dereference=True.
+ """
+ self.extractTar("tree22")
+ path = self.buildPath(["tree22", "dir003", ])
+ fsList = FilesystemList()
+ count = fsList.addDirContents(path, linkDepth=2, dereference=True)
+ if not platformSupportsLinks():
+ pass
+ else:
+ self.failUnlessEqual(32, count)
+ self.failUnlessEqual(32, len(fsList))
+ self.failUnless(self.buildPath(["tree22", "dir003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir002", "file004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir002", "file005", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir002", "file009", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir004", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir004", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir004", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir006", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir006", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir006", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir006", "link002", ]) in fsList)
+
+ def testAddDirContents_100(self):
+ """
+ Attempt to add a directory with linkDepth=3, dereference=True.
+ """
+ self.extractTar("tree22")
+ path = self.buildPath(["tree22", "dir003", ])
+ fsList = FilesystemList()
+ count = fsList.addDirContents(path, linkDepth=3, dereference=True)
+ if not platformSupportsLinks():
+ pass
+ else:
+ self.failUnlessEqual(35, count)
+ self.failUnlessEqual(35, len(fsList))
+ self.failUnless(self.buildPath(["tree22", "dir003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "dir001", "link004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir003", "link003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir001", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir001", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir001", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir002", "file004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir002", "file005", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir002", "file009", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir004", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir004", "file001", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir004", "file002", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir004", "file003", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "dir005", ]) in fsList)
+ self.failUnless(self.buildPath(["tree22", "...
[truncated message content] |
|
From: <pro...@us...> - 2008-04-28 03:22:22
|
Revision: 915
http://cedar-backup.svn.sourceforge.net/cedar-backup/?rev=915&view=rev
Author: pronovic
Date: 2008-04-27 20:21:50 -0700 (Sun, 27 Apr 2008)
Log Message:
-----------
Implement CollectDir.dereference configuration option
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/actions/collect.py
cedar-backup2/trunk/CedarBackup2/config.py
cedar-backup2/trunk/Changelog
cedar-backup2/trunk/manual/src/config.xml
cedar-backup2/trunk/test/configtests.py
cedar-backup2/trunk/test/data/cback.conf.15
cedar-backup2/trunk/test/data/cback.conf.20
cedar-backup2/trunk/test/data/cback.conf.21
cedar-backup2/trunk/test/data/cback.conf.8
Modified: cedar-backup2/trunk/CedarBackup2/actions/collect.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/actions/collect.py 2008-04-28 02:40:04 UTC (rev 914)
+++ cedar-backup2/trunk/CedarBackup2/actions/collect.py 2008-04-28 03:21:50 UTC (rev 915)
@@ -127,13 +127,14 @@
archiveMode = _getArchiveMode(config, collectDir)
ignoreFile = _getIgnoreFile(config, collectDir)
linkDepth = _getLinkDepth(collectDir)
+ dereference = _getDereference(collectDir)
digestPath = _getDigestPath(config, collectDir)
tarfilePath = _getTarfilePath(config, collectDir, archiveMode)
(excludePaths, excludePatterns) = _getExclusions(config, collectDir)
if fullBackup or (collectMode in ['daily', 'incr', ]) or (collectMode == 'weekly' and todayIsStart):
logger.debug("Directory meets criteria to be backed up today.")
_collectDirectory(config, collectDir.absolutePath, tarfilePath,
- collectMode, archiveMode, ignoreFile, linkDepth,
+ collectMode, archiveMode, ignoreFile, linkDepth, dereference,
resetDigest, digestPath, excludePaths, excludePatterns)
else:
logger.debug("Directory will not be backed up, per collect mode.")
@@ -182,8 +183,8 @@
###############################
def _collectDirectory(config, absolutePath, tarfilePath, collectMode, archiveMode,
- ignoreFile, linkDepth, resetDigest, digestPath, excludePaths,
- excludePatterns):
+ ignoreFile, linkDepth, dereference, resetDigest, digestPath,
+ excludePaths, excludePatterns):
"""
Collects a configured collect directory.
@@ -203,6 +204,7 @@
@param archiveMode: Archive mode to use.
@param ignoreFile: Ignore file to use.
@param linkDepth: Link depth value to use.
+ @param dereference: Dereference flag to use.
@param resetDigest: Reset digest flag.
@param digestPath: Path to digest file on disk, if needed.
@param excludePaths: List of absolute paths to exclude.
@@ -212,7 +214,7 @@
backupList.ignoreFile = ignoreFile
backupList.excludePaths = excludePaths
backupList.excludePatterns = excludePatterns
- backupList.addDirContents(absolutePath, linkDepth=linkDepth)
+ backupList.addDirContents(absolutePath, linkDepth=linkDepth, dereference=dereference)
_executeBackup(config, backupList, absolutePath, tarfilePath, collectMode, archiveMode, resetDigest, digestPath)
@@ -407,6 +409,25 @@
############################
+# _getDereference() function
+############################
+
+def _getDereference(item):
+ """
+ Gets the dereference flag that should be used for a collect directory.
+ If possible, use the one on the directory, otherwise set a value of False.
+ @param item: C{CollectDir} object
+ @return: Ignore file to use.
+ """
+ if item.dereference is None:
+ dereference = False
+ else:
+ dereference = item.dereference
+ logger.debug("Dereference flag is [%s]" % dereference)
+ return dereference
+
+
+############################
# _getDigestPath() function
############################
Modified: cedar-backup2/trunk/CedarBackup2/config.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/config.py 2008-04-28 02:40:04 UTC (rev 914)
+++ cedar-backup2/trunk/CedarBackup2/config.py 2008-04-28 03:21:50 UTC (rev 915)
@@ -1359,13 +1359,13 @@
@note: Lists within this class are "unordered" for equality comparisons.
@sort: __init__, __repr__, __str__, __cmp__, absolutePath, collectMode,
- archiveMode, ignoreFile, linkDepth, absoluteExcludePaths,
+ archiveMode, ignoreFile, linkDepth, dereference, absoluteExcludePaths,
relativeExcludePaths, excludePatterns
"""
def __init__(self, absolutePath=None, collectMode=None, archiveMode=None, ignoreFile=None,
absoluteExcludePaths=None, relativeExcludePaths=None, excludePatterns=None,
- linkDepth=None):
+ linkDepth=None, dereference=False):
"""
Constructor for the C{CollectDir} class.
@@ -1374,6 +1374,7 @@
@param archiveMode: Overridden archive mode for this directory.
@param ignoreFile: Overidden ignore file name for this directory.
@param linkDepth: Maximum at which soft links should be followed.
+ @param dereference: Whether to dereference links that are followed.
@param absoluteExcludePaths: List of absolute paths to exclude.
@param relativeExcludePaths: List of relative paths to exclude.
@param excludePatterns: List of regular expression patterns to exclude.
@@ -1385,6 +1386,7 @@
self._archiveMode = None
self._ignoreFile = None
self._linkDepth = None
+ self._deference = None
self._absoluteExcludePaths = None
self._relativeExcludePaths = None
self._excludePatterns = None
@@ -1393,6 +1395,7 @@
self.archiveMode = archiveMode
self.ignoreFile = ignoreFile
self.linkDepth = linkDepth
+ self.dereference = dereference
self.absoluteExcludePaths = absoluteExcludePaths
self.relativeExcludePaths = relativeExcludePaths
self.excludePatterns = excludePatterns
@@ -1401,12 +1404,12 @@
"""
Official string representation for class instance.
"""
- return "CollectDir(%s, %s, %s, %s, %s, %s, %s, %s)" % (self.absolutePath, self.collectMode,
- self.archiveMode, self.ignoreFile,
- self.absoluteExcludePaths,
- self.relativeExcludePaths,
- self.excludePatterns,
- self.linkDepth)
+ return "CollectDir(%s, %s, %s, %s, %s, %s, %s, %s, %s)" % (self.absolutePath, self.collectMode,
+ self.archiveMode, self.ignoreFile,
+ self.absoluteExcludePaths,
+ self.relativeExcludePaths,
+ self.excludePatterns,
+ self.linkDepth, self.dereference)
def __str__(self):
"""
@@ -1448,6 +1451,11 @@
return -1
else:
return 1
+ if self._dereference != other._dereference:
+ if self._dereference < other._dereference:
+ return -1
+ else:
+ return 1
if self._absoluteExcludePaths != other._absoluteExcludePaths:
if self._absoluteExcludePaths < other._absoluteExcludePaths:
return -1
@@ -1558,6 +1566,22 @@
"""
return self._linkDepth
+ def _setDereference(self, value):
+ """
+ Property target used to set the dereference flag.
+ No validations, but we normalize the value to C{True} or C{False}.
+ """
+ if value:
+ self._dereference = True
+ else:
+ self._dereference = False
+
+ def _getDereference(self):
+ """
+ Property target used to get the dereference flag.
+ """
+ return self._dereference
+
def _setAbsoluteExcludePaths(self, value):
"""
Property target used to set the absolute exclude paths list.
@@ -1630,6 +1654,7 @@
archiveMode = property(_getArchiveMode, _setArchiveMode, None, doc="Overridden archive mode for this directory.")
ignoreFile = property(_getIgnoreFile, _setIgnoreFile, None, doc="Overridden ignore file name for this directory.")
linkDepth = property(_getLinkDepth, _setLinkDepth, None, doc="Maximum at which soft links should be followed.")
+ dereference = property(_getDereference, _setDereference, None, doc="Whether to dereference links that are followed.")
absoluteExcludePaths = property(_getAbsoluteExcludePaths, _setAbsoluteExcludePaths, None, "List of absolute paths to exclude.")
relativeExcludePaths = property(_getRelativeExcludePaths, _setRelativeExcludePaths, None, "List of relative paths to exclude.")
excludePatterns = property(_getExcludePatterns, _setExcludePatterns, None, "List of regular expression patterns to exclude.")
@@ -4714,6 +4739,7 @@
archiveMode archive_mode
ignoreFile ignore_file
linkDepth link_depth
+ dereference dereference
The collect mode is a special case. Just a C{mode} tag is accepted for
backwards compatibility, but we prefer C{collect_mode} for consistency
@@ -4745,6 +4771,7 @@
cdir.archiveMode = readString(entry, "archive_mode")
cdir.ignoreFile = readString(entry, "ignore_file")
cdir.linkDepth = readInteger(entry, "link_depth")
+ cdir.dereference = readBoolean(entry, "dereference")
(cdir.absoluteExcludePaths, cdir.relativeExcludePaths, cdir.excludePatterns) = Config._parseExclusions(entry)
lst.append(cdir)
if lst == []:
@@ -5365,6 +5392,7 @@
archiveMode dir/archive_mode
ignoreFile dir/ignore_file
linkDepth dir/link_depth
+ dereference dir/dereference
Note that an original XML document might have listed the collect mode
using the C{mode} tag, since we accept both C{collect_mode} and C{mode}.
@@ -5393,6 +5421,7 @@
addStringNode(xmlDom, sectionNode, "archive_mode", collectDir.archiveMode)
addStringNode(xmlDom, sectionNode, "ignore_file", collectDir.ignoreFile)
addIntegerNode(xmlDom, sectionNode, "link_depth", collectDir.linkDepth)
+ addBooleanNode(xmlDom, sectionNode, "dereference", collectDir.dereference)
if ((collectDir.absoluteExcludePaths is not None and collectDir.absoluteExcludePaths != []) or
(collectDir.relativeExcludePaths is not None and collectDir.relativeExcludePaths != []) or
(collectDir.excludePatterns is not None and collectDir.excludePatterns != [])):
@@ -5706,6 +5735,8 @@
raise ValueError("Archive mode must either be set in parent collect section or individual collect directory.")
if self.collect.ignoreFile is None and collectDir.ignoreFile is None:
raise ValueError("Ignore file must either be set in parent collect section or individual collect directory.")
+ if (collectDir.linkDepth is None or collectDir.linkDepth < 1) and collectDir.dereference:
+ raise ValueError("Dereference flag is only valid when a non-zero link depth is in use.")
def _validateStage(self):
"""
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2008-04-28 02:40:04 UTC (rev 914)
+++ cedar-backup2/trunk/Changelog 2008-04-28 03:21:50 UTC (rev 915)
@@ -3,6 +3,9 @@
* Add the ability to dereference links when following them.
- Add util.dereferenceLink() function
- Add dereference flag to FilesystemList.addDirContents()
+ - Add CollectDir.dereference attribute
+ - Modify collect action to obey CollectDir.dereference
+ - Update user manual to discuss new attribute
Version 2.17.1 26 Apr 2008
Modified: cedar-backup2/trunk/manual/src/config.xml
===================================================================
--- cedar-backup2/trunk/manual/src/config.xml 2008-04-28 02:40:04 UTC (rev 914)
+++ cedar-backup2/trunk/manual/src/config.xml 2008-04-28 03:21:50 UTC (rev 915)
@@ -1125,7 +1125,8 @@
but a set of soft links to other files and directories.
Normally, Cedar Backup does not follow soft links, but you can
override this behavior for individual directories using the
- <literal>link_depth</literal> option (see below).
+ <literal>link_depth</literal> and <literal>dereference</literal>
+ options (see below).
</para>
<para>
@@ -1635,7 +1636,7 @@
This field is optional. If it doesn't exist,
the backup will assume a value of zero, meaning
that soft links within the collect directory will
- never be followed.
+ never be followed.
</para>
<para>
<emphasis>Restrictions:</emphasis> If set, must
@@ -1645,6 +1646,38 @@
</varlistentry>
<varlistentry>
+ <term><literal>dereference</literal></term>
+ <listitem>
+ <para>Whether to dereference soft links.</para>
+ <para>
+ If this flag is set, links that are being
+ followed will be dereferenced before being added
+ to the backup. The link will be added (as a
+ link), and then the directory or file that the
+ link points at will be added as well.
+ </para>
+ <para>
+ This value only applies to a directory where soft
+ links are being followed (per the
+ <literal>link_depth</literal> configuration
+ option). It never applies to a configured
+ collect directory itself, only to other
+ directories within the collect directory.
+ </para>
+ <para>
+ This field is optional. If it doesn't exist,
+ the backup will assume that links should never be
+ dereferenced.
+ </para>
+ <para>
+ <emphasis>Restrictions:</emphasis> Must be a
+ boolean (<literal>Y</literal> or
+ <literal>N</literal>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><literal>exclude</literal></term>
<listitem>
<para>List of paths or patterns to exclude from the backup.</para>
Modified: cedar-backup2/trunk/test/configtests.py
===================================================================
--- cedar-backup2/trunk/test/configtests.py 2008-04-28 02:40:04 UTC (rev 914)
+++ cedar-backup2/trunk/test/configtests.py 2008-04-28 03:21:50 UTC (rev 915)
@@ -2439,6 +2439,7 @@
self.failUnlessEqual(None, collectDir.archiveMode)
self.failUnlessEqual(None, collectDir.ignoreFile)
self.failUnlessEqual(None, collectDir.linkDepth)
+ self.failUnlessEqual(False, collectDir.dereference)
self.failUnlessEqual(None, collectDir.absoluteExcludePaths)
self.failUnlessEqual(None, collectDir.relativeExcludePaths)
self.failUnlessEqual(None, collectDir.excludePatterns)
@@ -2447,12 +2448,13 @@
"""
Test constructor with all values filled in, with valid values.
"""
- collectDir = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 2)
+ collectDir = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 2, True)
self.failUnlessEqual("/etc/whatever", collectDir.absolutePath)
self.failUnlessEqual("incr", collectDir.collectMode)
self.failUnlessEqual("tar", collectDir.archiveMode)
self.failUnlessEqual(".ignore", collectDir.ignoreFile)
self.failUnlessEqual(2, collectDir.linkDepth)
+ self.failUnlessEqual(True, collectDir.dereference)
self.failUnlessEqual([], collectDir.absoluteExcludePaths)
self.failUnlessEqual([], collectDir.relativeExcludePaths)
self.failUnlessEqual([], collectDir.excludePatterns)
@@ -2807,7 +2809,44 @@
self.failUnlessAssignRaises(ValueError, collectDir, "linkDepth", "ken")
self.failUnlessEqual(None, collectDir.linkDepth)
+ def testConstructor_039(self):
+ """
+ Test assignment of dereference attribute, None value.
+ """
+ collectDir = CollectDir(dereference=True)
+ self.failUnlessEqual(True, collectDir.dereference)
+ collectDir.dereference = None
+ self.failUnlessEqual(False, collectDir.dereference)
+ def testConstructor_040(self):
+ """
+ Test assignment of dereference attribute, valid value (real boolean).
+ """
+ collectDir = CollectDir()
+ self.failUnlessEqual(False, collectDir.dereference)
+ collectDir.dereference = True
+ self.failUnlessEqual(True, collectDir.dereference)
+ collectDir.dereference = False
+ self.failUnlessEqual(False, collectDir.dereference)
+
+ def testConstructor_041(self):
+ """
+ Test assignment of dereference attribute, valid value (expression).
+ """
+ collectDir = CollectDir()
+ self.failUnlessEqual(False, collectDir.dereference)
+ collectDir.dereference = 0
+ self.failUnlessEqual(False, collectDir.dereference)
+ collectDir.dereference = []
+ self.failUnlessEqual(False, collectDir.dereference)
+ collectDir.dereference = None
+ self.failUnlessEqual(False, collectDir.dereference)
+ collectDir.dereference = ['a']
+ self.failUnlessEqual(True, collectDir.dereference)
+ collectDir.dereference = 3
+ self.failUnlessEqual(True, collectDir.dereference)
+
+
############################
# Test comparison operators
############################
@@ -2831,8 +2870,8 @@
Test comparison of two identical objects, all attributes non-None (empty
lists).
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
self.failUnless(collectDir1 == collectDir2)
self.failUnless(not collectDir1 < collectDir2)
self.failUnless(collectDir1 <= collectDir2)
@@ -2845,8 +2884,8 @@
Test comparison of two identical objects, all attributes non-None
(non-empty lists).
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/one",], ["two",], ["three",], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/one",], ["two",], ["three",], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/one",], ["two",], ["three",], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/one",], ["two",], ["three",], 1, True)
self.failUnless(collectDir1 == collectDir2)
self.failUnless(not collectDir1 < collectDir2)
self.failUnless(collectDir1 <= collectDir2)
@@ -2872,8 +2911,8 @@
"""
Test comparison of two differing objects, absolutePath differs.
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
- collectDir2 = CollectDir("/stuff", "incr", "tar", ".ignore", [], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
+ collectDir2 = CollectDir("/stuff", "incr", "tar", ".ignore", [], [], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(collectDir1 < collectDir2)
@@ -2900,8 +2939,8 @@
"""
Test comparison of two differing objects, collectMode differs.
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "daily", "tar", ".ignore", [], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "daily", "tar", ".ignore", [], [], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(not collectDir1 < collectDir2)
@@ -2928,8 +2967,8 @@
"""
Test comparison of two differing objects, archiveMode differs.
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "targz", ".ignore", [], [], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "targz", ".ignore", [], [], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(not collectDir1 < collectDir2)
@@ -2956,8 +2995,8 @@
"""
Test comparison of two differing objects, ignoreFile differs.
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", "ignore", [], [], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", "ignore", [], [], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(not collectDir1 < collectDir2)
@@ -3001,8 +3040,8 @@
Test comparison of two differing objects, absoluteExcludePaths differs
(one empty, one not empty).
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/whatever", ], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/whatever", ], [], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(collectDir1 < collectDir2)
@@ -3016,8 +3055,8 @@
Test comparison of two differing objects, absoluteExcludePaths differs
(both not empty).
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/stuff", ], [], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/stuff", "/something", ], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/stuff", ], [], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", ["/stuff", "/something", ], [], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(not collectDir1 < collectDir2) # note: different than standard due to unsorted list
@@ -3061,8 +3100,8 @@
Test comparison of two differing objects, relativeExcludePaths differs
(one empty, one not empty).
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], ["one", ], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], ["one", ], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(not collectDir1 < collectDir2)
@@ -3076,8 +3115,8 @@
Test comparison of two differing objects, relativeExcludePaths differs
(both not empty).
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], ["one", ], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], ["two", ], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], ["one", ], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], ["two", ], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(collectDir1 < collectDir2)
@@ -3121,8 +3160,8 @@
Test comparison of two differing objects, excludePatterns differs (one
empty, one not empty).
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], ["pattern", ], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], ["pattern", ], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(collectDir1 < collectDir2)
@@ -3136,8 +3175,8 @@
Test comparison of two differing objects, excludePatterns differs (both
not empty).
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], ["p1", ], 1)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], ["p2", ], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], ["p1", ], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", ".ignore", [], [], ["p2", ], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(collectDir1 < collectDir2)
@@ -3164,8 +3203,8 @@
"""
Test comparison of two differing objects, linkDepth differs.
"""
- collectDir1 = CollectDir("/etc/whatever", "incr", "tar", "ignore", [], [], [], 2)
- collectDir2 = CollectDir("/etc/whatever", "incr", "tar", "ignore", [], [], [], 1)
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", "ignore", [], [], [], 2, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", "ignore", [], [], [], 1, True)
self.failIfEqual(collectDir1, collectDir2)
self.failUnless(not collectDir1 == collectDir2)
self.failUnless(not collectDir1 < collectDir2)
@@ -3174,7 +3213,35 @@
self.failUnless(collectDir1 >= collectDir2)
self.failUnless(collectDir1 != collectDir2)
+ def testComparison_026(self):
+ """
+ Test comparison of two differing objects, dereference differs (one None).
+ """
+ collectDir1 = CollectDir()
+ collectDir2 = CollectDir(dereference=True)
+ self.failIfEqual(collectDir1, collectDir2)
+ self.failUnless(not collectDir1 == collectDir2)
+ self.failUnless(collectDir1 < collectDir2)
+ self.failUnless(collectDir1 <= collectDir2)
+ self.failUnless(not collectDir1 > collectDir2)
+ self.failUnless(not collectDir1 >= collectDir2)
+ self.failUnless(collectDir1 != collectDir2)
+ def testComparison_027(self):
+ """
+ Test comparison of two differing objects, dereference differs.
+ """
+ collectDir1 = CollectDir("/etc/whatever", "incr", "tar", "ignore", [], [], [], 1, True)
+ collectDir2 = CollectDir("/etc/whatever", "incr", "tar", "ignore", [], [], [], 1, False)
+ self.failIfEqual(collectDir1, collectDir2)
+ self.failUnless(not collectDir1 == collectDir2)
+ self.failUnless(not collectDir1 < collectDir2)
+ self.failUnless(not collectDir1 <= collectDir2)
+ self.failUnless(collectDir1 > collectDir2)
+ self.failUnless(collectDir1 >= collectDir2)
+ self.failUnless(collectDir1 != collectDir2)
+
+
#####################
# TestPurgeDir class
#####################
@@ -10696,7 +10763,67 @@
config.peers.remotePeers[0].managedActions = ["collect", ]
config._validatePeers()
+ def testValidate_078(self):
+ """
+ Test case where dereference is True but link depth is None.
+ """
+ config = Config()
+ config.collect = CollectConfig()
+ config.collect.targetDir = "/whatever"
+ config.collect.collectDirs = [ CollectDir(absolutePath="/stuff", collectMode="incr", archiveMode="tar", ignoreFile="i", linkDepth=None, dereference=True), ]
+ self.failUnlessRaises(ValueError, config._validateCollect)
+ def testValidate_079(self):
+ """
+ Test case where dereference is True but link depth is zero.
+ """
+ config = Config()
+ config.collect = CollectConfig()
+ config.collect.targetDir = "/whatever"
+ config.collect.collectDirs = [ CollectDir(absolutePath="/stuff", collectMode="incr", archiveMode="tar", ignoreFile="i", l...
[truncated message content] |
|
From: <pro...@us...> - 2008-05-06 00:56:58
|
Revision: 917
http://cedar-backup.svn.sourceforge.net/cedar-backup/?rev=917&view=rev
Author: pronovic
Date: 2008-05-05 17:56:53 -0700 (Mon, 05 May 2008)
Log Message:
-----------
Release 2.18.0
Modified Paths:
--------------
cedar-backup2/trunk/CedarBackup2/release.py
cedar-backup2/trunk/Changelog
Modified: cedar-backup2/trunk/CedarBackup2/release.py
===================================================================
--- cedar-backup2/trunk/CedarBackup2/release.py 2008-04-28 03:27:18 UTC (rev 916)
+++ cedar-backup2/trunk/CedarBackup2/release.py 2008-05-06 00:56:53 UTC (rev 917)
@@ -34,7 +34,7 @@
AUTHOR = "Kenneth J. Pronovici"
EMAIL = "pro...@ie..."
COPYRIGHT = "2004-2008"
-VERSION = "2.17.1"
-DATE = "26 Apr 2008"
+VERSION = "2.18.0"
+DATE = "05 May 2008"
URL = "http://cedar-backup.sourceforge.net/"
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2008-04-28 03:27:18 UTC (rev 916)
+++ cedar-backup2/trunk/Changelog 2008-05-06 00:56:53 UTC (rev 917)
@@ -1,4 +1,4 @@
-Version 2.18.0 unreleased
+Version 2.18.0 05 May 2008
* Add the ability to dereference links when following them.
- Add util.dereferenceLink() function
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2008-05-06 02:03:57
|
Revision: 919
http://cedar-backup.svn.sourceforge.net/cedar-backup/?rev=919&view=rev
Author: pronovic
Date: 2008-05-05 19:03:55 -0700 (Mon, 05 May 2008)
Log Message:
-----------
Fix a typo in CREDITS
Modified Paths:
--------------
cedar-backup2/trunk/CREDITS
cedar-backup2/trunk/Changelog
Modified: cedar-backup2/trunk/CREDITS
===================================================================
--- cedar-backup2/trunk/CREDITS 2008-05-06 00:57:07 UTC (rev 918)
+++ cedar-backup2/trunk/CREDITS 2008-05-06 02:03:55 UTC (rev 919)
@@ -58,7 +58,7 @@
Walsh and were originally released under a BSD-style license as documented
below.
-Source code annoted as "(c) 2000 Fourthought Inc, USA" was taken from or
+Source code annotated as "(c) 2000 Fourthought Inc, USA" was taken from or
derived from code within the PyXML distribution and was originally part of
the 4DOM suite developed by Fourthought, Inc. Fourthought released the
code under a BSD-like license. Items under this license include the XML
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2008-05-06 00:57:07 UTC (rev 918)
+++ cedar-backup2/trunk/Changelog 2008-05-06 02:03:55 UTC (rev 919)
@@ -1,3 +1,8 @@
+Version 2.18.1 unreleased
+
+ * Fix a few typos in the CREDITS file.
+
+
Version 2.18.0 05 May 2008
* Add the ability to dereference links when following them.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <pro...@us...> - 2008-05-06 02:12:54
|
Revision: 921
http://cedar-backup.svn.sourceforge.net/cedar-backup/?rev=921&view=rev
Author: pronovic
Date: 2008-05-05 19:12:52 -0700 (Mon, 05 May 2008)
Log Message:
-----------
Update README to properly reference SourceForge site.
Modified Paths:
--------------
cedar-backup2/trunk/Changelog
cedar-backup2/trunk/README
Modified: cedar-backup2/trunk/Changelog
===================================================================
--- cedar-backup2/trunk/Changelog 2008-05-06 02:05:09 UTC (rev 920)
+++ cedar-backup2/trunk/Changelog 2008-05-06 02:12:52 UTC (rev 921)
@@ -1,8 +1,8 @@
Version 2.18.1 unreleased
* Fix a few typos in the CREDITS file.
+ * Update README to properly reference SourceForge site.
-
Version 2.18.0 05 May 2008
* Add the ability to dereference links when following them.
Modified: cedar-backup2/trunk/README
===================================================================
--- cedar-backup2/trunk/README 2008-05-06 02:05:09 UTC (rev 920)
+++ cedar-backup2/trunk/README 2008-05-06 02:12:52 UTC (rev 921)
@@ -39,12 +39,11 @@
For more information, see the Cedar Backup web site:
- http://cedar-solutions.com/software/cedar-backup
+ http://cedar-backup.sourceforge.net/
-If you regularly use Cedar Backup, you might also like to join the
-low-volume Cedar Backup mailing list:
+If you regularly use Cedar Backup, you might also want to join the
+low-volume cedar-backup-users mailing list, which you can subscribe to via
+the SourceForge site. This list is used to announce new releases of Cedar
+Backup, and you can use it to report bugs or to get help using Cedar
+Backup.
- http://cedar-solutions.com/listarchives/
-
-Use this mailing list to report bugs or for help using Cedar Backup.
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|