mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 19:06:11 +00:00
Merge pull request #44 from benfirad/agent/remove-integration-wrapper
Remove macOS command wrapper during integration cleanup
This commit is contained in:
+23
-4
@@ -34,6 +34,7 @@ import sys
|
|||||||
AGENT_ID = "io.github.yusufipk.dikte"
|
AGENT_ID = "io.github.yusufipk.dikte"
|
||||||
ICON_NAME = "dikte"
|
ICON_NAME = "dikte"
|
||||||
DESKTOP_FILE = "dikte.desktop"
|
DESKTOP_FILE = "dikte.desktop"
|
||||||
|
MACOS_COMMAND_MARKER = "# Written by Dikte itself. Delete it to be rid of it.\n"
|
||||||
|
|
||||||
|
|
||||||
def packaged():
|
def packaged():
|
||||||
@@ -398,6 +399,20 @@ def _agent_path():
|
|||||||
return pathlib.Path.home() / "Library" / "LaunchAgents" / f"{AGENT_ID}.plist"
|
return pathlib.Path.home() / "Library" / "LaunchAgents" / f"{AGENT_ID}.plist"
|
||||||
|
|
||||||
|
|
||||||
|
def _macos_command_path():
|
||||||
|
return pathlib.Path.home() / ".local" / "bin" / "dikte"
|
||||||
|
|
||||||
|
|
||||||
|
def _macos_command_is_ours(command):
|
||||||
|
"""Whether this is the wrapper a downloaded Mac build wrote itself."""
|
||||||
|
try:
|
||||||
|
return command.is_file() and MACOS_COMMAND_MARKER in command.read_text(
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
except (OSError, UnicodeDecodeError):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _agent_plist(app):
|
def _agent_plist(app):
|
||||||
"""Through `open` rather than the executable inside the bundle, so that the
|
"""Through `open` rather than the executable inside the bundle, so that the
|
||||||
process is one LaunchServices started: that is what gives it the bundle's
|
process is one LaunchServices started: that is what gives it the bundle's
|
||||||
@@ -449,13 +464,13 @@ def _macos_install(app, force=False):
|
|||||||
# The command, as a wrapper rather than a symlink: the executable has to be
|
# The command, as a wrapper rather than a symlink: the executable has to be
|
||||||
# run from inside the bundle for macOS to file its permissions under Dikte,
|
# run from inside the bundle for macOS to file its permissions under Dikte,
|
||||||
# and a symlink somewhere else is a different process to macOS.
|
# and a symlink somewhere else is a different process to macOS.
|
||||||
command = pathlib.Path.home() / ".local" / "bin" / "dikte"
|
command = _macos_command_path()
|
||||||
binary = app / "Contents" / "MacOS" / "Dikte"
|
binary = app / "Contents" / "MacOS" / "Dikte"
|
||||||
marker = "# Written by Dikte itself. Delete it to be rid of it.\n"
|
script = (f'#!/bin/sh\n{MACOS_COMMAND_MARKER}'
|
||||||
script = f'#!/bin/sh\n{marker}exec {shlex.quote(str(binary))} "$@"\n'
|
f'exec {shlex.quote(str(binary))} "$@"\n')
|
||||||
# install-mac.sh writes its own wrapper here, naming the checkout's Python.
|
# install-mac.sh writes its own wrapper here, naming the checkout's Python.
|
||||||
# Ours only replaces a wrapper it wrote before, or nothing at all.
|
# Ours only replaces a wrapper it wrote before, or nothing at all.
|
||||||
ours = command.exists() and marker in command.read_text(encoding="utf-8")
|
ours = _macos_command_is_ours(command)
|
||||||
if (not command.exists() or ours or force) and _write(command, script):
|
if (not command.exists() or ours or force) and _write(command, script):
|
||||||
command.chmod(0o755)
|
command.chmod(0o755)
|
||||||
written.append(command)
|
written.append(command)
|
||||||
@@ -470,6 +485,10 @@ def _macos_remove():
|
|||||||
capture_output=True, check=False)
|
capture_output=True, check=False)
|
||||||
agent.unlink()
|
agent.unlink()
|
||||||
gone.append(agent)
|
gone.append(agent)
|
||||||
|
command = _macos_command_path()
|
||||||
|
if _macos_command_is_ours(command):
|
||||||
|
command.unlink()
|
||||||
|
gone.append(command)
|
||||||
return gone
|
return gone
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -364,6 +364,12 @@ class MacOS(Home):
|
|||||||
mock.patch.object(integrate, "_launchctl_reload"):
|
mock.patch.object(integrate, "_launchctl_reload"):
|
||||||
return integrate.install(force=force)
|
return integrate.install(force=force)
|
||||||
|
|
||||||
|
def remove(self):
|
||||||
|
with Frozen("/Applications/Dikte.app/Contents/MacOS/Dikte",
|
||||||
|
home=self.home, platform="darwin"), \
|
||||||
|
mock.patch("subprocess.run"):
|
||||||
|
return integrate.remove()
|
||||||
|
|
||||||
def test_it_writes_a_login_item_and_the_command(self):
|
def test_it_writes_a_login_item_and_the_command(self):
|
||||||
app = self.home / "Applications" / "Dikte.app"
|
app = self.home / "Applications" / "Dikte.app"
|
||||||
(app / "Contents/MacOS").mkdir(parents=True)
|
(app / "Contents/MacOS").mkdir(parents=True)
|
||||||
@@ -425,6 +431,25 @@ class MacOS(Home):
|
|||||||
self.install(app)
|
self.install(app)
|
||||||
self.assertIn("install-mac.sh", command.read_text())
|
self.assertIn("install-mac.sh", command.read_text())
|
||||||
|
|
||||||
|
def test_removing_takes_back_the_login_item_and_command_it_wrote(self):
|
||||||
|
app = self.home / "Applications" / "Dikte.app"
|
||||||
|
(app / "Contents/MacOS").mkdir(parents=True)
|
||||||
|
self.install(app)
|
||||||
|
command = self.home / ".local/bin/dikte"
|
||||||
|
|
||||||
|
self.assertEqual(self.remove(), [self.agent(), command])
|
||||||
|
self.assertFalse(self.agent().exists())
|
||||||
|
self.assertFalse(command.exists())
|
||||||
|
|
||||||
|
def test_removing_leaves_another_installers_command_alone(self):
|
||||||
|
command = self.home / ".local/bin/dikte"
|
||||||
|
command.parent.mkdir(parents=True)
|
||||||
|
command.write_text("#!/bin/sh\n# Written by install-mac.sh.\n"
|
||||||
|
"exec /usr/local/bin/python3 /src/__main__.py \"$@\"\n")
|
||||||
|
|
||||||
|
self.assertEqual(self.remove(), [])
|
||||||
|
self.assertIn("install-mac.sh", command.read_text())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user