diff --git a/plugins/modules/patch.py b/plugins/modules/patch.py index 9c6cfff..ea2c618 100644 --- a/plugins/modules/patch.py +++ b/plugins/modules/patch.py @@ -74,6 +74,11 @@ options: - If set to C(no), C(patch) will replace CRLF in C(src) files on POSIX. type: bool default: no + ignore_whitespace: + description: + - Setting to C(yes) will ignore white space changes between patch and input.. + type: bool + default: no notes: - This module requires GNU I(patch) utility to be installed on the remote host. ''' @@ -116,13 +121,15 @@ def add_dry_run_option(opts): opts.append('--dry-run') -def is_already_applied(patch_func, patch_file, basedir, dest_file=None, binary=False, strip=0, state='present'): +def is_already_applied(patch_func, patch_file, basedir, dest_file=None, binary=False, ignore_whitespace=False, strip=0, state='present'): opts = ['--quiet', '--forward', "--strip=%s" % strip, "--directory='%s'" % basedir, "--input='%s'" % patch_file] add_dry_run_option(opts) if binary: opts.append('--binary') + if ignore_whitespace: + opts.append('--ignore-whitespace') if dest_file: opts.append("'%s'" % dest_file) if state == 'present': @@ -132,7 +139,7 @@ def is_already_applied(patch_func, patch_file, basedir, dest_file=None, binary=F return rc == 0 -def apply_patch(patch_func, patch_file, basedir, dest_file=None, binary=False, strip=0, dry_run=False, backup=False, state='present'): +def apply_patch(patch_func, patch_file, basedir, dest_file=None, binary=False, ignore_whitespace=False, strip=0, dry_run=False, backup=False, state='present'): opts = ['--quiet', '--forward', '--batch', '--reject-file=-', "--strip=%s" % strip, "--directory='%s'" % basedir, "--input='%s'" % patch_file] @@ -140,6 +147,8 @@ def apply_patch(patch_func, patch_file, basedir, dest_file=None, binary=False, s add_dry_run_option(opts) if binary: opts.append('--binary') + if ignore_whitespace: + opts.append('--ignore-whitespace') if dest_file: opts.append("'%s'" % dest_file) if backup: @@ -165,6 +174,7 @@ def main(): # since patch will create numbered copies, not strftime("%Y-%m-%d@%H:%M:%S~") backup=dict(type='bool', default=False), binary=dict(type='bool', default=False), + ignore_whitespace=dict(type='bool', default=False), state=dict(type='str', default='present', choices=['absent', 'present']), ), required_one_of=[['dest', 'basedir']], @@ -197,9 +207,10 @@ def main(): p.src = os.path.abspath(p.src) changed = False - if not is_already_applied(patch_func, p.src, p.basedir, dest_file=p.dest, binary=p.binary, strip=p.strip, state=p.state): + if not is_already_applied(patch_func, p.src, p.basedir, dest_file=p.dest, binary=p.binary, + ignore_whitespace=p.ignore_whitespace, strip=p.strip, state=p.state): try: - apply_patch(patch_func, p.src, p.basedir, dest_file=p.dest, binary=p.binary, strip=p.strip, + apply_patch(patch_func, p.src, p.basedir, dest_file=p.dest, binary=p.binary, ignore_whitespace=p.ignore_whitespace, strip=p.strip, dry_run=module.check_mode, backup=p.backup, state=p.state) changed = True except PatchError as e: diff --git a/tests/integration/targets/patch/files/result_whitespace.patch b/tests/integration/targets/patch/files/result_whitespace.patch new file mode 100644 index 0000000..3cd4371 --- /dev/null +++ b/tests/integration/targets/patch/files/result_whitespace.patch @@ -0,0 +1,24 @@ +--- origin.txt 2018-05-12 10:22:14.155109584 +0200 ++++ result.txt 2018-05-12 10:18:07.230811204 +0200 +@@ -2,18 +2,12 @@ + sit amet. + + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod +-tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At +-vero eos et accusam et justo duo dolores et ea rebum. +- +-Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor +-sit amet. +- +-Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod +-tempor invidunt ut labore et dolore magna aliquyam erat. ++tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. ++At vero eos et accusam et justo duo dolores et ea rebum. + + Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod + tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At + vero eos et accusam et justo duo dolores et ea rebum. + +-Stet clita kasd gubergren,no sea takimata sanctus est Lorem ipsum dolor ++Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor + sit amet. diff --git a/tests/integration/targets/patch/tasks/main.yml b/tests/integration/targets/patch/tasks/main.yml index 90e9837..0b5f3ee 100644 --- a/tests/integration/targets/patch/tasks/main.yml +++ b/tests/integration/targets/patch/tasks/main.yml @@ -87,3 +87,38 @@ dest: '{{ output_dir }}/patch/workfile.txt' register: result failed_when: result is changed + +- name: copy the origin file whitespace + copy: + src: ./origin.txt + dest: '{{ output_dir }}/patch/workfile_whitespace.txt' + register: result + +- name: patch the origin file + register: result + patch: + src: result_whitespace.patch + dest: '{{ output_dir }}/patch/workfile_whitespace.txt' + ignore_whitespace: yes +- name: verify patch the origin file + assert: + that: + - result is changed + +- name: test patch the origin file idempotency + register: result + patch: + src: result_whitespace.patch + dest: '{{ output_dir }}/patch/workfile_whitespace.txt' + ignore_whitespace: yes +- name: verify test patch the origin file idempotency + assert: + that: + - result is not changed + +- name: verify the resulted file matches expectations + copy: + src: ./result_whitespace.txt + dest: '{{ output_dir }}/patch/workfile_whitespace.txt' + register: result + failed_when: result is changed