Fix: wildcard excludes in unarchive with tar archives (#40935)
* fix: exclude using wildcards for tar archives Fixes #37842, #22947 * fix: Remove quote() as it munges the exclude format * test: Refactor to use single archive structure A common structure archived by different methods should simplify some of the feature tests. * test: Use common archive layout to validate exclude feature * test: Use the same exclude checks for zip/tar archives
This commit is contained in:
parent
e9b658baae
commit
ba3db90e3a
2 changed files with 67 additions and 19 deletions
|
@ -647,7 +647,7 @@ class TgzArchive(object):
|
||||||
if self.opts:
|
if self.opts:
|
||||||
cmd.extend(['--show-transformed-names'] + self.opts)
|
cmd.extend(['--show-transformed-names'] + self.opts)
|
||||||
if self.excludes:
|
if self.excludes:
|
||||||
cmd.extend(['--exclude=' + quote(f) for f in self.excludes])
|
cmd.extend(['--exclude=' + f for f in self.excludes])
|
||||||
cmd.extend(['-f', self.src])
|
cmd.extend(['-f', self.src])
|
||||||
rc, out, err = self.module.run_command(cmd, cwd=self.dest, environ_update=dict(LANG='C', LC_ALL='C', LC_MESSAGES='C'))
|
rc, out, err = self.module.run_command(cmd, cwd=self.dest, environ_update=dict(LANG='C', LC_ALL='C', LC_MESSAGES='C'))
|
||||||
if rc != 0:
|
if rc != 0:
|
||||||
|
@ -658,14 +658,18 @@ class TgzArchive(object):
|
||||||
# filename = filename.decode('string_escape')
|
# filename = filename.decode('string_escape')
|
||||||
filename = to_native(codecs.escape_decode(filename)[0])
|
filename = to_native(codecs.escape_decode(filename)[0])
|
||||||
|
|
||||||
if filename and filename not in self.excludes:
|
# We don't allow absolute filenames. If the user wants to unarchive rooted in "/"
|
||||||
# We don't allow absolute filenames. If the user wants to unarchive rooted in "/"
|
# they need to use "dest: '/'". This follows the defaults for gtar, pax, etc.
|
||||||
# they need to use "dest: '/'". This follows the defaults for gtar, pax, etc.
|
# Allowing absolute filenames here also causes bugs: https://github.com/ansible/ansible/issues/21397
|
||||||
# Allowing absolute filenames here also causes bugs: https://github.com/ansible/ansible/issues/21397
|
if filename.startswith('/'):
|
||||||
if filename.startswith('/'):
|
filename = filename[1:]
|
||||||
filename = filename[1:]
|
|
||||||
|
|
||||||
self._files_in_archive.append(filename)
|
if self.excludes:
|
||||||
|
for exclude in self.excludes:
|
||||||
|
if not fnmatch.fnmatch(filename, exclude):
|
||||||
|
self._files_in_archive.append(to_native(filename))
|
||||||
|
else:
|
||||||
|
self._files_in_archive.append(to_native(filename))
|
||||||
|
|
||||||
return self._files_in_archive
|
return self._files_in_archive
|
||||||
|
|
||||||
|
@ -682,7 +686,7 @@ class TgzArchive(object):
|
||||||
if self.module.params['keep_newer']:
|
if self.module.params['keep_newer']:
|
||||||
cmd.append('--keep-newer-files')
|
cmd.append('--keep-newer-files')
|
||||||
if self.excludes:
|
if self.excludes:
|
||||||
cmd.extend(['--exclude=' + quote(f) for f in self.excludes])
|
cmd.extend(['--exclude=' + f for f in self.excludes])
|
||||||
cmd.extend(['-f', self.src])
|
cmd.extend(['-f', self.src])
|
||||||
rc, out, err = self.module.run_command(cmd, cwd=self.dest, environ_update=dict(LANG='C', LC_ALL='C', LC_MESSAGES='C'))
|
rc, out, err = self.module.run_command(cmd, cwd=self.dest, environ_update=dict(LANG='C', LC_ALL='C', LC_MESSAGES='C'))
|
||||||
|
|
||||||
|
@ -729,7 +733,7 @@ class TgzArchive(object):
|
||||||
if self.module.params['keep_newer']:
|
if self.module.params['keep_newer']:
|
||||||
cmd.append('--keep-newer-files')
|
cmd.append('--keep-newer-files')
|
||||||
if self.excludes:
|
if self.excludes:
|
||||||
cmd.extend(['--exclude=' + quote(f) for f in self.excludes])
|
cmd.extend(['--exclude=' + f for f in self.excludes])
|
||||||
cmd.extend(['-f', self.src])
|
cmd.extend(['-f', self.src])
|
||||||
rc, out, err = self.module.run_command(cmd, cwd=self.dest, environ_update=dict(LANG='C', LC_ALL='C', LC_MESSAGES='C'))
|
rc, out, err = self.module.run_command(cmd, cwd=self.dest, environ_update=dict(LANG='C', LC_ALL='C', LC_MESSAGES='C'))
|
||||||
return dict(cmd=cmd, rc=rc, out=out, err=err)
|
return dict(cmd=cmd, rc=rc, out=out, err=err)
|
||||||
|
|
|
@ -60,6 +60,39 @@
|
||||||
- name: prep a zip file
|
- name: prep a zip file
|
||||||
shell: zip test-unarchive.zip foo-unarchive.txt foo-unarchive-777.txt chdir={{output_dir}}
|
shell: zip test-unarchive.zip foo-unarchive.txt foo-unarchive-777.txt chdir={{output_dir}}
|
||||||
|
|
||||||
|
- name: Prepare - Create test dirs
|
||||||
|
file:
|
||||||
|
path: "{{output_dir}}/{{item}}"
|
||||||
|
state: directory
|
||||||
|
with_items:
|
||||||
|
- created/include
|
||||||
|
- created/exclude
|
||||||
|
- created/other
|
||||||
|
|
||||||
|
- name: Prepare - Create test files
|
||||||
|
file:
|
||||||
|
path: "{{output_dir}}/created/{{item}}"
|
||||||
|
state: touch
|
||||||
|
with_items:
|
||||||
|
- include/include-1.txt
|
||||||
|
- include/include-2.txt
|
||||||
|
- include/include-3.txt
|
||||||
|
- exclude/exclude-1.txt
|
||||||
|
- exclude/exclude-2.txt
|
||||||
|
- exclude/exclude-3.txt
|
||||||
|
- other/include-1.ext
|
||||||
|
- other/include-2.ext
|
||||||
|
- other/exclude-1.ext
|
||||||
|
- other/exclude-2.ext
|
||||||
|
- other/other-1.ext
|
||||||
|
- other/other-2.ext
|
||||||
|
|
||||||
|
- name: Prepare - zip file
|
||||||
|
shell: zip -r {{output_dir}}/unarchive-00.zip * chdir={{output_dir}}/created/
|
||||||
|
|
||||||
|
- name: Prepare - tar file
|
||||||
|
shell: tar czvf {{output_dir}}/unarchive-00.tar * chdir={{output_dir}}/created/
|
||||||
|
|
||||||
- name: add a file with Windows permissions to zip file
|
- name: add a file with Windows permissions to zip file
|
||||||
shell: zip -k test-unarchive.zip FOO-UNAR.TXT chdir={{output_dir}}
|
shell: zip -k test-unarchive.zip FOO-UNAR.TXT chdir={{output_dir}}
|
||||||
|
|
||||||
|
@ -187,22 +220,33 @@
|
||||||
- name: "Create {{ output_dir }}/exclude directory"
|
- name: "Create {{ output_dir }}/exclude directory"
|
||||||
file:
|
file:
|
||||||
state: directory
|
state: directory
|
||||||
path: "{{ output_dir }}/exclude"
|
path: "{{ output_dir }}/exclude-{{item}}"
|
||||||
|
with_items:
|
||||||
|
- zip
|
||||||
|
- tar
|
||||||
|
|
||||||
- name: Unpack zip file excluding one file.
|
- name: Unpack archive file excluding glob files.
|
||||||
unarchive:
|
unarchive:
|
||||||
src: "{{ output_dir }}/test-unarchive.zip"
|
src: "{{ output_dir }}/unarchive-00.{{item}}"
|
||||||
dest: "{{ output_dir }}/exclude"
|
dest: "{{ output_dir }}/exclude-{{item}}"
|
||||||
exclude: "foo-unarchive-*.txt"
|
exclude: "exclude/exclude-*.txt"
|
||||||
|
with_items:
|
||||||
|
- zip
|
||||||
|
- tar
|
||||||
|
|
||||||
- name: verify that the file was unarchived
|
- name: verify that the file was unarchived
|
||||||
shell: find {{ output_dir }}/exclude chdir={{ output_dir }}
|
shell: find {{ output_dir }}/exclude-{{item}} chdir={{ output_dir }}
|
||||||
register: unarchive_dir01
|
register: unarchive00
|
||||||
|
with_items:
|
||||||
|
- zip
|
||||||
|
- tar
|
||||||
|
|
||||||
- name: verify that zip extraction excluded file
|
- name: verify that archive extraction excluded the files
|
||||||
assert:
|
assert:
|
||||||
that:
|
that:
|
||||||
- "'foo-unarchive-777.txt' not in unarchive_dir01.stdout"
|
- "'exclude/exclude-1.txt' not in item.stdout"
|
||||||
|
with_items:
|
||||||
|
- "{{ unarchive00.results }}"
|
||||||
|
|
||||||
- name: remove our zip unarchive destination
|
- name: remove our zip unarchive destination
|
||||||
file: path={{output_dir}}/test-unarchive-zip state=absent
|
file: path={{output_dir}}/test-unarchive-zip state=absent
|
||||||
|
|
Loading…
Reference in a new issue