summaryrefslogtreecommitdiff
path: root/files
diff options
context:
space:
mode:
authorBen Doherty <ben@thinkoomph.com>2016-05-26 23:09:35 -0400
committerBen Doherty <ben@thinkoomph.com>2016-05-26 23:09:35 -0400
commitcca70b7c9131627681bed77f4fbee5bb6e4823af (patch)
tree121beeb6c3ef8e8de6e987f46c8ba8142bfb0858 /files
parentf482cb4790fead81f1146fd9cc89a91e1c0ad12e (diff)
downloadansible-modules-extras-cca70b7c9131627681bed77f4fbee5bb6e4823af.tar.gz
Fix up for zip files and nesting logic.
* Don't include the archive in the archive if it falls within an archived path * If remove=True and the archive would be in an archived path, fail. * Fix single-file zip file compression * Add more documentation about 'state' return
Diffstat (limited to 'files')
-rw-r--r--files/archive.py49
1 files changed, 40 insertions, 9 deletions
diff --git a/files/archive.py b/files/archive.py
index fecd7a45..2dba54a3 100644
--- a/files/archive.py
+++ b/files/archive.py
@@ -72,7 +72,12 @@ EXAMPLES = '''
RETURN = '''
state:
- description: The current state of the archived file.
+ description:
+ The current state of the archived file.
+ If 'absent', then no source files were found and the archive does not exist.
+ If 'compress', then the file source file is in the compressed state.
+ If 'archive', then the source file or paths are currently archived.
+ If 'incomplete', then an archive was created, but not all source paths were found.
type: string
returned: always
missing:
@@ -98,6 +103,7 @@ import glob
import shutil
import gzip
import bz2
+import filecmp
import zipfile
import tarfile
@@ -157,6 +163,7 @@ def main():
archive_paths = []
missing = []
+ exclude = []
arcroot = ''
for path in expanded_paths:
@@ -172,9 +179,9 @@ def main():
if i < len(arcroot):
arcroot = os.path.dirname(arcroot[0:i+1])
- if path == creates:
- # Don't allow the archive to specify itself! this is an error.
- module.fail_json(path=', '.join(paths), msg='Error, created archive would be included in archive')
+ # Don't allow archives to be created anywhere within paths to be removed
+ if remove and os.path.isdir(path) and creates.startswith(path):
+ module.fail_json(path=', '.join(paths), msg='Error, created archive can not be contained in source paths when remove=True')
if os.path.lexists(path):
archive_paths.append(path)
@@ -208,18 +215,40 @@ def main():
if state != 'archive':
try:
+ # Easier compression using tarfile module
if compression == 'gz' or compression == 'bz2':
archive = tarfile.open(creates, 'w|' + compression)
for path in archive_paths:
- archive.add(path, path[len(arcroot):])
+ basename = ''
+
+ # Prefix trees in the archive with their basename, unless specifically prevented with '.'
+ if os.path.isdir(path) and not path.endswith(os.sep + '.'):
+ basename = os.path.basename(path) + os.sep
+
+ archive.add(path, path[len(arcroot):], filter=lambda f: f if f.name != creates else None)
successes.append(path)
+ # Slightly more difficult (and less efficient!) compression using zipfile module
elif compression == 'zip':
- archive = zipfile.ZipFile(creates, 'w')
+ archive = zipfile.ZipFile(creates, 'w', zipfile.ZIP_DEFLATED)
for path in archive_paths:
- archive.write(path, path[len(arcroot):])
+ basename = ''
+
+ # Prefix trees in the archive with their basename, unless specifically prevented with '.'
+ if os.path.isdir(path) and not path.endswith(os.sep + '.'):
+ basename = os.path.basename(path) + os.sep
+
+ for dirpath, dirnames, filenames in os.walk(path, topdown=True):
+ for dirname in dirnames:
+ archive.write(dirpath + os.sep + dirname, basename + dirname)
+ for filename in filenames:
+ fullpath = dirpath + os.sep + filename
+
+ if not filecmp.cmp(fullpath, creates):
+ archive.write(fullpath, basename + filename)
+
successes.append(path)
except OSError:
@@ -228,8 +257,10 @@ def main():
if archive:
archive.close()
+ state = 'archive'
+
- if state != 'archive' and remove:
+ if state == 'archive' and remove:
for path in successes:
try:
if os.path.isdir(path):
@@ -275,7 +306,7 @@ def main():
try:
if compression == 'zip':
- archive = zipfile.ZipFile(creates, 'wb')
+ archive = zipfile.ZipFile(creates, 'w', zipfile.ZIP_DEFLATED)
archive.write(path, path[len(arcroot):])
archive.close()
state = 'archive' # because all zip files are archives