2 Commits

Author SHA1 Message Date
cdricms
c675a98309 Better reactivity and functionality 2024-07-09 20:29:20 +02:00
cdricms
bd9c351b7c The app is starting to look good 2024-07-09 15:00:09 +02:00
20 changed files with 1673 additions and 0 deletions

View File

@@ -0,0 +1,636 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 56;
objects = {
/* Begin PBXBuildFile section */
9E6C73072C3D5E570056ADDC /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6C73062C3D5E570056ADDC /* SearchView.swift */; };
9E6C73092C3D5E950056ADDC /* InstalledView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6C73082C3D5E950056ADDC /* InstalledView.swift */; };
9E6C730C2C3D796D0056ADDC /* DownloadButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6C730B2C3D796D0056ADDC /* DownloadButton.swift */; };
9E6C730E2C3DB16F0056ADDC /* UninstallButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6C730D2C3DB16F0056ADDC /* UninstallButton.swift */; };
9E6C73112C3DB5940056ADDC /* CaskDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6C73102C3DB5940056ADDC /* CaskDetailView.swift */; };
9E8CE5362C3C545600A39146 /* BrewerApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E8CE5352C3C545600A39146 /* BrewerApp.swift */; };
9E8CE5382C3C545600A39146 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E8CE5372C3C545600A39146 /* ContentView.swift */; };
9E8CE53A2C3C545700A39146 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9E8CE5392C3C545700A39146 /* Assets.xcassets */; };
9E8CE53D2C3C545700A39146 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9E8CE53C2C3C545700A39146 /* Preview Assets.xcassets */; };
9E8CE5482C3C545800A39146 /* BrewerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E8CE5472C3C545800A39146 /* BrewerTests.swift */; };
9E8CE5522C3C545800A39146 /* BrewerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E8CE5512C3C545800A39146 /* BrewerUITests.swift */; };
9E8CE5542C3C545800A39146 /* BrewerUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E8CE5532C3C545800A39146 /* BrewerUITestsLaunchTests.swift */; };
9E8CE5622C3C5A6A00A39146 /* Homebrew.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E8CE5612C3C5A6A00A39146 /* Homebrew.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
9E8CE5442C3C545800A39146 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 9E8CE52A2C3C545600A39146 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 9E8CE5312C3C545600A39146;
remoteInfo = Brewer;
};
9E8CE54E2C3C545800A39146 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 9E8CE52A2C3C545600A39146 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 9E8CE5312C3C545600A39146;
remoteInfo = Brewer;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
9E6C73062C3D5E570056ADDC /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
9E6C73082C3D5E950056ADDC /* InstalledView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledView.swift; sourceTree = "<group>"; };
9E6C730B2C3D796D0056ADDC /* DownloadButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadButton.swift; sourceTree = "<group>"; };
9E6C730D2C3DB16F0056ADDC /* UninstallButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UninstallButton.swift; sourceTree = "<group>"; };
9E6C73102C3DB5940056ADDC /* CaskDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CaskDetailView.swift; sourceTree = "<group>"; };
9E8CE5322C3C545600A39146 /* Brewer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Brewer.app; sourceTree = BUILT_PRODUCTS_DIR; };
9E8CE5352C3C545600A39146 /* BrewerApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrewerApp.swift; sourceTree = "<group>"; };
9E8CE5372C3C545600A39146 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
9E8CE5392C3C545700A39146 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
9E8CE53C2C3C545700A39146 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
9E8CE53E2C3C545700A39146 /* Brewer.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Brewer.entitlements; sourceTree = "<group>"; };
9E8CE5432C3C545800A39146 /* BrewerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BrewerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
9E8CE5472C3C545800A39146 /* BrewerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrewerTests.swift; sourceTree = "<group>"; };
9E8CE54D2C3C545800A39146 /* BrewerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BrewerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
9E8CE5512C3C545800A39146 /* BrewerUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrewerUITests.swift; sourceTree = "<group>"; };
9E8CE5532C3C545800A39146 /* BrewerUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrewerUITestsLaunchTests.swift; sourceTree = "<group>"; };
9E8CE5612C3C5A6A00A39146 /* Homebrew.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Homebrew.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
9E8CE52F2C3C545600A39146 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
9E8CE5402C3C545800A39146 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
9E8CE54A2C3C545800A39146 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9E6C730A2C3D795D0056ADDC /* Components */ = {
isa = PBXGroup;
children = (
9E6C730B2C3D796D0056ADDC /* DownloadButton.swift */,
9E6C730D2C3DB16F0056ADDC /* UninstallButton.swift */,
);
path = Components;
sourceTree = "<group>";
};
9E6C730F2C3DB5850056ADDC /* Details */ = {
isa = PBXGroup;
children = (
9E6C73102C3DB5940056ADDC /* CaskDetailView.swift */,
);
name = Details;
sourceTree = "<group>";
};
9E8CE5292C3C545600A39146 = {
isa = PBXGroup;
children = (
9E8CE5342C3C545600A39146 /* Brewer */,
9E8CE5462C3C545800A39146 /* BrewerTests */,
9E8CE5502C3C545800A39146 /* BrewerUITests */,
9E8CE5332C3C545600A39146 /* Products */,
);
sourceTree = "<group>";
};
9E8CE5332C3C545600A39146 /* Products */ = {
isa = PBXGroup;
children = (
9E8CE5322C3C545600A39146 /* Brewer.app */,
9E8CE5432C3C545800A39146 /* BrewerTests.xctest */,
9E8CE54D2C3C545800A39146 /* BrewerUITests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
9E8CE5342C3C545600A39146 /* Brewer */ = {
isa = PBXGroup;
children = (
9E6C730A2C3D795D0056ADDC /* Components */,
9E8CE5602C3C5A5000A39146 /* Model */,
9E8CE5352C3C545600A39146 /* BrewerApp.swift */,
9E6C73062C3D5E570056ADDC /* SearchView.swift */,
9E6C730F2C3DB5850056ADDC /* Details */,
9E6C73082C3D5E950056ADDC /* InstalledView.swift */,
9E8CE5372C3C545600A39146 /* ContentView.swift */,
9E8CE5392C3C545700A39146 /* Assets.xcassets */,
9E8CE53E2C3C545700A39146 /* Brewer.entitlements */,
9E8CE53B2C3C545700A39146 /* Preview Content */,
);
path = Brewer;
sourceTree = "<group>";
};
9E8CE53B2C3C545700A39146 /* Preview Content */ = {
isa = PBXGroup;
children = (
9E8CE53C2C3C545700A39146 /* Preview Assets.xcassets */,
);
path = "Preview Content";
sourceTree = "<group>";
};
9E8CE5462C3C545800A39146 /* BrewerTests */ = {
isa = PBXGroup;
children = (
9E8CE5472C3C545800A39146 /* BrewerTests.swift */,
);
path = BrewerTests;
sourceTree = "<group>";
};
9E8CE5502C3C545800A39146 /* BrewerUITests */ = {
isa = PBXGroup;
children = (
9E8CE5512C3C545800A39146 /* BrewerUITests.swift */,
9E8CE5532C3C545800A39146 /* BrewerUITestsLaunchTests.swift */,
);
path = BrewerUITests;
sourceTree = "<group>";
};
9E8CE5602C3C5A5000A39146 /* Model */ = {
isa = PBXGroup;
children = (
9E8CE5612C3C5A6A00A39146 /* Homebrew.swift */,
);
path = Model;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
9E8CE5312C3C545600A39146 /* Brewer */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9E8CE5572C3C545800A39146 /* Build configuration list for PBXNativeTarget "Brewer" */;
buildPhases = (
9E8CE52E2C3C545600A39146 /* Sources */,
9E8CE52F2C3C545600A39146 /* Frameworks */,
9E8CE5302C3C545600A39146 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = Brewer;
productName = Brewer;
productReference = 9E8CE5322C3C545600A39146 /* Brewer.app */;
productType = "com.apple.product-type.application";
};
9E8CE5422C3C545800A39146 /* BrewerTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9E8CE55A2C3C545800A39146 /* Build configuration list for PBXNativeTarget "BrewerTests" */;
buildPhases = (
9E8CE53F2C3C545800A39146 /* Sources */,
9E8CE5402C3C545800A39146 /* Frameworks */,
9E8CE5412C3C545800A39146 /* Resources */,
);
buildRules = (
);
dependencies = (
9E8CE5452C3C545800A39146 /* PBXTargetDependency */,
);
name = BrewerTests;
productName = BrewerTests;
productReference = 9E8CE5432C3C545800A39146 /* BrewerTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
9E8CE54C2C3C545800A39146 /* BrewerUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 9E8CE55D2C3C545800A39146 /* Build configuration list for PBXNativeTarget "BrewerUITests" */;
buildPhases = (
9E8CE5492C3C545800A39146 /* Sources */,
9E8CE54A2C3C545800A39146 /* Frameworks */,
9E8CE54B2C3C545800A39146 /* Resources */,
);
buildRules = (
);
dependencies = (
9E8CE54F2C3C545800A39146 /* PBXTargetDependency */,
);
name = BrewerUITests;
productName = BrewerUITests;
productReference = 9E8CE54D2C3C545800A39146 /* BrewerUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
9E8CE52A2C3C545600A39146 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1540;
LastUpgradeCheck = 1540;
TargetAttributes = {
9E8CE5312C3C545600A39146 = {
CreatedOnToolsVersion = 15.4;
};
9E8CE5422C3C545800A39146 = {
CreatedOnToolsVersion = 15.4;
TestTargetID = 9E8CE5312C3C545600A39146;
};
9E8CE54C2C3C545800A39146 = {
CreatedOnToolsVersion = 15.4;
TestTargetID = 9E8CE5312C3C545600A39146;
};
};
};
buildConfigurationList = 9E8CE52D2C3C545600A39146 /* Build configuration list for PBXProject "Brewer" */;
compatibilityVersion = "Xcode 14.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 9E8CE5292C3C545600A39146;
productRefGroup = 9E8CE5332C3C545600A39146 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
9E8CE5312C3C545600A39146 /* Brewer */,
9E8CE5422C3C545800A39146 /* BrewerTests */,
9E8CE54C2C3C545800A39146 /* BrewerUITests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
9E8CE5302C3C545600A39146 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9E8CE53D2C3C545700A39146 /* Preview Assets.xcassets in Resources */,
9E8CE53A2C3C545700A39146 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9E8CE5412C3C545800A39146 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
9E8CE54B2C3C545800A39146 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
9E8CE52E2C3C545600A39146 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9E6C73072C3D5E570056ADDC /* SearchView.swift in Sources */,
9E6C730C2C3D796D0056ADDC /* DownloadButton.swift in Sources */,
9E8CE5382C3C545600A39146 /* ContentView.swift in Sources */,
9E6C730E2C3DB16F0056ADDC /* UninstallButton.swift in Sources */,
9E8CE5622C3C5A6A00A39146 /* Homebrew.swift in Sources */,
9E6C73092C3D5E950056ADDC /* InstalledView.swift in Sources */,
9E8CE5362C3C545600A39146 /* BrewerApp.swift in Sources */,
9E6C73112C3DB5940056ADDC /* CaskDetailView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9E8CE53F2C3C545800A39146 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9E8CE5482C3C545800A39146 /* BrewerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
9E8CE5492C3C545800A39146 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
9E8CE5522C3C545800A39146 /* BrewerUITests.swift in Sources */,
9E8CE5542C3C545800A39146 /* BrewerUITestsLaunchTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
9E8CE5452C3C545800A39146 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 9E8CE5312C3C545600A39146 /* Brewer */;
targetProxy = 9E8CE5442C3C545800A39146 /* PBXContainerItemProxy */;
};
9E8CE54F2C3C545800A39146 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 9E8CE5312C3C545600A39146 /* Brewer */;
targetProxy = 9E8CE54E2C3C545800A39146 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
9E8CE5552C3C545800A39146 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 14.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
9E8CE5562C3C545800A39146 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MACOSX_DEPLOYMENT_TARGET = 14.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
};
name = Release;
};
9E8CE5582C3C545800A39146 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Brewer/Brewer.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Brewer/Preview Content\"";
DEVELOPMENT_TEAM = 96S93Z7LTG;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_LSUIElement = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.cems.Brewer;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
9E8CE5592C3C545800A39146 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Brewer/Brewer.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_ASSET_PATHS = "\"Brewer/Preview Content\"";
DEVELOPMENT_TEAM = 96S93Z7LTG;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_LSUIElement = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.cems.Brewer;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Release;
};
9E8CE55B2C3C545800A39146 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 96S93Z7LTG;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.cems.BrewerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Brewer.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Brewer";
};
name = Debug;
};
9E8CE55C2C3C545800A39146 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 96S93Z7LTG;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 14.5;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.cems.BrewerTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Brewer.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Brewer";
};
name = Release;
};
9E8CE55E2C3C545800A39146 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 96S93Z7LTG;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.cems.BrewerUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_TARGET_NAME = Brewer;
};
name = Debug;
};
9E8CE55F2C3C545800A39146 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 96S93Z7LTG;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.cems.BrewerUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_TARGET_NAME = Brewer;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
9E8CE52D2C3C545600A39146 /* Build configuration list for PBXProject "Brewer" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9E8CE5552C3C545800A39146 /* Debug */,
9E8CE5562C3C545800A39146 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9E8CE5572C3C545800A39146 /* Build configuration list for PBXNativeTarget "Brewer" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9E8CE5582C3C545800A39146 /* Debug */,
9E8CE5592C3C545800A39146 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9E8CE55A2C3C545800A39146 /* Build configuration list for PBXNativeTarget "BrewerTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9E8CE55B2C3C545800A39146 /* Debug */,
9E8CE55C2C3C545800A39146 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
9E8CE55D2C3C545800A39146 /* Build configuration list for PBXNativeTarget "BrewerUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
9E8CE55E2C3C545800A39146 /* Debug */,
9E8CE55F2C3C545800A39146 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 9E8CE52A2C3C545600A39146 /* Project object */;
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,58 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

42
Brewer/BrewerApp.swift Normal file
View File

@@ -0,0 +1,42 @@
//
// BrewerApp.swift
// Brewer
//
// Created by Cédric MAS on 08/07/2024.
//
import SwiftUI
@main
struct BrewerApp: App {
@AppStorage("isUpToDate") var isUpToDate: Bool = true
init() {
do {
let res = try shell("/opt/homebrew/bin/brew outdated --greedy-latest -g | wc -l")
if let number = Int(res.trimmingCharacters(in: .whitespacesAndNewlines)), number > 0 {
isUpToDate = false
}
} catch {
print(error.localizedDescription)
}
}
var body: some Scene {
WindowGroup {
EmptyView()
}
MenuBarExtra {
ContentView().padding()
} label: {
if isUpToDate {
Label("Brewer", systemImage: "sparkle.magnifyingglass")
} else {
Label("Brewer", systemImage: "sparkle.magnifyingglass")
.symbolRenderingMode(.palette)
.foregroundStyle(.orange)
}
}
.menuBarExtraStyle(.window)
}
}

View File

@@ -0,0 +1,38 @@
//
// CaskDetailView.swift
// Brewer
//
// Created by Cédric MAS on 09/07/2024.
//
import SwiftUI
struct CaskDetailView: View {
var cask: Cask
@Bindable var brewListing: Homebrew
var body: some View {
NavigationStack {
VStack {
Text("Identifier: \(cask.fullToken)")
Text("Version: \(cask.version)")
}
.navigationTitle(cask.name.first ?? cask.fullToken)
.toolbar {
ToolbarItem(placement: .primaryAction) {
if cask.installed == nil {
DownloadButton(name: cask.fullToken, isCask: true)
} else if cask.outdated {
Button("Update") {
}
}
}
if cask.installed != nil {
ToolbarItem(placement: .primaryAction) {
UninstallButton(name: cask.fullToken, brewListing: brewListing)
}
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
//
// DownloadButton.swift
// Brewer
//
// Created by Cédric MAS on 09/07/2024.
//
import SwiftUI
struct DownloadButton: View {
let name: String
var isCask: Bool = false
@State private var brew = Homebrew()
@State private var downloaded = false
var body: some View {
VStack {
if downloaded {
Image(systemName: "checkmark")
.symbolRenderingMode(.palette)
.symbolVariant(.circle)
.symbolVariant(.fill)
.foregroundStyle(.white, .green)
} else if brew.isLoading {
ProgressView()
.controlSize(.small)
} else if brew.errorMessage != nil {
Image(systemName: "x")
.symbolRenderingMode(.palette)
.symbolVariant(.circle)
.symbolVariant(.fill)
.foregroundStyle(.white, .red)
} else {
Button("Get") {
Task {
downloaded = await brew.install(name, isCask: isCask)
}
}
.buttonBorderShape(.capsule)
.buttonStyle(.borderedProminent)
}
}
.onAppear {
Task {
downloaded = await brew.isDownloaded(name)
}
}
}
}
#Preview {
DownloadButton(name: "firefox")
}

View File

@@ -0,0 +1,45 @@
//
// UninstallButton.swift
// Brewer
//
// Created by Cédric MAS on 09/07/2024.
//
import SwiftUI
struct UninstallButton: View {
let name: String
@State private var brew = Homebrew()
@State private var uninstalled = false
@Bindable var brewListing: Homebrew
var body: some View {
VStack {
if uninstalled {
EmptyView()
} else if brew.isLoading {
ProgressView()
.controlSize(.small)
} else if brew.errorMessage != nil {
Image(systemName: "x")
.symbolRenderingMode(.palette)
.symbolVariant(.circle)
.symbolVariant(.fill)
.foregroundStyle(.white, .red)
} else {
Button("Uninstall", role: .destructive) {
Task {
uninstalled = await brew.uninstall(name)
brewListing.getInstalled()
}
}
.buttonBorderShape(.capsule)
.buttonStyle(.borderedProminent)
}
}
.onAppear {
Task {
uninstalled = await brew.isDownloaded(name)
}
}
}
}

36
Brewer/ContentView.swift Normal file
View File

@@ -0,0 +1,36 @@
//
// ContentView.swift
// Brewer
//
// Created by Cédric MAS on 08/07/2024.
//
import SwiftUI
enum SegementedSelection: String, CaseIterable {
case search = "Search"
case installed = "Installed"
}
struct ContentView: View {
@State private var segmentedSelection: SegementedSelection = .search
var body: some View {
NavigationStack {
Picker("", selection: $segmentedSelection) {
ForEach(SegementedSelection.allCases, id: \.self) { sel in
Text(sel.rawValue).tag(sel)
}
}.pickerStyle(.segmented)
switch segmentedSelection {
case .search:
SearchView()
case .installed:
InstalledView()
}
}
}
}
#Preview {
ContentView()
}

108
Brewer/InstalledView.swift Normal file
View File

@@ -0,0 +1,108 @@
//
// InstalledView.swift
// Brewer
//
// Created by Cédric MAS on 09/07/2024.
//
import SwiftUI
struct InstalledView: View {
@State private var brew = Homebrew()
var body: some View {
VStack {
if brew.isLoading {
ProgressView("Loading...")
} else if let data = brew.data {
List {
if !data.casks.isEmpty {
Section {
ForEach(data.casks, id: \.fullToken) { cask in
NavigationLink {
CaskDetailView(cask: cask, brewListing: brew)
} label: {
HStack {
Text(cask.name.first ?? cask.fullToken)
Spacer()
if cask.outdated {
Button {
} label: {
Label("Update", systemImage: "arrow.counterclockwise.circle.fill")
.symbolRenderingMode(.palette)
.foregroundStyle(.white, .orange)
}
} else {
Text(cask.version)
}
}
.contextMenu {
UninstallButton(name: cask.fullToken, brewListing: brew)
}
}
}
} header: {
HStack {
Text("Casks")
Spacer()
Text("\(data.casks.count) installed")
}
}
}
if !data.formulae.isEmpty {
Section {
ForEach(data.formulae, id: \.fullName) { formulae in
HStack {
Text(formulae.fullName)
Spacer()
if formulae.outdated {
Button {
} label: {
Label("Update", systemImage: "arrow.counterclockwise.circle.fill")
.symbolRenderingMode(.palette)
.foregroundStyle(.white, .orange)
}
} else {
Text(formulae.versions.stable)
}
}
.contextMenu {
UninstallButton(name: formulae.fullName, brewListing: brew)
}
}
} header: {
HStack {
Text("Formulae")
Spacer()
Text("\(data.formulae.count) installed")
}
}
}
}
.listStyle(.inset(alternatesRowBackgrounds: true))
let areOutdated = data.casks.map(\.outdated).count + data.formulae.map(\.outdated).count
let _ = UserDefaults.standard.set(!(areOutdated > 0), forKey: "isUpToDate")
if areOutdated > 0 {
Button {
} label: {
Label("Update all", systemImage: "arrow.counterclockwise.circle.fill")
}
.buttonStyle(.borderedProminent)
.tint(.orange)
}
} else if let error = brew.errorMessage {
Text(error)
.foregroundStyle(.red)
}
}.task {
brew.getInstalled()
}
}
}
#Preview {
InstalledView()
}

214
Brewer/Model/Homebrew.swift Normal file
View File

@@ -0,0 +1,214 @@
//
// Cask.swift
// Brewer
//
// Created by Cédric MAS on 08/07/2024.
//
import Foundation
enum ShellError: Error {
case emptyOutput
}
@discardableResult
func shell(_ command: String) throws -> String {
let task = Process()
task.executableURL = URL(filePath: "/bin/bash")
task.arguments = ["-c", command]
let pipe = Pipe()
task.standardError = pipe
task.standardOutput = pipe
try task.run()
if let data = try pipe.fileHandleForReading.readToEnd(),
let output = String(data: data, encoding: .utf8)
{
return output
}
throw ShellError.emptyOutput
}
struct Cask: Codable {
let token: String
let fullToken: String
let tap: String
let name: [String]
let desc: String
let homepage: String
let url: String
let version: String
let installed: String?
let outdated: Bool
enum CodingKeys: String, CodingKey {
case token, tap, name, desc, homepage, url, version, installed, outdated
case fullToken = "full_token"
}
}
struct Formulae: Codable {
struct Version: Codable {
let stable: String
let head: String?
let bottle: Bool
enum CodingKeys: String, CodingKey {
case stable
case head, bottle
}
}
let name: String
let fullName: String
let tap: String
let oldNames: [String]
let aliases: [String]
let versionedFormulae: [String]
let desc: String
let license: String?
let homepage: String
let versions: Version
let outdated: Bool
enum CodingKeys: String, CodingKey {
case name
case tap
case aliases
case desc
case license
case homepage
case versions
case outdated
case fullName = "full_name"
case oldNames = "oldnames"
case versionedFormulae = "versioned_formulae"
}
}
struct InfoResponse: Codable {
let formulae: [Formulae]
let casks: [Cask]
enum CodingKeys: String, CodingKey {
case casks
case formulae
}
}
@Observable
class Homebrew {
var data: InfoResponse?
var isLoading = false
var errorMessage: String?
func getInfo(on query: String) {
self.isLoading = true
self.errorMessage = nil
self.data = nil
Task { [weak self] in
do {
let res = try shell("/opt/homebrew/bin/brew info --json=v2 \(query)")
if let data = res.data(using: .utf8) {
let output = try JSONDecoder().decode(InfoResponse.self, from: data)
self?.data = output
}
} catch {
self?.errorMessage = error.localizedDescription
}
self?.isLoading = false
}
}
func getInstalled() {
self.isLoading = true
self.data = nil
self.errorMessage = nil
Task { [weak self] in
do {
let res = try shell("/opt/homebrew/bin/brew info --json=v2 --installed")
if let data = res.data(using: .utf8) {
let output = try JSONDecoder().decode(InfoResponse.self, from: data)
self?.data = output
}
} catch {
self?.errorMessage = error.localizedDescription
}
self?.isLoading = false
}
}
func isDownloaded(_ name: String) async -> Bool {
self.isLoading = true
self.errorMessage = nil
self.data = nil
let task = Task { [weak self] in
do {
let res = try shell("/opt/homebrew/bin/brew list -1 \(name) >/dev/null 2>&1; echo $?")
.trimmingCharacters(in: .whitespacesAndNewlines)
self?.isLoading = false
return res == "0"
} catch {
self?.errorMessage = error.localizedDescription
}
return false
}
switch await task.result {
case .success(let success):
return success
case .failure(let fail):
return false
}
}
func install(_ fullToken: String, isCask: Bool = false) async -> Bool {
self.isLoading = true
self.data = nil
let task = Task { [weak self] in
do {
try shell("/opt/homebrew/bin/brew install \(isCask ? "--cask" : "") \(fullToken)")
} catch {
self?.errorMessage = error.localizedDescription
}
self?.isLoading = false
return await self?.isDownloaded(fullToken) ?? false
}
return switch await task.result {
case .success(let success):
success
case .failure(let fail):
false
}
}
func uninstall(_ fullToken: String) async -> Bool {
self.isLoading = true
self.data = nil
let task = Task { [weak self] in
do {
let res =
try shell("/opt/homebrew/bin/brew uninstall \(fullToken); echo $?")
.trimmingCharacters(in: .whitespacesAndNewlines)
} catch {
self?.errorMessage = error.localizedDescription
}
self?.isLoading = false
return await !(self?.isDownloaded(fullToken) ?? true)
}
return switch await task.result {
case .success(let success):
success
case .failure(let failure):
false
}
}
}

View File

@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

65
Brewer/SearchView.swift Normal file
View File

@@ -0,0 +1,65 @@
//
// SearchView.swift
// Brewer
//
// Created by Cédric MAS on 09/07/2024.
//
import SwiftUI
struct SearchView: View {
@State private var query = ""
@State private var brew = Homebrew()
var body: some View {
VStack {
TextField("Search", text: $query)
.padding()
.padding(.bottom, 0)
.onSubmit {
brew.getInfo(on: query)
}
Spacer()
if brew.isLoading {
ProgressView("Loading...")
} else if let data = brew.data {
List {
if !data.casks.isEmpty {
Section("Casks") {
ForEach(data.casks, id: \.fullToken) { cask in
HStack {
Text(cask.fullToken)
Spacer()
if cask.installed != nil {
Image(systemName: "checkmark.circle.fill")
.symbolRenderingMode(.palette)
.foregroundStyle(.white, .green)
} else {
DownloadButton(name: cask.fullToken, isCask: true)
}
}
}
}
}
if !data.formulae.isEmpty {
Section("Formulaes") {
ForEach(data.formulae, id: \.fullName) { formulae in
HStack {
Text(formulae.fullName)
}
}
}
}
}
} else if let errorMessage = brew.errorMessage {
Text(errorMessage)
.foregroundStyle(.red)
}
}
}
}
#Preview {
SearchView()
}

226
Brewer/formulae.json Normal file
View File

@@ -0,0 +1,226 @@
{
"name": "aom",
"full_name": "aom",
"tap": "homebrew/core",
"oldnames": [],
"aliases": [],
"versioned_formulae": [],
"desc": "Codec library for encoding and decoding AV1 video streams",
"license": "BSD-2-Clause",
"homepage": "https://aomedia.googlesource.com/aom",
"versions": {
"stable": "3.9.1",
"head": null,
"bottle": true
},
"urls": {
"stable": {
"url": "https://aomedia.googlesource.com/aom.git",
"tag": "v3.9.1",
"revision": "8ad484f8a18ed1853c094e7d3a4e023b2a92df28",
"using": null,
"checksum": null
}
},
"revision": 0,
"version_scheme": 0,
"bottle": {
"stable": {
"rebuild": 0,
"root_url": "https://ghcr.io/v2/homebrew/core",
"files": {
"arm64_sonoma": {
"cellar": ":any",
"url": "https://ghcr.io/v2/homebrew/core/aom/blobs/sha256:8cb9a41dca274a535e5cf7ea728a694f3e9621d97ea48fa8fd270cd5d99f0347",
"sha256": "8cb9a41dca274a535e5cf7ea728a694f3e9621d97ea48fa8fd270cd5d99f0347"
},
"arm64_ventura": {
"cellar": ":any",
"url": "https://ghcr.io/v2/homebrew/core/aom/blobs/sha256:7b35304138ab104ff4c05cc78d16fdd6f3a4a19393d50cab274356f0dfc72479",
"sha256": "7b35304138ab104ff4c05cc78d16fdd6f3a4a19393d50cab274356f0dfc72479"
},
"arm64_monterey": {
"cellar": ":any",
"url": "https://ghcr.io/v2/homebrew/core/aom/blobs/sha256:1274fcede1882cd3cd3f176e2a44f461e3dba57f2fa77151722774c77753455b",
"sha256": "1274fcede1882cd3cd3f176e2a44f461e3dba57f2fa77151722774c77753455b"
},
"sonoma": {
"cellar": ":any",
"url": "https://ghcr.io/v2/homebrew/core/aom/blobs/sha256:cb0a6ac49c83d5377c1fe7fdc4df43e403af231c2d6db3398b01cd70b31f1ab7",
"sha256": "cb0a6ac49c83d5377c1fe7fdc4df43e403af231c2d6db3398b01cd70b31f1ab7"
},
"ventura": {
"cellar": ":any",
"url": "https://ghcr.io/v2/homebrew/core/aom/blobs/sha256:7410d19b27f952bc12722457ea58b904a6de0416f3d7ada42cfad2b1cd67e795",
"sha256": "7410d19b27f952bc12722457ea58b904a6de0416f3d7ada42cfad2b1cd67e795"
},
"monterey": {
"cellar": ":any",
"url": "https://ghcr.io/v2/homebrew/core/aom/blobs/sha256:9abf106327c58ffaae970744caad8b9bdace79220ba3ecf4e47fe4eb500f6fb0",
"sha256": "9abf106327c58ffaae970744caad8b9bdace79220ba3ecf4e47fe4eb500f6fb0"
},
"x86_64_linux": {
"cellar": ":any_skip_relocation",
"url": "https://ghcr.io/v2/homebrew/core/aom/blobs/sha256:d018fbe0e71201de17504c3a5ed73f3499dfd36b1b07a09173e826418abd00b8",
"sha256": "d018fbe0e71201de17504c3a5ed73f3499dfd36b1b07a09173e826418abd00b8"
}
}
}
},
"pour_bottle_only_if": null,
"keg_only": false,
"keg_only_reason": null,
"options": [],
"build_dependencies": [
"cmake",
"pkg-config"
],
"dependencies": [
"jpeg-xl",
"libvmaf"
],
"test_dependencies": [],
"recommended_dependencies": [],
"optional_dependencies": [],
"uses_from_macos": [],
"uses_from_macos_bounds": [],
"requirements": [],
"conflicts_with": [],
"conflicts_with_reasons": [],
"link_overwrite": [],
"caveats": null,
"installed": [
{
"version": "3.9.1",
"used_options": [],
"built_as_bottle": true,
"poured_from_bottle": true,
"time": 1718172114,
"runtime_dependencies": [
{
"full_name": "brotli",
"version": "1.1.0",
"revision": 0,
"pkg_version": "1.1.0",
"declared_directly": false
},
{
"full_name": "giflib",
"version": "5.2.2",
"revision": 0,
"pkg_version": "5.2.2",
"declared_directly": false
},
{
"full_name": "highway",
"version": "1.2.0",
"revision": 0,
"pkg_version": "1.2.0",
"declared_directly": false
},
{
"full_name": "imath",
"version": "3.1.11",
"revision": 0,
"pkg_version": "3.1.11",
"declared_directly": false
},
{
"full_name": "jpeg-turbo",
"version": "3.0.3",
"revision": 0,
"pkg_version": "3.0.3",
"declared_directly": false
},
{
"full_name": "libpng",
"version": "1.6.43",
"revision": 0,
"pkg_version": "1.6.43",
"declared_directly": false
},
{
"full_name": "xz",
"version": "5.4.6",
"revision": 0,
"pkg_version": "5.4.6",
"declared_directly": false
},
{
"full_name": "lz4",
"version": "1.9.4",
"revision": 0,
"pkg_version": "1.9.4",
"declared_directly": false
},
{
"full_name": "zstd",
"version": "1.5.6",
"revision": 0,
"pkg_version": "1.5.6",
"declared_directly": false
},
{
"full_name": "libtiff",
"version": "4.6.0",
"revision": 0,
"pkg_version": "4.6.0",
"declared_directly": false
},
{
"full_name": "little-cms2",
"version": "2.16",
"revision": 0,
"pkg_version": "2.16",
"declared_directly": false
},
{
"full_name": "openexr",
"version": "3.2.4",
"revision": 0,
"pkg_version": "3.2.4",
"declared_directly": false
},
{
"full_name": "webp",
"version": "1.4.0",
"revision": 0,
"pkg_version": "1.4.0",
"declared_directly": false
},
{
"full_name": "jpeg-xl",
"version": "0.10.2",
"revision": 0,
"pkg_version": "0.10.2",
"declared_directly": true
},
{
"full_name": "libvmaf",
"version": "3.0.0",
"revision": 0,
"pkg_version": "3.0.0",
"declared_directly": true
}
],
"installed_as_dependency": true,
"installed_on_request": false
}
],
"linked_keg": "3.9.1",
"pinned": false,
"outdated": false,
"deprecated": false,
"deprecation_date": null,
"deprecation_reason": null,
"disabled": false,
"disable_date": null,
"disable_reason": null,
"post_install_defined": false,
"service": null,
"tap_git_head": "e63757f09f6098330ee6073b756d52e9e4957b4b",
"ruby_source_path": "Formula/a/aom.rb",
"ruby_source_checksum": {
"sha256": "3de11c9a16f43364bf721cb6253993143ca9e5c9baeef1e6cb6170ecb176524f"
}
}

View File

@@ -0,0 +1,36 @@
//
// BrewerTests.swift
// BrewerTests
//
// Created by Cédric MAS on 08/07/2024.
//
import XCTest
@testable import Brewer
final class BrewerTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
// Any test you write for XCTest can be annotated as throws and async.
// Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
}
func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}

View File

@@ -0,0 +1,41 @@
//
// BrewerUITests.swift
// BrewerUITests
//
// Created by Cédric MAS on 08/07/2024.
//
import XCTest
final class BrewerUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests its important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
// UI tests must launch the application that they test.
let app = XCUIApplication()
app.launch()
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testLaunchPerformance() throws {
if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
// This measures how long it takes to launch your application.
measure(metrics: [XCTApplicationLaunchMetric()]) {
XCUIApplication().launch()
}
}
}
}

View File

@@ -0,0 +1,32 @@
//
// BrewerUITestsLaunchTests.swift
// BrewerUITests
//
// Created by Cédric MAS on 08/07/2024.
//
import XCTest
final class BrewerUITestsLaunchTests: XCTestCase {
override class var runsForEachTargetApplicationUIConfiguration: Bool {
true
}
override func setUpWithError() throws {
continueAfterFailure = false
}
func testLaunch() throws {
let app = XCUIApplication()
app.launch()
// Insert steps here to perform after app launch but before taking a screenshot,
// such as logging into a test account or navigating somewhere in the app
let attachment = XCTAttachment(screenshot: app.screenshot())
attachment.name = "Launch Screen"
attachment.lifetime = .keepAlways
add(attachment)
}
}