Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event hook fix #288

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/udiskie.8.txt
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ remain available:
ui_device_presentation
ui_id_label
ui_id_uuid
job_action in an event_hook call of a job_failed event, this is the action that failed
job_message in an event_hook call of a job_failed event, this is the message from udisks


See Also
Expand Down
2 changes: 2 additions & 0 deletions udiskie/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class DeviceFilter:
'ui_device_presentation',
'ui_id_label',
'ui_id_uuid',
'job_action',
'job_message',
]

def __init__(self, match):
Expand Down
31 changes: 26 additions & 5 deletions udiskie/prompt.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ async def get_password_tty(device, options):
class DeviceCommand:

"""
Launcher that starts user-defined password prompts. The command can be
Launcher that starts a user-defined external command. This may be
a user-defined password prompt, or an event hook. The command can be
specified in terms of a command line template.
"""

Expand Down Expand Up @@ -203,13 +204,24 @@ def __init__(self, argv, capture=False, **extra):
'Unknown device attribute {!r} in format string: {!r}',
kwd, arg))

async def __call__(self, device):
# I'm not sure what to do with the event_hook on device_changed events
# We should probably call the event hook only once, with a list of changed
# attributes. But for now, just call the event_hook twice, once with the
# old attributes, and once with the new ones.
async def __call__(self, device, arg1=None, arg2=None):
"""
Invoke the subprocess to ask the user to enter a password for unlocking
the specified device.
Invoke a subprocess. This may be an event hook or to ask the user
to enter a password for unlocking the specified device.
arg2 will only be not-None for a job_failed event hook.
arg1 will only be not-None for job_failed or device_changed event hooks.
"""
attrs = {attr: getattr(device, attr) for attr in self.used_attrs}
attrs.update(self.extra)
if arg2:
attrs['job_action'] = arg1
attrs['job_message'] = arg2
elif arg1:
attrs['event'] = 'device_changed_from'
argv = [arg.format(**attrs) for arg in self.argv]
try:
stdout = await exec_subprocess(argv, self.capture)
Expand All @@ -219,6 +231,15 @@ async def __call__(self, device):
# keyfiles. This logic is a guess that may cause bugs for some users:(
if stdout and stdout.endswith(b'\n') and is_utf8(stdout):
stdout = stdout[:-1]
if arg1 and arg2 is None:
attrs = {attr: getattr(arg1, attr) for attr in self.used_attrs}
attrs.update(self.extra)
attrs['event'] = 'device_changed_to'
argv = [arg.format(**attrs) for arg in self.argv]
try:
await exec_subprocess(argv, False)
except subprocess.CalledProcessError:
return None
return stdout

async def password(self, device, options):
Expand Down Expand Up @@ -280,7 +301,7 @@ def connect_event_hook(command_format, mounter):
:param mounter: Mounter object
"""
udisks = mounter.udisks
for event in ['device_mounted', 'device_unmounted',
for event in ['device_changed', 'device_mounted', 'device_unmounted',
'device_locked', 'device_unlocked',
'device_added', 'device_removed',
'job_failed']:
Expand Down
8 changes: 8 additions & 0 deletions udiskie/udisks2.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,14 @@ def drive_label(self):
self.drive_model,
]))

@property
def job_action(self):
return None

@property
def job_message(self):
return None


# ----------------------------------------
# UDisks2 service wrapper
Expand Down
Loading