New implementation for getting a recursive list of files

This commit is contained in:
Greg Neagle
2025-06-07 16:06:01 -07:00
parent 0fa92d7390
commit b27bdd1f07
3 changed files with 48 additions and 24 deletions

View File

@@ -488,6 +488,7 @@
C0E994222C5C1109006FDF44 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = C0E994212C5C1109006FDF44 /* ArgumentParser */; };
C0EEC9A72DA7335900F92942 /* clientcerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0EEC9A62DA7335900F92942 /* clientcerts.swift */; };
C0EEC9A82DA7335900F92942 /* clientcerts.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0EEC9A62DA7335900F92942 /* clientcerts.swift */; };
C0FB3AC92DF490CF00BEA7F9 /* libedit.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C030A9F32C4350FE007F0B34 /* libedit.tbd */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -891,6 +892,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
C0FB3AC92DF490CF00BEA7F9 /* libedit.tbd in Frameworks */,
C0B715BE2DA6F43E00F255FB /* X509 in Frameworks */,
C0E9941A2C5C10E1006FDF44 /* ArgumentParser in Frameworks */,
);

View File

@@ -179,31 +179,8 @@ class FileRepo: Repo {
/// Kind might be 'catalogs', 'manifests', 'pkgsinfo', 'pkgs', or 'icons'.
/// For a file-backed repo this would be a list of pathnames.
func list(_ kind: String) async throws -> [String] {
// TODO: the order Foundation enumerates files is different than the order
// you get from Python's os.walk. This affets the behavior of MWA2.
// MWA2 probably should not be relying on catalogs being built in a specific ordering.
var fileList = [String]()
let searchPath = (root as NSString).appendingPathComponent(kind)
let filemanager = FileManager.default
guard let dirEnum = filemanager.enumerator(atPath: searchPath) else {
return [String]()
}
while let file = dirEnum.nextObject() as? String {
let fullpath = (searchPath as NSString).appendingPathComponent(file)
let basename = (file as NSString).lastPathComponent
if !pathIsDirectory(fullpath) {
if !basename.hasPrefix(".") {
fileList.append(file)
}
} else {
// path is directory
if basename.hasPrefix(".") {
// skip this directory
dirEnum.skipDescendants()
}
}
}
return fileList
return recursiveFileList(searchPath)
}
/// Returns the content of item with given resource_identifier.

View File

@@ -222,3 +222,48 @@ func verifyExecutableOwnershipAndPermissions() -> Bool {
}
return true
}
/// Why not use FileManager.DirectoryEnumerator?
///
/// A recursive list of files built via FileManager.DirectoryEnumerator is in avery different order than one built
/// with Python's os.walk(), making it difficult to prove that (for example), the output of `makecatalogs` is
/// the same from the Swift version as it is from the Python version.
/// Also, Munki expects to follow directory symlinks, which FileManager.DirectoryEnumerator does not.
///
/// This code is much slower (5x-20x) than the equivlent Python code based on os.walk(). We'll need
/// to work on that, too.
///
/// List of paths returned is relative to `top`.
func recursiveFileList(_ top: String, followLinks: Bool = true, skipDotFiles: Bool = true) -> [String] {
let fm = FileManager.default
var dirs = [String]()
var paths = [String]()
for item in (try? fm.contentsOfDirectory(atPath: top)) ?? [] {
if skipDotFiles, item.hasPrefix(".") {
// skip any item that starts with a .
continue
}
let path = (top as NSString).appendingPathComponent(item)
if pathIsDirectory(path) {
dirs.append(item)
continue
}
if pathIsSymlink(path), followLinks {
if let destination = try? fm.destinationOfSymbolicLink(atPath: path),
pathIsDirectory(destination)
{
dirs.append(item)
continue
}
}
paths.append(item)
}
for dir in dirs {
let fulldir = (top as NSString).appendingPathComponent(dir)
paths = paths + recursiveFileList(fulldir, followLinks: followLinks).map {
(dir as NSString).appendingPathComponent($0)
}
}
return paths
}