Convert some comments to documentation

This commit is contained in:
Greg Neagle
2024-09-10 20:46:42 -07:00
parent 544138152b
commit 83aafa770f
3 changed files with 116 additions and 131 deletions
+37 -41
View File
@@ -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)
+31 -36
View File
@@ -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 {