Compare commits
No commits in common. "main" and "v0.2" have entirely different histories.
|
|
@ -352,7 +352,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.3;
|
MARKETING_VERSION = 0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.MaxSoch.BrewBar;
|
PRODUCT_BUNDLE_IDENTIFIER = com.MaxSoch.BrewBar;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
|
|
@ -400,7 +400,7 @@
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 0.3;
|
MARKETING_VERSION = 0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.MaxSoch.BrewBar;
|
PRODUCT_BUNDLE_IDENTIFIER = com.MaxSoch.BrewBar;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
REGISTER_APP_GROUPS = YES;
|
REGISTER_APP_GROUPS = YES;
|
||||||
|
|
@ -428,7 +428,7 @@
|
||||||
DEVELOPMENT_TEAM = GLVUYYHFD9;
|
DEVELOPMENT_TEAM = GLVUYYHFD9;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 0.3;
|
MARKETING_VERSION = 0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "com.MaxSoch.BrewBarTests";
|
PRODUCT_BUNDLE_IDENTIFIER = "com.MaxSoch.BrewBarTests";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
|
|
@ -449,7 +449,7 @@
|
||||||
DEVELOPMENT_TEAM = GLVUYYHFD9;
|
DEVELOPMENT_TEAM = GLVUYYHFD9;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
MACOSX_DEPLOYMENT_TARGET = 13.0;
|
||||||
MARKETING_VERSION = 0.3;
|
MARKETING_VERSION = 0.2;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "com.MaxSoch.BrewBarTests";
|
PRODUCT_BUNDLE_IDENTIFIER = "com.MaxSoch.BrewBarTests";
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
menu.addItem(upgradeAllItem)
|
menu.addItem(upgradeAllItem)
|
||||||
upgradeOnlyItem = NSMenuItem(title: "🎯 Upgrade only…", action: nil, keyEquivalent: "")
|
upgradeOnlyItem = NSMenuItem(title: "🎯 Upgrade only…", action: nil, keyEquivalent: "")
|
||||||
let upgradeOnlySubmenu = NSMenu()
|
let upgradeOnlySubmenu = NSMenu()
|
||||||
// manual isEnabled control below; otherwise AppKit re-enables the
|
|
||||||
// items from the responder chain every time the menu opens
|
|
||||||
upgradeOnlySubmenu.autoenablesItems = false
|
|
||||||
upgradeFormulaeItem = NSMenuItem(title: "Formulae", action: #selector(upgradeFormulaeOnly), keyEquivalent: "")
|
upgradeFormulaeItem = NSMenuItem(title: "Formulae", action: #selector(upgradeFormulaeOnly), keyEquivalent: "")
|
||||||
upgradeCasksItem = NSMenuItem(title: "Casks", action: #selector(upgradeCasksOnly), keyEquivalent: "")
|
upgradeCasksItem = NSMenuItem(title: "Casks", action: #selector(upgradeCasksOnly), keyEquivalent: "")
|
||||||
upgradeOnlySubmenu.addItem(upgradeFormulaeItem)
|
upgradeOnlySubmenu.addItem(upgradeFormulaeItem)
|
||||||
|
|
@ -366,14 +363,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
// packages that turn outdated only after this brew update are not
|
// packages that turn outdated only after this brew update are not
|
||||||
// in cachedOutdated yet; the final refetch will surface them
|
// in cachedOutdated yet; the final refetch will surface them
|
||||||
let formulaNames = formulae ? self.cachedOutdated.formulae.map(\.name) : []
|
let formulaNames = formulae ? self.cachedOutdated.formulae.map(\.name) : []
|
||||||
var caskNames = casks ? self.cachedOutdated.casks.map(\.name) : []
|
let caskNames = casks ? self.cachedOutdated.casks.map(\.name) : []
|
||||||
if Settings.skipRunningCasksManual, !caskNames.isEmpty {
|
|
||||||
let running = RunningApps.runningCasks(caskNames, brewPath: self.resolveBrewPath())
|
|
||||||
if !running.isEmpty {
|
|
||||||
self.log("upgrade: skipping running app\(running.count == 1 ? "" : "s"): \(running.joined(separator: ", "))\n")
|
|
||||||
caskNames.removeAll(where: running.contains)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.upgradeFormulaeSequentially(formulaNames) {
|
self.upgradeFormulaeSequentially(formulaNames) {
|
||||||
self.upgradeCasksSequentially(caskNames) {
|
self.upgradeCasksSequentially(caskNames) {
|
||||||
|
|
@ -453,18 +443,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
alert.messageText = "Upgrade \(packages.count) package\(packages.count == 1 ? "" : "s")?"
|
alert.messageText = "Upgrade \(packages.count) package\(packages.count == 1 ? "" : "s")?"
|
||||||
}
|
}
|
||||||
|
|
||||||
// warn only about apps that are actually running right now, by name
|
// the running-app warning only applies when casks are being upgraded
|
||||||
var lines: [String] = []
|
var lines: [String] = []
|
||||||
if casks {
|
if casks {
|
||||||
let running = RunningApps.runningCasks(cachedOutdated.casks.map(\.name), brewPath: resolveBrewPath())
|
lines.append("Apps upgraded as casks (like a web browser) may be closed and replaced while running, without further warning. Save your work first.")
|
||||||
if !running.isEmpty {
|
|
||||||
let list = running.joined(separator: ", ")
|
|
||||||
if Settings.skipRunningCasksManual {
|
|
||||||
lines.append("Currently running, will be skipped: \(list).")
|
|
||||||
} else {
|
|
||||||
lines.append("Currently running: \(list). These apps may be closed and replaced mid-use, without further warning. Save your work first.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !packages.isEmpty {
|
if !packages.isEmpty {
|
||||||
lines.append(packages.map(\.label).joined(separator: "\n"))
|
lines.append(packages.map(\.label).joined(separator: "\n"))
|
||||||
|
|
@ -510,18 +492,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
// only trigger for the kinds that are both enabled AND outdated —
|
// only trigger for the kinds that are both enabled AND outdated —
|
||||||
// e.g. an outdated cask must not start a pointless formulae upgrade
|
// e.g. an outdated cask must not start a pointless formulae upgrade
|
||||||
let upgradeFormulae = Settings.autoUpgradeFormulae && !outdated.formulae.isEmpty
|
let upgradeFormulae = Settings.autoUpgradeFormulae && !outdated.formulae.isEmpty
|
||||||
var autoCaskNames = Settings.autoUpgradeCasks ? outdated.casks.map(\.name) : []
|
let upgradeCasks = Settings.autoUpgradeCasks && !outdated.casks.isEmpty
|
||||||
// filtered before the trigger decision: a permanently running app
|
if allowAutoUpgrade, upgradeFormulae || upgradeCasks {
|
||||||
// must not start an upgrade cycle that would skip it anyway
|
self.runAutoUpgrade(formulae: upgradeFormulae, casks: upgradeCasks)
|
||||||
if Settings.skipRunningCasksAuto, !autoCaskNames.isEmpty {
|
|
||||||
let running = RunningApps.runningCasks(autoCaskNames, brewPath: self.resolveBrewPath())
|
|
||||||
if !running.isEmpty {
|
|
||||||
self.log("auto-upgrade: skipping running app\(running.count == 1 ? "" : "s"): \(running.joined(separator: ", "))\n")
|
|
||||||
autoCaskNames.removeAll(where: running.contains)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if allowAutoUpgrade, upgradeFormulae || !autoCaskNames.isEmpty {
|
|
||||||
self.runAutoUpgrade(formulae: upgradeFormulae, caskNames: autoCaskNames)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -553,12 +526,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
UNUserNotificationCenter.current().add(request)
|
UNUserNotificationCenter.current().add(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runAutoUpgrade(formulae: Bool, caskNames: [String]) {
|
func runAutoUpgrade(formulae: Bool, casks: Bool) {
|
||||||
statusMenuItem.title = "Auto-upgrading..."
|
statusMenuItem.title = "Auto-upgrading..."
|
||||||
setMenuBarIcon("brewbar-updating")
|
setMenuBarIcon("brewbar-updating")
|
||||||
failedUpgrades = []
|
failedUpgrades = []
|
||||||
|
|
||||||
let formulaNames = formulae ? cachedOutdated.formulae.map(\.name) : []
|
let formulaNames = formulae ? cachedOutdated.formulae.map(\.name) : []
|
||||||
|
let caskNames = casks ? cachedOutdated.casks.map(\.name) : []
|
||||||
|
|
||||||
upgradeFormulaeSequentially(formulaNames) {
|
upgradeFormulaeSequentially(formulaNames) {
|
||||||
self.upgradeCasksSequentially(caskNames) {
|
self.upgradeCasksSequentially(caskNames) {
|
||||||
|
|
@ -573,13 +547,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
outdatedSubmenu.removeAllItems()
|
outdatedSubmenu.removeAllItems()
|
||||||
outdatedItem.isHidden = outdated.isEmpty
|
outdatedItem.isHidden = outdated.isEmpty
|
||||||
upgradeAllItem.isHidden = outdated.isEmpty
|
upgradeAllItem.isHidden = outdated.isEmpty
|
||||||
// visible whenever anything is outdated; a kind with nothing to
|
// "only" is meaningful only when both kinds are outdated; with a
|
||||||
// upgrade stays listed but greyed out
|
// single kind, the main item already upgrades exactly what there is
|
||||||
upgradeOnlyItem.isHidden = outdated.isEmpty
|
upgradeOnlyItem.isHidden = outdated.formulae.isEmpty || outdated.casks.isEmpty
|
||||||
upgradeFormulaeItem.title = outdated.formulae.isEmpty ? "Formulae" : "Formulae (\(outdated.formulae.count))"
|
upgradeFormulaeItem.title = "Formulae (\(outdated.formulae.count))"
|
||||||
upgradeFormulaeItem.isEnabled = !outdated.formulae.isEmpty
|
upgradeCasksItem.title = "Casks (\(outdated.casks.count))"
|
||||||
upgradeCasksItem.title = outdated.casks.isEmpty ? "Casks" : "Casks (\(outdated.casks.count))"
|
|
||||||
upgradeCasksItem.isEnabled = !outdated.casks.isEmpty
|
|
||||||
|
|
||||||
for package in outdated.all {
|
for package in outdated.all {
|
||||||
let item = NSMenuItem(title: package.label, action: #selector(upgradeSingle(_:)), keyEquivalent: "")
|
let item = NSMenuItem(title: package.label, action: #selector(upgradeSingle(_:)), keyEquivalent: "")
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,8 @@ struct OutdatedPackage: Codable, Equatable {
|
||||||
|
|
||||||
/// Menu label, e.g. "wget 1.21 → 1.22"
|
/// Menu label, e.g. "wget 1.21 → 1.22"
|
||||||
var label: String {
|
var label: String {
|
||||||
let installed = installedVersions.map(Self.displayVersion).joined(separator: ", ")
|
let installed = installedVersions.joined(separator: ", ")
|
||||||
return "\(name) \(installed) → \(Self.displayVersion(currentVersion))"
|
return "\(name) \(installed) → \(currentVersion)"
|
||||||
}
|
|
||||||
|
|
||||||
/// Some casks (e.g. claude: "1.20186.9,69f150a4c9…") version themselves
|
|
||||||
/// as "user-facing-version,build-id" — the part after the comma only
|
|
||||||
/// matters for brew's own download URL, never for display.
|
|
||||||
static func displayVersion(_ version: String) -> String {
|
|
||||||
String(version.split(separator: ",", maxSplits: 1)[0])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
import AppKit
|
|
||||||
|
|
||||||
/// Maps installed casks to their .app bundles and checks them against the
|
|
||||||
/// apps currently running. The mapping comes from the Caskroom: brew keeps
|
|
||||||
/// a copy of every installed cask's artifacts there, so listing
|
|
||||||
/// <prefix>/Caskroom/<token>/<version>/*.app gives the app names without
|
|
||||||
/// spawning a brew process.
|
|
||||||
enum RunningApps {
|
|
||||||
/// Caskroom lives next to the brew binary: <prefix>/bin/brew → <prefix>/Caskroom
|
|
||||||
static func caskroomURL(brewPath: String) -> URL {
|
|
||||||
URL(fileURLWithPath: brewPath)
|
|
||||||
.deletingLastPathComponent() // <prefix>/bin
|
|
||||||
.deletingLastPathComponent() // <prefix>
|
|
||||||
.appendingPathComponent("Caskroom", isDirectory: true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// .app bundle names (e.g. "Firefox.app") found in any installed version
|
|
||||||
/// of the cask. Casks without an app artifact (fonts, pkg-based
|
|
||||||
/// installers) return [] and are never considered running.
|
|
||||||
static func appNames(forCask token: String, brewPath: String) -> [String] {
|
|
||||||
let caskDir = caskroomURL(brewPath: brewPath).appendingPathComponent(token, isDirectory: true)
|
|
||||||
let fm = FileManager.default
|
|
||||||
guard let versions = try? fm.contentsOfDirectory(atPath: caskDir.path) else { return [] }
|
|
||||||
|
|
||||||
var names: Set<String> = []
|
|
||||||
for version in versions where !version.hasPrefix(".") {
|
|
||||||
let versionDir = caskDir.appendingPathComponent(version, isDirectory: true)
|
|
||||||
for entry in (try? fm.contentsOfDirectory(atPath: versionDir.path)) ?? [] where entry.hasSuffix(".app") {
|
|
||||||
names.insert(entry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Array(names)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Subset of the given cask tokens whose app is currently running.
|
|
||||||
/// Matches on the bundle name — the running copy lives in /Applications,
|
|
||||||
/// the Caskroom one is brew's, but both carry the same name.
|
|
||||||
static func runningCasks(_ tokens: [String], brewPath: String) -> [String] {
|
|
||||||
let running = Set(NSWorkspace.shared.runningApplications.compactMap {
|
|
||||||
$0.bundleURL?.lastPathComponent
|
|
||||||
})
|
|
||||||
return tokens.filter { token in
|
|
||||||
appNames(forCask: token, brewPath: brewPath).contains { running.contains($0) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -12,7 +12,6 @@ enum Settings {
|
||||||
UserDefaults.standard.register(defaults: [
|
UserDefaults.standard.register(defaults: [
|
||||||
"includeGreedyCasks": true,
|
"includeGreedyCasks": true,
|
||||||
"confirmBeforeUpgradeAll": true,
|
"confirmBeforeUpgradeAll": true,
|
||||||
"skipRunningCasksAuto": true,
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,18 +49,4 @@ enum Settings {
|
||||||
get { UserDefaults.standard.bool(forKey: "cleanupAfterUpgrade") }
|
get { UserDefaults.standard.bool(forKey: "cleanupAfterUpgrade") }
|
||||||
set { UserDefaults.standard.set(newValue, forKey: "cleanupAfterUpgrade") }
|
set { UserDefaults.standard.set(newValue, forKey: "cleanupAfterUpgrade") }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// auto-upgrade never touches a cask whose app is running (on by default:
|
|
||||||
/// there is no dialog to warn anyone in that flow)
|
|
||||||
static var skipRunningCasksAuto: Bool {
|
|
||||||
get { UserDefaults.standard.bool(forKey: "skipRunningCasksAuto") }
|
|
||||||
set { UserDefaults.standard.set(newValue, forKey: "skipRunningCasksAuto") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// manual bulk upgrades skip running apps too (off by default: the
|
|
||||||
/// confirmation dialog already names them)
|
|
||||||
static var skipRunningCasksManual: Bool {
|
|
||||||
get { UserDefaults.standard.bool(forKey: "skipRunningCasksManual") }
|
|
||||||
set { UserDefaults.standard.set(newValue, forKey: "skipRunningCasksManual") }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,6 @@ class SettingsWindowController: NSWindowController {
|
||||||
var showCountCheckbox: NSButton!
|
var showCountCheckbox: NSButton!
|
||||||
var confirmCheckbox: NSButton!
|
var confirmCheckbox: NSButton!
|
||||||
var cleanupCheckbox: NSButton!
|
var cleanupCheckbox: NSButton!
|
||||||
var skipRunningAutoCheckbox: NSButton!
|
|
||||||
var skipRunningManualCheckbox: NSButton!
|
|
||||||
|
|
||||||
convenience init(appDelegate: AppDelegate) {
|
convenience init(appDelegate: AppDelegate) {
|
||||||
let window = NSWindow(
|
let window = NSWindow(
|
||||||
|
|
@ -110,26 +108,6 @@ class SettingsWindowController: NSWindowController {
|
||||||
"⚠️ Upgrading a cask can close and replace the app while it is running (e.g. your browser), without warning."
|
"⚠️ Upgrading a cask can close and replace the app while it is running (e.g. your browser), without warning."
|
||||||
)
|
)
|
||||||
|
|
||||||
let runningAppsHeader = NSTextField(labelWithString: "Running apps")
|
|
||||||
runningAppsHeader.font = .boldSystemFont(ofSize: NSFont.smallSystemFontSize)
|
|
||||||
runningAppsHeader.textColor = .secondaryLabelColor
|
|
||||||
|
|
||||||
skipRunningAutoCheckbox = NSButton(
|
|
||||||
checkboxWithTitle: "Auto-upgrade: skip casks whose app is running",
|
|
||||||
target: self,
|
|
||||||
action: #selector(toggleSkipRunningAuto(_:))
|
|
||||||
)
|
|
||||||
|
|
||||||
skipRunningManualCheckbox = NSButton(
|
|
||||||
checkboxWithTitle: "Manual upgrades: skip them too",
|
|
||||||
target: self,
|
|
||||||
action: #selector(toggleSkipRunningManual(_:))
|
|
||||||
)
|
|
||||||
|
|
||||||
let runningAppsNote = noteRow(
|
|
||||||
"Skipped apps stay in the outdated list and upgrade at the first check after they quit. Upgrading a single package from the Outdated menu always proceeds."
|
|
||||||
)
|
|
||||||
|
|
||||||
notifyCheckbox = NSButton(
|
notifyCheckbox = NSButton(
|
||||||
checkboxWithTitle: "Notify when new updates are found",
|
checkboxWithTitle: "Notify when new updates are found",
|
||||||
target: self,
|
target: self,
|
||||||
|
|
@ -164,11 +142,6 @@ class SettingsWindowController: NSWindowController {
|
||||||
autoUpgradeCasksCheckbox,
|
autoUpgradeCasksCheckbox,
|
||||||
caskWarningRow,
|
caskWarningRow,
|
||||||
separator(),
|
separator(),
|
||||||
runningAppsHeader,
|
|
||||||
skipRunningAutoCheckbox,
|
|
||||||
skipRunningManualCheckbox,
|
|
||||||
runningAppsNote,
|
|
||||||
separator(),
|
|
||||||
notifyCheckbox,
|
notifyCheckbox,
|
||||||
showCountCheckbox,
|
showCountCheckbox,
|
||||||
confirmCheckbox,
|
confirmCheckbox,
|
||||||
|
|
@ -215,8 +188,6 @@ class SettingsWindowController: NSWindowController {
|
||||||
showCountCheckbox.state = Settings.showCountInMenuBar ? .on : .off
|
showCountCheckbox.state = Settings.showCountInMenuBar ? .on : .off
|
||||||
confirmCheckbox.state = Settings.confirmBeforeUpgradeAll ? .on : .off
|
confirmCheckbox.state = Settings.confirmBeforeUpgradeAll ? .on : .off
|
||||||
cleanupCheckbox.state = Settings.cleanupAfterUpgrade ? .on : .off
|
cleanupCheckbox.state = Settings.cleanupAfterUpgrade ? .on : .off
|
||||||
skipRunningAutoCheckbox.state = Settings.skipRunningCasksAuto ? .on : .off
|
|
||||||
skipRunningManualCheckbox.state = Settings.skipRunningCasksManual ? .on : .off
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func separator() -> NSBox {
|
func separator() -> NSBox {
|
||||||
|
|
@ -353,14 +324,6 @@ class SettingsWindowController: NSWindowController {
|
||||||
Settings.cleanupAfterUpgrade = sender.state == .on
|
Settings.cleanupAfterUpgrade = sender.state == .on
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func toggleSkipRunningAuto(_ sender: NSButton) {
|
|
||||||
Settings.skipRunningCasksAuto = sender.state == .on
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func toggleSkipRunningManual(_ sender: NSButton) {
|
|
||||||
Settings.skipRunningCasksManual = sender.state == .on
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc func toggleLaunchAtLogin(_ sender: NSButton) {
|
@objc func toggleLaunchAtLogin(_ sender: NSButton) {
|
||||||
do {
|
do {
|
||||||
if sender.state == .on {
|
if sender.state == .on {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,6 @@
|
||||||
@testable import BrewBar
|
@testable import BrewBar
|
||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
final class RunningAppsTests: XCTestCase {
|
|
||||||
func testCaskroomURL_appleSilicon() {
|
|
||||||
let url = RunningApps.caskroomURL(brewPath: "/opt/homebrew/bin/brew")
|
|
||||||
XCTAssertEqual(url.path, "/opt/homebrew/Caskroom")
|
|
||||||
}
|
|
||||||
|
|
||||||
func testCaskroomURL_intel() {
|
|
||||||
let url = RunningApps.caskroomURL(brewPath: "/usr/local/bin/brew")
|
|
||||||
XCTAssertEqual(url.path, "/usr/local/Caskroom")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class BrewParserTests: XCTestCase {
|
final class BrewParserTests: XCTestCase {
|
||||||
// MARK: - parseOutdatedJSON
|
// MARK: - parseOutdatedJSON
|
||||||
|
|
||||||
|
|
@ -64,15 +52,6 @@ final class BrewParserTests: XCTestCase {
|
||||||
XCTAssertEqual(package.label, "wget 1.21.3 → 1.21.4")
|
XCTAssertEqual(package.label, "wget 1.21.3 → 1.21.4")
|
||||||
}
|
}
|
||||||
|
|
||||||
func testParseOutdatedJSON_packageLabel_stripsBuildIdAfterComma() {
|
|
||||||
let package = OutdatedPackage(
|
|
||||||
name: "claude",
|
|
||||||
installedVersions: ["1.20185.0,5e8f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f"],
|
|
||||||
currentVersion: "1.20186.9,69f150a4c9316d5c8cd7b9f130ed583d15c0383e"
|
|
||||||
)
|
|
||||||
XCTAssertEqual(package.label, "claude 1.20185.0 → 1.20186.9")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - parseVersion
|
// MARK: - parseVersion
|
||||||
|
|
||||||
func testParseVersion_picksFirstLine() {
|
func testParseVersion_picksFirstLine() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
cask "brewbar" do
|
cask "brewbar" do
|
||||||
version "0.3"
|
version "0.2"
|
||||||
sha256 "d87a744e034c2ce0f92a24c3ebba167533419f948337a2dbedd393152d08d13d"
|
sha256 "dc449ec93f44698acf5de671675b06fbe66bcd40639153c8fe8bae92f569469e"
|
||||||
|
|
||||||
url "https://forgejo.socheleau.fr/maxsoch/BrewBar/releases/download/v#{version}/BrewBar-#{version}.zip"
|
url "https://forgejo.socheleau.fr/maxsoch/BrewBar/releases/download/v#{version}/BrewBar-#{version}.zip"
|
||||||
name "BrewBar"
|
name "BrewBar"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue