diff --git a/AltBackup/Info.plist b/AltBackup/Info.plist index 87318f17..f3345af1 100644 --- a/AltBackup/Info.plist +++ b/AltBackup/Info.plist @@ -37,6 +37,8 @@ BuildRevision $(BUILD_REVISION) + BuildChannel + $(BUILD_CHANNEL) CFBundleVersion $(CURRENT_PROJECT_VERSION) LSRequiresIPhoneOS diff --git a/AltStore.xcodeproj/project.pbxproj b/AltStore.xcodeproj/project.pbxproj index 914ff9a8..b2cab4ba 100644 --- a/AltStore.xcodeproj/project.pbxproj +++ b/AltStore.xcodeproj/project.pbxproj @@ -65,6 +65,8 @@ A86315DF2D3EB2DE0048FA40 /* ErrorProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = A86315DE2D3EB2D80048FA40 /* ErrorProcessing.swift */; }; A868CFE42D31999A002F1201 /* SingletonGenericMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = A868CFE32D319988002F1201 /* SingletonGenericMap.swift */; }; A8696EE42D34512C00E96389 /* RemoveAppExtensionsOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8696EE32D34512C00E96389 /* RemoveAppExtensionsOperation.swift */; }; + A888EAD52D401D8F0026F7E3 /* BuildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A888EAD42D401D8A0026F7E3 /* BuildInfo.swift */; }; + A888EAD62D4020770026F7E3 /* BuildInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = A888EAD42D401D8A0026F7E3 /* BuildInfo.swift */; }; A88B8C492D35AD3200F53F9D /* OperationsLoggingContolView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88B8C482D35AD3200F53F9D /* OperationsLoggingContolView.swift */; }; A88B8C552D35F1EC00F53F9D /* OperationsLoggingControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = A88B8C542D35F1EC00F53F9D /* OperationsLoggingControl.swift */; }; A8945AA62D059B6100D86CBE /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8945AA52D059B6100D86CBE /* Roxas.framework */; }; @@ -649,6 +651,7 @@ A86315DE2D3EB2D80048FA40 /* ErrorProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorProcessing.swift; sourceTree = ""; }; A868CFE32D319988002F1201 /* SingletonGenericMap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingletonGenericMap.swift; sourceTree = ""; }; A8696EE32D34512C00E96389 /* RemoveAppExtensionsOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveAppExtensionsOperation.swift; sourceTree = ""; }; + A888EAD42D401D8A0026F7E3 /* BuildInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildInfo.swift; sourceTree = ""; }; A88B8C482D35AD3200F53F9D /* OperationsLoggingContolView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationsLoggingContolView.swift; sourceTree = ""; }; A88B8C542D35F1EC00F53F9D /* OperationsLoggingControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationsLoggingControl.swift; sourceTree = ""; }; A8945AA52D059B6100D86CBE /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1224,6 +1227,14 @@ path = errors; sourceTree = ""; }; + A888EAD32D401D7C0026F7E3 /* buildinfo */ = { + isa = PBXGroup; + children = ( + A888EAD42D401D8A0026F7E3 /* BuildInfo.swift */, + ); + path = buildinfo; + sourceTree = ""; + }; A88B8C532D35F1E800F53F9D /* operations */ = { isa = PBXGroup; children = ( @@ -1288,6 +1299,7 @@ A8C38C1C2D2068D100E83DBD /* Utils */ = { isa = PBXGroup; children = ( + A888EAD32D401D7C0026F7E3 /* buildinfo */, A8AD35572D31BEB2003A28B4 /* datastructures */, A8A853AD2D3050CC00995795 /* pagination */, A8087E712D2D291B002DB21B /* importexport */, @@ -2910,6 +2922,7 @@ 0E05025C2BEC947000879B5C /* String+SideStore.swift in Sources */, 0EE7FDCB2BE8D12B00D1E390 /* ALTLocalizedError.swift in Sources */, BF66EEA92501AEC5007EE018 /* Tier.swift in Sources */, + A888EAD62D4020770026F7E3 /* BuildInfo.swift in Sources */, BF66EEDB2501AECA007EE018 /* StoreApp.swift in Sources */, D5CE309C2B4C946300DB8151 /* AltStore15ToAltStore16.xcmappingmodel in Sources */, BF66EEDE2501AECA007EE018 /* AppID.swift in Sources */, @@ -3054,6 +3067,7 @@ BFF00D302501BD7D00746320 /* Intents.intentdefinition in Sources */, D5B6F6AB2AD76541007EED5A /* PreviewAppScreenshotsViewController.swift in Sources */, BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */, + A888EAD52D401D8F0026F7E3 /* BuildInfo.swift in Sources */, BF41B806233423AE00C593A3 /* TabBarController.swift in Sources */, BFE00A202503097F00EB4D0C /* INInteraction+AltStore.swift in Sources */, BFDB6A0B22AAEDB7007EA6D6 /* Operation.swift in Sources */, diff --git a/AltStore/Info.plist b/AltStore/Info.plist index cfe47fc9..031b11d9 100644 --- a/AltStore/Info.plist +++ b/AltStore/Info.plist @@ -83,6 +83,8 @@ $(CURRENT_PROJECT_VERSION) BuildRevision $(BUILD_REVISION) + BuildChannel + $(BUILD_CHANNEL) INIntentsSupported RefreshAllIntent diff --git a/AltStore/Settings/SettingsViewController.swift b/AltStore/Settings/SettingsViewController.swift index 88e09eb4..26d066c4 100644 --- a/AltStore/Settings/SettingsViewController.swift +++ b/AltStore/Settings/SettingsViewController.swift @@ -211,20 +211,11 @@ private extension SettingsViewController { private func getVersionLabel() -> String { - let MARKETING_VERSION_KEY = "CFBundleShortVersionString" - let BUILD_REVISION = "CFBundleRevision" // commit ID for now (but could be any, set by build env vars - let CURRENT_PROJECT_VERSION = kCFBundleVersionKey as String + let buildInfo = BuildInfo() func getXcodeVersion() -> String { - let XCODE_VERSION = "DTXcode" - let XCODE_REVISION = "DTXcodeBuild" - - let xcode = Bundle.main.object(forInfoDictionaryKey: XCODE_VERSION) as? String - let build = Bundle.main.object(forInfoDictionaryKey: XCODE_REVISION) as? String - - var xcodeVersion = xcode.map { version in -// " - Xcode \(version) - " + (build.map { revision in "\(revision)" } ?? "") // Ex: "0.6.0 - Xcode 16.2 - 21ac1ef" - "Xcode \(version) - " + (build.map { revision in "\(revision)" } ?? "") // Ex: "0.6.0 - Xcode 16.2 - 21ac1ef" + var xcodeVersion = buildInfo.xcode.map { version in + "Xcode \(version)" + (buildInfo.xcode_revision.map { revision in " - \(revision)" } ?? "") // Ex: "0.6.0 - Xcode 16.2 - 21ac1ef" } ?? "" if let pairing = Bundle.main.object(forInfoDictionaryKey: "ALTPairingFile") as? String, @@ -234,26 +225,25 @@ private extension SettingsViewController return xcodeVersion } + var versionLabel: String = "" if let installedApp = InstalledApp.fetchAltStore(in: DatabaseManager.shared.viewContext) { - #if BETA - // Only show build version (and build revision) for BETA builds. - let bundleVersion: String? = Bundle.main.object(forInfoDictionaryKey: CURRENT_PROJECT_VERSION) as? String - let buildRevision: String? = Bundle.main.object(forInfoDictionaryKey: BUILD_REVISION) as? String + let isStableBuild = (buildInfo.channel == .stable) + let revision = buildInfo.revision ?? "" - var localizedVersion = bundleVersion.map { version in - "\(installedApp.version) (\(version))" + (buildRevision.map { revision in " - \(revision)" } ?? "") // Ex: "0.6.0 (0600) - 1acdef3" - } ?? installedApp.localizedVersion - - #else var localizedVersion = installedApp.version - #endif - + // Only show build version (and build revision) for non stable builds. + if !isStableBuild { + localizedVersion += buildInfo.project_version.map{ version in + version.isEmpty ? "" : " (\(version))" + (revision.isEmpty ? "" : " - \(revision)") + } ?? installedApp.localizedVersion + } + versionLabel = NSLocalizedString(String(format: "Version %@", localizedVersion), comment: "SideStore Version") } - else if let version = Bundle.main.object(forInfoDictionaryKey: MARKETING_VERSION_KEY) as? String + else if let version = buildInfo.marketing_version { var version = "SideStore \(version)" @@ -268,10 +258,11 @@ private extension SettingsViewController versionLabel = NSLocalizedString(version, comment: "SideStore Version") } - // add xcode build version if in debug mode - #if DEBUG - versionLabel += "\n\(getXcodeVersion())" - #endif + // add xcode build version for local builds + if buildInfo.channel == .local + { + versionLabel += "\n\(getXcodeVersion())" + } return versionLabel } diff --git a/AltStoreCore/Info.plist b/AltStoreCore/Info.plist index cebb1257..cc1fbfd2 100644 --- a/AltStoreCore/Info.plist +++ b/AltStoreCore/Info.plist @@ -18,6 +18,8 @@ $(MARKETING_VERSION) BuildRevision $(BUILD_REVISION) + BuildChannel + $(BUILD_CHANNEL) CFBundleVersion $(CURRENT_PROJECT_VERSION) diff --git a/AltWidget/Info.plist b/AltWidget/Info.plist index cf410522..31fda5f7 100644 --- a/AltWidget/Info.plist +++ b/AltWidget/Info.plist @@ -24,6 +24,8 @@ $(MARKETING_VERSION) BuildRevision $(BUILD_REVISION) + BuildChannel + $(BUILD_CHANNEL) CFBundleVersion $(CURRENT_PROJECT_VERSION) NSExtension diff --git a/Build.xcconfig b/Build.xcconfig index 93135631..d46cb8d0 100644 --- a/Build.xcconfig +++ b/Build.xcconfig @@ -3,6 +3,7 @@ MARKETING_VERSION = 0.6.0 CURRENT_PROJECT_VERSION = 6000 +BUILD_CHANNEL = stable // Vars to be overwritten by `CodeSigning.xcconfig` if exists DEVELOPMENT_TEAM = S32Z3HMYVQ diff --git a/CodeSigning.xcconfig.sample b/CodeSigning.xcconfig.sample index e0a5f1b0..31a8c67a 100644 --- a/CodeSigning.xcconfig.sample +++ b/CodeSigning.xcconfig.sample @@ -15,6 +15,10 @@ ORG_IDENTIFIER = com.myuniquename // we don't want to do this for release since those builds will most likely be installed via SideServer, which adds the team ID BUNDLE_ID_SUFFIX = .$(DEVELOPMENT_TEAM) +// Comment this out to use default 'stable' channel defined in Build.xcconfig +// For local xcode or commandline builds we can use local channel for local build specific logic +BUILD_CHANNEL = local + // Set to YES if you have a valid paid Apple Developer account DEVELOPER_ACCOUNT_PAID = NO diff --git a/SideStore/Utils/buildinfo/BuildInfo.swift b/SideStore/Utils/buildinfo/BuildInfo.swift new file mode 100644 index 00000000..5e800ba1 --- /dev/null +++ b/SideStore/Utils/buildinfo/BuildInfo.swift @@ -0,0 +1,58 @@ +// +// BuildInfo.swift +// AltStore +// +// Created by Magesh K on 21/01/25. +// Copyright © 2025 SideStore. All rights reserved. +// + +public class BuildInfo{ + private static let BUILD_REVISION_TAG = "BuildRevision" // commit ID for now (but could be any, set by build env vars + private static let BUILD_CHANNEL_TAG = "BuildChannel" // set by build env, ex CI will set it via env vars, for xcode builds this is empty + + private static let MARKETING_VERSION_TAG = "CFBundleShortVersionString" + private static let CURRENT_PROJECT_VERSION_TAG = kCFBundleVersionKey as String + + private static let XCODE_VERSION_TAG = "DTXcode" + private static let XCODE_REVISION_TAG = "DTXcodeBuild" + + public enum Channel: String { + case unknown + case local // xcodebuilds can use this by setting BUILD_CHANNEL in CodeSigning.xcconfig + + case alpha + case beta + case stable + } + + public lazy var channel: Channel = { + let channel = Bundle.main.object(forInfoDictionaryKey: Self.BUILD_CHANNEL_TAG) as? String + return Channel(rawValue: channel ?? "") ?? .unknown + }() + + public lazy var revision: String? = { + let revision = Bundle.main.object(forInfoDictionaryKey: Self.BUILD_REVISION_TAG) as? String + return revision + }() + + public lazy var project_version: String? = { + let revision = Bundle.main.object(forInfoDictionaryKey: Self.CURRENT_PROJECT_VERSION_TAG) as? String + return revision + }() + + public lazy var marketing_version: String? = { + let revision = Bundle.main.object(forInfoDictionaryKey: Self.MARKETING_VERSION_TAG) as? String + return revision + }() + + public lazy var xcode: String? = { + let xcode = Bundle.main.object(forInfoDictionaryKey: Self.XCODE_VERSION_TAG) as? String + return xcode + }() + + public lazy var xcode_revision: String? = { + let revision = Bundle.main.object(forInfoDictionaryKey: Self.XCODE_REVISION_TAG) as? String + return revision + }() + +}