Skip to content

Commit

Permalink
feat: improve "changed" flag by parsing the stow output
Browse files Browse the repository at this point in the history
  • Loading branch information
upsetbit committed Oct 8, 2022
1 parent e474f04 commit bff7a64
Showing 1 changed file with 46 additions and 7 deletions.
53 changes: 46 additions & 7 deletions stow
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,18 @@ For more information, please see
'''

import os
import re

from ansible.module_utils.basic import AnsibleModule


unlink_re = re.compile('^UNLINK: (?P<link_path>.+)$')

link_re = re.compile(
'^LINK: (?P<file_path>.+) => (?P<link_path>.+)(?P<reverts> \(reverts previous action\))?$'
)


def purge_conflicts(conflicted_files):
"""Delete a file or unlink a symlink conflicting with a package.
Expand Down Expand Up @@ -131,8 +140,7 @@ def stow_has_conflicts(module, package, cmd):
conflicts = []

# Grab the conflicting files path.
stderr_lines = stderr.split('\n')
for sel in stderr_lines:
for sel in stderr.split('\n'):
if '* existing target is' in sel:
conflict = sel.split(':')
conflict = conflict[-1].strip()
Expand All @@ -146,6 +154,27 @@ def stow_has_conflicts(module, package, cmd):
return dict(recoverable=True, message=msg, files=conflicts)


def has_stow_changed_links(stow_output):
if stow_output.strip() == '':
return 0

n_linked = set()
n_unlinked = set()

for sel in stow_output.split('\n'):

link_match = link_re.match(sel)
if link_match:
n_linked.add(link_match.group('file_path'))
continue

unlink_match = unlink_re.match(sel)
if unlink_match:
n_unlinked.add(unlink_match.group('link_path'))

return n_linked != n_unlinked


def stow(module, package, state):
"""Perform stow on a package against the filesystem.
Expand Down Expand Up @@ -193,20 +222,30 @@ def stow(module, package, state):
# (supposing execution passed all errors checking).
rc_, _, se_ = module.run_command(cmd)
if rc_ != 0:
msg = 'execution of command "{cmd}" failed with error code {rc_}; output: "{se_}"'
msg = f'execution of command "{cmd}" failed with error code {rc_}; output: "{se_}"'
return dict(error=True, message=msg)

return dict(error=False, changed=(se_ != ''))
return dict(error=False, changed=has_stow_changed_links(se_))


def main():
'''The module main routine.'''

module = AnsibleModule(
argument_spec={
'dir': {'required': True, 'type': 'str'},
'package': {'required': True, 'type': 'list'},
'target': {'required': False, 'type': 'str', 'default': os.environ.get('HOME')},
'dir': {
'required': True,
'type': 'str',
},
'package': {
'required': True,
'type': 'list',
},
'target': {
'required': False,
'type': 'str',
'default': os.environ.get('HOME'),
},
'state': {
'required': True,
'type': 'str',
Expand Down

0 comments on commit bff7a64

Please sign in to comment.