89 lines
4.5 KiB
Python
89 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
from pathlib import Path
|
|
from datetime import datetime
|
|
import shutil
|
|
|
|
root = Path.cwd()
|
|
controller = root / 'OrionToolbar/OrionVMController.swift'
|
|
view = root / 'OrionToolbar/OrionMenuView.swift'
|
|
if not controller.exists() or not view.exists():
|
|
raise SystemExit('Run from the OrionToolbar project root. No changes made.')
|
|
c = controller.read_text()
|
|
v = view.read_text()
|
|
|
|
# Verify all expected anchors before writing anything.
|
|
checks = [
|
|
(c, 'await discoverVMs()\n await refreshAll()', 1),
|
|
(c, 'await self.discoverVMs(); await self.refreshAll()', 1),
|
|
(c, 'func refreshServiceAvailability() async {', 1),
|
|
(c, 'func openSSH(_ s: ServerDefinition) {', 1),
|
|
(c, 'func openMailpit(_ s: ServerDefinition) { if let p = s.mailpitPort, let url = URL(string: "http://\\(s.host):\\(p)") { NSWorkspace.shared.open(url) } }', 1),
|
|
(v, 'if !server.host.isEmpty && !server.sshUser.isEmpty {', 2),
|
|
(v, 'if !server.host.isEmpty && server.mailpitPort != nil {', 2),
|
|
]
|
|
for src, anchor, count in checks:
|
|
if src.count(anchor) != count:
|
|
raise SystemExit(f'Expected {count} occurrence(s) of {anchor!r}, found {src.count(anchor)}. No changes made.')
|
|
|
|
c = c.replace('await discoverVMs()\n await refreshAll()', 'await discoverVMs()\n await refreshAll()\n await refreshServiceAvailability()', 1)
|
|
c = c.replace('await self.discoverVMs(); await self.refreshAll()', 'await self.discoverVMs(); await self.refreshAll(); await self.refreshServiceAvailability()', 1)
|
|
|
|
# Dismiss the menu bar panel before activating external apps. This must happen
|
|
# at the click site; delayed activation alone leaves the panel in front.
|
|
helper = ''' private func dismissMenuPanelAndActivate(_ application: NSRunningApplication?) {
|
|
NSApp.keyWindow?.orderOut(nil)
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
|
|
application?.activate(options: [.activateAllWindows])
|
|
}
|
|
}
|
|
|
|
'''
|
|
if 'private func dismissMenuPanelAndActivate(' not in c:
|
|
c = c.replace(' func openSSH(_ s: ServerDefinition) {', helper + ' func openSSH(_ s: ServerDefinition) {', 1)
|
|
|
|
old = ''' NSWorkspace.shared.open([scriptURL], withApplicationAt: terminalURL, configuration: configuration) { _, error in
|
|
Task { @MainActor in
|
|
if let error { self.lastError = "Could not open Terminal: \\(error.localizedDescription)" }
|
|
}
|
|
}'''
|
|
new = ''' NSApp.keyWindow?.orderOut(nil)
|
|
NSWorkspace.shared.open([scriptURL], withApplicationAt: terminalURL, configuration: configuration) { app, error in
|
|
Task { @MainActor in
|
|
if let error {
|
|
self.lastError = "Could not open Terminal: \\(error.localizedDescription)"
|
|
} else {
|
|
self.dismissMenuPanelAndActivate(app)
|
|
}
|
|
}
|
|
}'''
|
|
if c.count(old) != 1:
|
|
raise SystemExit('SSH open completion differs from expected. No changes made.')
|
|
c = c.replace(old, new, 1)
|
|
|
|
old_mail = ' func openMailpit(_ s: ServerDefinition) { if let p = s.mailpitPort, let url = URL(string: "http://\\(s.host):\\(p)") { NSWorkspace.shared.open(url) } }'
|
|
new_mail = ''' func openMailpit(_ s: ServerDefinition) {
|
|
guard let port = s.mailpitPort,
|
|
let url = URL(string: "http://\\(s.host):\\(port)") else { return }
|
|
NSApp.keyWindow?.orderOut(nil)
|
|
NSWorkspace.shared.open(url)
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
|
|
if let browser = NSWorkspace.shared.frontmostApplication,
|
|
browser.bundleIdentifier != Bundle.main.bundleIdentifier {
|
|
browser.activate(options: [.activateAllWindows])
|
|
}
|
|
}
|
|
}'''
|
|
c = c.replace(old_mail, new_mail, 1)
|
|
|
|
v = v.replace('if !server.host.isEmpty && !server.sshUser.isEmpty {', 'if !server.host.isEmpty && !server.sshUser.isEmpty && vm.reachableSSH.contains(server.id) {')
|
|
v = v.replace('if !server.host.isEmpty && server.mailpitPort != nil {', 'if !server.host.isEmpty && server.mailpitPort != nil && vm.reachableMailpit.contains(server.id) {')
|
|
|
|
backup = root / 'backups' / ('service-foreground-' + datetime.now().strftime('%Y%m%d-%H%M%S'))
|
|
for path, content in [(controller, c), (view, v)]:
|
|
dest = backup / path.relative_to(root)
|
|
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(path, dest)
|
|
path.write_text(content)
|
|
print('Updated:', path.relative_to(root))
|
|
print('Backup:', backup)
|