mirror of
https://github.com/munki/munki.git
synced 2026-05-04 11:29:16 -05:00
Convert some comments to documentation
This commit is contained in:
@@ -23,11 +23,11 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Determines if an item is in a list of processed items.
|
||||
///
|
||||
/// Returns true if the item has already been processed (it's in the list)
|
||||
/// and, optionally, the version is the same or greater.
|
||||
func itemInInstallInfo(_ thisItem: PlistDict, theList: [PlistDict], version: String = "") -> Bool {
|
||||
/// Determines if an item is in a list of processed items.
|
||||
///
|
||||
/// Returns true if the item has already been processed (it's in the list)
|
||||
/// and, optionally, the version is the same or greater.
|
||||
for listItem in theList {
|
||||
if let listItemName = listItem["name"] as? String,
|
||||
let thisItemName = thisItem["name"] as? String
|
||||
@@ -56,12 +56,11 @@ func itemInInstallInfo(_ thisItem: PlistDict, theList: [PlistDict], version: Str
|
||||
return false
|
||||
}
|
||||
|
||||
/// Returns true if the item to be installed or removed appears to be from
|
||||
/// Apple. If we are installing or removing any Apple items in a check/install
|
||||
/// cycle, we skip checking/installing Apple updates from an Apple Software
|
||||
/// Update server so we don't stomp on each other
|
||||
func isAppleItem(_ pkginfo: PlistDict) -> Bool {
|
||||
/// Returns True if the item to be installed or removed appears to be from
|
||||
/// Apple. If we are installing or removing any Apple items in a check/install
|
||||
/// cycle, we skip checking/installing Apple updates from an Apple Software
|
||||
/// Update server so we don't stomp on each other
|
||||
|
||||
// is this a startosinstall item?
|
||||
if let installerType = pkginfo["installer_type"] as? String,
|
||||
installerType == "startosinstall"
|
||||
@@ -93,9 +92,9 @@ func isAppleItem(_ pkginfo: PlistDict) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
/// Returns true if itemname has already been added to installinfo in one
|
||||
/// of the given sections
|
||||
func alreadyProcessed(_ itemName: String, installInfo: PlistDict, sections: [String]) -> Bool {
|
||||
/// Returns True if itemname has already been added to installinfo in one
|
||||
/// of the given sections
|
||||
let description = [
|
||||
"processed_installs": "install",
|
||||
"processed_uninstalls": "uninstall",
|
||||
@@ -122,6 +121,13 @@ func alreadyProcessed(_ itemName: String, installInfo: PlistDict, sections: [Str
|
||||
return false
|
||||
}
|
||||
|
||||
/// Processes a manifest item for install. Determines if it needs to be
|
||||
/// installed, and if so, if any items it is dependent on need to
|
||||
/// be installed first. Installation detail is added to
|
||||
/// installinfo['managed_installs']
|
||||
/// Calls itself recursively as it processes dependencies.
|
||||
/// Returns a boolean; when processing dependencies, a false return
|
||||
/// will stop the installation of a dependent item
|
||||
func processInstall(
|
||||
_ manifestItem: String,
|
||||
catalogList: [String],
|
||||
@@ -129,16 +135,8 @@ func processInstall(
|
||||
isManagedUpdate: Bool = false,
|
||||
isOptionalInstall: Bool = false
|
||||
) async -> Bool {
|
||||
/// Processes a manifest item for install. Determines if it needs to be
|
||||
/// installed, and if so, if any items it is dependent on need to
|
||||
/// be installed first. Installation detail is added to
|
||||
/// installinfo['managed_installs']
|
||||
/// Calls itself recursively as it processes dependencies.
|
||||
/// Returns a boolean; when processing dependencies, a false return
|
||||
/// will stop the installation of a dependent item
|
||||
|
||||
/// helper function
|
||||
func appendToProcessedManagedInstalls(_ item: PlistDict) {
|
||||
/// helper function
|
||||
var managedInstalls = installInfo["managed_installs"] as? [PlistDict] ?? []
|
||||
managedInstalls.append(item)
|
||||
installInfo["managed_installs"] = managedInstalls
|
||||
@@ -523,13 +521,12 @@ func processInstall(
|
||||
return true
|
||||
}
|
||||
|
||||
/// Process a managed_updates item to see if it is installed, and if so, if it needs an update.
|
||||
func processManagedUpdate(
|
||||
_ manifestItem: String,
|
||||
catalogList: [String],
|
||||
installInfo: inout PlistDict
|
||||
) async {
|
||||
/// Process a managed_updates item to see if it is installed, and if so,
|
||||
/// if it needs an update.
|
||||
let manifestItemName = (manifestItem as NSString).lastPathComponent
|
||||
displayDebug1("* Processing manifest item \(manifestItemName) for update")
|
||||
|
||||
@@ -562,13 +559,13 @@ func processManagedUpdate(
|
||||
}
|
||||
}
|
||||
|
||||
/// Process an optional install item to see if it should be added to
|
||||
/// the list of optional installs
|
||||
func processOptionalInstall(
|
||||
_ manifestItem: String,
|
||||
catalogList: [String],
|
||||
installInfo: inout PlistDict
|
||||
) async {
|
||||
// Process an optional install item to see if it should be added to
|
||||
// the list of optional installs
|
||||
let manifestItemName = (manifestItem as NSString).lastPathComponent
|
||||
displayDebug1("* Processing manifest item \(manifestItemName) for optional install")
|
||||
|
||||
@@ -762,28 +759,27 @@ func processOptionalInstall(
|
||||
installInfo["optional_installs"] = optionalInstalls
|
||||
}
|
||||
|
||||
/// Processes a manifest item; attempts to determine if it
|
||||
/// needs to be removed, and if it can be removed.
|
||||
///
|
||||
/// Unlike installs, removals aren't really version-specific -
|
||||
/// If we can figure out how to remove the currently installed
|
||||
/// version, we do, unless the admin specifies a specific version
|
||||
/// number in the manifest. In that case, we only attempt a
|
||||
/// removal if the version installed matches the specific version
|
||||
/// in the manifest.
|
||||
///
|
||||
/// Any items dependent on the given item need to be removed first.
|
||||
/// Items to be removed are added to installinfo['removals'].
|
||||
///
|
||||
/// Calls itself recursively as it processes dependencies.
|
||||
/// Returns a boolean; when processing dependencies, a false return
|
||||
/// will stop the removal of a dependent item.
|
||||
func processRemoval(
|
||||
_ manifestItem: String,
|
||||
catalogList: [String],
|
||||
installInfo: inout PlistDict
|
||||
) async -> Bool {
|
||||
/// Processes a manifest item; attempts to determine if it
|
||||
/// needs to be removed, and if it can be removed.
|
||||
///
|
||||
/// Unlike installs, removals aren't really version-specific -
|
||||
/// If we can figure out how to remove the currently installed
|
||||
/// version, we do, unless the admin specifies a specific version
|
||||
/// number in the manifest. In that case, we only attempt a
|
||||
/// removal if the version installed matches the specific version
|
||||
/// in the manifest.
|
||||
///
|
||||
/// Any items dependent on the given item need to be removed first.
|
||||
/// Items to be removed are added to installinfo['removals'].
|
||||
///
|
||||
/// Calls itself recursively as it processes dependencies.
|
||||
/// Returns a boolean; when processing dependencies, a false return
|
||||
/// will stop the removal of a dependent item.
|
||||
|
||||
func getReceiptsToRemove(_ item: PlistDict) async -> [String] {
|
||||
/// Returns a list of (installed/present) receipts to remove for item
|
||||
if let name = item["name"] as? String {
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
/// a Singleton class to track catalog data
|
||||
class Catalogs {
|
||||
/// a Singleton class to track catalog data
|
||||
static let shared = Catalogs()
|
||||
|
||||
var db: [String: PlistDict]
|
||||
@@ -33,6 +33,7 @@ class Catalogs {
|
||||
|
||||
typealias CatalogDBTable = [String: [String: [Int]]]
|
||||
|
||||
/// Creates a dict we use like a database to query the catalogs for info
|
||||
func makeCatalogDB(_ catalogItems: [PlistDict]) -> PlistDict {
|
||||
var nameTable = CatalogDBTable()
|
||||
var pkgidTable = CatalogDBTable()
|
||||
@@ -111,14 +112,14 @@ func makeCatalogDB(_ catalogItems: [PlistDict]) -> PlistDict {
|
||||
return pkgdb
|
||||
}
|
||||
|
||||
/// Adds packageids from each catalogitem to two dictionaries.
|
||||
/// One maps itemnames to receipt pkgids, the other maps receipt pkgids
|
||||
/// to itemnames
|
||||
func addPackageIDs(
|
||||
_ catalogItems: [PlistDict],
|
||||
itemNameToPkgID: inout [String: [String: [String]]],
|
||||
pkgidToItemName: inout [String: [String: [String]]]
|
||||
) {
|
||||
/// Adds packageids from each catalogitem to two dictionaries.
|
||||
/// One maps itemnames to receipt pkgids, the other maps receipt pkgids
|
||||
/// to itemnames
|
||||
for item in catalogItems {
|
||||
guard let name = item["name"] as? String else {
|
||||
continue
|
||||
@@ -158,13 +159,12 @@ func addPackageIDs(
|
||||
}
|
||||
}
|
||||
|
||||
/// Searches the catalogs in a list for all items matching a given name.
|
||||
///
|
||||
/// Returns:
|
||||
/// list of pkginfo items; sorted with newest version first. No precedence
|
||||
/// is given to catalog order.
|
||||
func getAllItemsWithName(_ name: String, catalogList: [String]) -> [PlistDict] {
|
||||
/// Searches the catalogs in a list for all items matching a given name.
|
||||
///
|
||||
/// Returns:
|
||||
/// list of pkginfo items; sorted with newest version first. No precedence
|
||||
/// is given to catalog order.
|
||||
|
||||
var itemList = [PlistDict]()
|
||||
let itemName = nameAndVersion(name, onlySplitOnHyphens: true).0
|
||||
|
||||
@@ -199,13 +199,13 @@ func getAllItemsWithName(_ name: String, catalogList: [String]) -> [PlistDict] {
|
||||
return itemList
|
||||
}
|
||||
|
||||
/// Gets a list of items marked for automatic removal from the catalogs
|
||||
/// in cataloglist. Filters those against items in the processed_installs
|
||||
/// list, and managed_install list, which, together, should contain everything
|
||||
/// that is supposed to be installed.
|
||||
/// Then filters against the removals list, which contains all the removals
|
||||
/// that have already been processed.
|
||||
func getAutoRemovalItems(installInfo: PlistDict, catalogList: [String]) -> [String] {
|
||||
/// Gets a list of items marked for automatic removal from the catalogs
|
||||
/// in cataloglist. Filters those against items in the processed_installs
|
||||
/// list, and managed_install list, which, together, should contain everything
|
||||
/// that is supposed to be installed.
|
||||
/// Then filters against the removals list, which contains all the removals
|
||||
/// that have already been processed.
|
||||
var autoremovalNames = [String]()
|
||||
for catalogName in catalogList {
|
||||
if let catalogDB = Catalogs.shared.get(catalogName),
|
||||
@@ -237,16 +237,14 @@ func getAutoRemovalItems(installInfo: PlistDict, catalogList: [String]) -> [Stri
|
||||
return autoremovalNames
|
||||
}
|
||||
|
||||
/// Looks for updates for a given manifest item that is either
|
||||
/// installed or scheduled to be installed or removed. This handles not only
|
||||
/// specific application updates, but also updates that aren't simply
|
||||
/// later versions of the manifest item.
|
||||
/// For example, AdobeCameraRaw might be an update for Adobe Photoshop, but
|
||||
/// doesn't update the version of Adobe Photoshop.
|
||||
/// Returns a list of item names that are updates for manifestItem.
|
||||
func lookForUpdatesFor(_ manifestItem: String, catalogList: [String]) -> [String] {
|
||||
/// Looks for updates for a given manifest item that is either
|
||||
/// installed or scheduled to be installed or removed. This handles not only
|
||||
/// specific application updates, but also updates that aren't simply
|
||||
/// later versions of the manifest item.
|
||||
/// For example, AdobeCameraRaw might be an update for Adobe Photoshop, but
|
||||
/// doesn't update the version of Adobe Photoshop.
|
||||
/// Returns a list of item names that are updates for
|
||||
/// manifestItem.
|
||||
|
||||
displayDebug1("Looking for updates for: \(manifestItem)")
|
||||
// get a list of catalog items that are updates for other items
|
||||
var updateList = [String]()
|
||||
@@ -291,15 +289,13 @@ func lookForUpdatesForName(_ manifestname: String,
|
||||
return Array(Set(updateList))
|
||||
}
|
||||
|
||||
/// Attempts to find the best match in itemDict for version
|
||||
func bestVersionMatch(version _: String, itemDict _: [String: [String]]) -> String? {
|
||||
/// Attempts to find the best match in itemDict for version
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Analyze catalog data and installed packages in an attempt to determine what is installed.
|
||||
func analyzeInstalledPkgs() async -> PlistDict {
|
||||
/// Analyze catalog data and installed packages in an attempt to determine
|
||||
/// what is installed.
|
||||
|
||||
var itemNameToPkgID = [String: [String: [String]]]()
|
||||
var pkgidToItemName = [String: [String: [String]]]()
|
||||
for catalogName in Catalogs.shared.list() {
|
||||
@@ -431,6 +427,14 @@ func analyzeInstalledPkgs() async -> PlistDict {
|
||||
]
|
||||
}
|
||||
|
||||
/// Searches the catalogs in list for an item matching the given name that
|
||||
/// can be installed on the current hardware/OS (optionally skipping the
|
||||
/// minimum OS check so we can return an item that requires a higher OS)
|
||||
///
|
||||
/// If no version is supplied, but the version is appended to the name
|
||||
/// ('TextWrangler--2.3.0.0.0') that version is used.
|
||||
/// If no version is given at all, the latest version is assumed.
|
||||
/// Returns a pkginfo item, or nil.
|
||||
func getItemDetail(
|
||||
_ itemName: String,
|
||||
catalogList: [String],
|
||||
@@ -438,22 +442,13 @@ func getItemDetail(
|
||||
skipMinimumOSCheck: Bool = false,
|
||||
suppressWarnings: Bool = false
|
||||
) async -> PlistDict? {
|
||||
/// Searches the catalogs in list for an item matching the given name that
|
||||
/// can be installed on the current hardware/OS (optionally skipping the
|
||||
/// minimum OS check so we can return an item that requires a higher OS)
|
||||
///
|
||||
/// If no version is supplied, but the version is appended to the name
|
||||
/// ('TextWrangler--2.3.0.0.0') that version is used.
|
||||
/// If no version is given at all, the latest version is assumed.
|
||||
/// Returns a pkginfo item, or None.
|
||||
|
||||
var rejectedItems = [String]()
|
||||
let machine = await getMachineFacts()
|
||||
|
||||
/// Returns a boolean to indicate if the current Munki version is high
|
||||
/// enough to install this item. If not, also adds the failure reason to
|
||||
/// the rejected_items list.
|
||||
func munkiVersionOK(_ item: PlistDict) -> Bool {
|
||||
/// Returns a boolean to indicate if the current Munki version is high
|
||||
/// enough to install this item. If not, also adds the failure reason to
|
||||
/// the rejected_items list.
|
||||
guard let name = item["name"] as? String,
|
||||
let version = item["version"] as? String,
|
||||
let munkiVersion = machine["munki_version"] as? String
|
||||
@@ -474,11 +469,11 @@ func getItemDetail(
|
||||
return true
|
||||
}
|
||||
|
||||
/// Returns a boolean to indicate if the item is ok to install under
|
||||
/// the current OS. If not, also adds the failure reason to the
|
||||
/// rejected_items list. If skipMinimumOSCheck is true, skips the minimum os
|
||||
/// version check.
|
||||
func osVersionOK(_ item: PlistDict) -> Bool {
|
||||
/// Returns a boolean to indicate if the item is ok to install under
|
||||
/// the current OS. If not, also adds the failure reason to the
|
||||
/// rejected_items list. If skipMinimumOSCheck is true, skips the minimum os
|
||||
/// version check.
|
||||
guard let name = item["name"] as? String,
|
||||
let version = item["version"] as? String,
|
||||
let osVersion = machine["os_vers"] as? String
|
||||
@@ -516,10 +511,10 @@ func getItemDetail(
|
||||
return true
|
||||
}
|
||||
|
||||
/// Returns a boolean to indicate if the item is ok to install under
|
||||
/// the current CPU architecture. If not, also adds the failure reason to
|
||||
/// the rejected_items list.
|
||||
func cpuArchOK(_ item: PlistDict) -> Bool {
|
||||
/// Returns a boolean to indicate if the item is ok to install under
|
||||
/// the current CPU architecture. If not, also adds the failure reason to
|
||||
/// the rejected_items list.
|
||||
guard let name = item["name"] as? String,
|
||||
let version = item["version"] as? String,
|
||||
let currentArch = machine["arch"] as? String
|
||||
@@ -551,10 +546,10 @@ func getItemDetail(
|
||||
return true
|
||||
}
|
||||
|
||||
/// Returns a boolean to indicate if an installable_condition predicate
|
||||
/// in the current item passes. If not, also adds the failure reason to
|
||||
/// the rejected_items list.
|
||||
func installableConditionOK(_ item: PlistDict) async -> Bool {
|
||||
/// Returns a boolean to indicate if an installable_condition predicate
|
||||
/// in the current item passes. If not, also adds the failure reason to
|
||||
/// the rejected_items list.
|
||||
if let installableCondition = item["installable_condition"] as? String {
|
||||
let infoObject = await predicateInfoObject()
|
||||
if !predicateEvaluatesAsTrue(installableCondition, infoObject: infoObject) {
|
||||
@@ -636,9 +631,8 @@ func getItemDetail(
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Retrieves the catalogs from the server and populates our Catalogs object.
|
||||
func getCatalogs(_ catalogList: [String]) {
|
||||
/// Retrieves the catalogs from the server and populates our Catalogs
|
||||
/// object.
|
||||
for catalogName in catalogList {
|
||||
if Catalogs.shared.list().contains(catalogName) {
|
||||
continue
|
||||
@@ -662,8 +656,8 @@ func getCatalogs(_ catalogList: [String]) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes any catalog files that are no longer in use by this client
|
||||
func cleanUpCatalogs() {
|
||||
/// Removes any catalog files that are no longer in use by this client
|
||||
let catalogsToKeep = Catalogs.shared.list()
|
||||
let catalogsDir = managedInstallsDir(subpath: "catalogs")
|
||||
cleanUpDir(catalogsDir, keeping: catalogsToKeep)
|
||||
|
||||
@@ -23,10 +23,9 @@ let comparisonResultDescriptions = [
|
||||
"newer",
|
||||
]
|
||||
|
||||
/// Compares two version numbers to one another.
|
||||
/// Returns MunkiComparisonResult (one of .older, .same, .newer)
|
||||
func compareVersions(_ thisVersion: String, _ thatVersion: String) -> MunkiComparisonResult {
|
||||
// Compares two version numbers to one another.
|
||||
//
|
||||
// Returns MunkiComparisonResult (one of .older, .same, .newer)
|
||||
if MunkiVersion(thisVersion) < MunkiVersion(thatVersion) {
|
||||
return .older
|
||||
}
|
||||
@@ -36,10 +35,9 @@ func compareVersions(_ thisVersion: String, _ thatVersion: String) -> MunkiCompa
|
||||
return .newer
|
||||
}
|
||||
|
||||
/// Gets the version string from the plist at path and compares versions with plistItem
|
||||
/// May throw a MunkiError if there's an error in the input
|
||||
func comparePlistVersion(_ item: PlistDict) throws -> MunkiComparisonResult {
|
||||
// Gets the version string from the plist at path
|
||||
// and compares versions with plistItem
|
||||
// May throw a MunkiError if there's an error in the input
|
||||
let versionComparisonKey = item["version_comparison_key"] as? String ?? "CFBundleShortVersionString"
|
||||
guard let path = item["path"] as? String,
|
||||
let versionString = item[versionComparisonKey] as? String
|
||||
@@ -82,9 +80,9 @@ func comparePlistVersion(_ item: PlistDict) throws -> MunkiComparisonResult {
|
||||
return comparisonResult
|
||||
}
|
||||
|
||||
/// Compares bundle described in bundleItem with what is actually on-disk.
|
||||
/// May throw a MunkiError if there's an error in the input
|
||||
func compareBundleVersion(_ bundleItem: PlistDict) throws -> MunkiComparisonResult {
|
||||
// Compares bundle described in bundleItem with what is actually on-disk.
|
||||
// May throw a MunkiError if there's an error in the input
|
||||
if let path = bundleItem["path"] as? NSString {
|
||||
var infoPlistPath = path.appendingPathComponent("Contents/Info.plist")
|
||||
if !pathExists(infoPlistPath) {
|
||||
@@ -103,11 +101,11 @@ func compareBundleVersion(_ bundleItem: PlistDict) throws -> MunkiComparisonResu
|
||||
return .notPresent
|
||||
}
|
||||
|
||||
/// Compares app described in appItem with what is actually on-disk.
|
||||
/// Checks the given path if it's available,
|
||||
/// otherwise uses LaunchServices and/or Spotlight to look for the app
|
||||
/// May throw a MunkiError if there's an error in the input
|
||||
func compareApplicationVersion(_ appItem: PlistDict) throws -> MunkiComparisonResult {
|
||||
// Compares app described in appItem with what is actually on-disk.
|
||||
// Checks the given path if it's available,
|
||||
// otherwise uses LaunchServices and/or Spotlight to look for the app
|
||||
// May throw a MunkiError if there's an error in the input
|
||||
if let path = appItem["path"] as? String {
|
||||
if !pathExists(path) {
|
||||
displayDebug2("Application is not present at \(path).")
|
||||
@@ -178,14 +176,13 @@ func compareApplicationVersion(_ appItem: PlistDict) throws -> MunkiComparisonRe
|
||||
return endResult
|
||||
}
|
||||
|
||||
/// Returns the status of the local filesystem item as compared to
|
||||
/// the passed-in dictionary
|
||||
///
|
||||
/// If item has md5checksum attribute, compares on disk file's checksum.
|
||||
///
|
||||
/// Throws a MunkiError if there's a problwm with the input
|
||||
func filesystemItemStatus(_ item: PlistDict) throws -> MunkiComparisonResult {
|
||||
// returns the status of the local filesystem item as compared to
|
||||
// the passed-in dictionary
|
||||
//
|
||||
// If item has md5checksum attribute, compares on disk file's checksum.
|
||||
//
|
||||
// Throws a MunkiError if there's a problwm with the input
|
||||
|
||||
guard let filepath = item["path"] as? String else {
|
||||
throw MunkiError("No path specified for filesystem item")
|
||||
}
|
||||
@@ -210,11 +207,11 @@ func filesystemItemStatus(_ item: PlistDict) throws -> MunkiComparisonResult {
|
||||
return .notPresent
|
||||
}
|
||||
|
||||
/// Compares an installs_item with what's on the startup disk.
|
||||
/// Wraps other comparison functions.
|
||||
/// Returns a MunkiComparisonResult
|
||||
/// Can throw MunkiError on bad input
|
||||
func compareItem(_ item: PlistDict) throws -> MunkiComparisonResult {
|
||||
// Compares an installs_item with what's on the startup disk.
|
||||
// Wraps other comparison functions.
|
||||
// Returns a MunkiComparisonResult
|
||||
// Can throw MunkiError on bad input
|
||||
guard let type = item["type"] as? String else {
|
||||
throw MunkiError("Item type was not defined")
|
||||
}
|
||||
@@ -232,12 +229,11 @@ func compareItem(_ item: PlistDict) throws -> MunkiComparisonResult {
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if the given package is already installed.
|
||||
/// Input: dict with receipt info
|
||||
/// Returns a MunkiComparisonResult
|
||||
/// Can throw MunkiError on bad input
|
||||
func compareReceipt(_ item: PlistDict) async throws -> MunkiComparisonResult {
|
||||
// Determines if the given package is already installed.
|
||||
// Input: dict with receipt info
|
||||
// Returns a MunkiComparisonResult
|
||||
// Can throw MunkiError on bad input
|
||||
|
||||
if item["optional"] as? Bool ?? false {
|
||||
// receipt has been marked as optional, so it doesn't matter
|
||||
// if it's installed or not. Return .same
|
||||
@@ -259,15 +255,14 @@ func compareReceipt(_ item: PlistDict) async throws -> MunkiComparisonResult {
|
||||
return .notPresent
|
||||
}
|
||||
|
||||
/// Attempts to determine the currently installed version of an item.
|
||||
///
|
||||
/// Args:
|
||||
/// pkginfo: pkginfo plist of an item to get the version for.
|
||||
///
|
||||
/// Returns:
|
||||
/// String version of the item, or 'UNKNOWN' if unable to determine
|
||||
func getInstalledVersion(_ pkginfo: PlistDict) -> String {
|
||||
// Attempts to determine the currently installed version of an item.
|
||||
//
|
||||
// Args:
|
||||
// pkginfo: pkginfo plist of an item to get the version for.
|
||||
//
|
||||
// Returns:
|
||||
// String version of the item, or 'UNKNOWN' if unable to determine
|
||||
|
||||
func versionFromPlist(_ path: String) -> String? {
|
||||
do {
|
||||
if let plist = try readPlist(fromFile: path) as? PlistDict {
|
||||
|
||||
Reference in New Issue
Block a user