mirror of https://github.com/oxen-io/session-ios
commit
ae43d9b4e8
@ -0,0 +1,150 @@
|
||||
#!/usr/bin/xcrun --sdk macosx swift
|
||||
|
||||
// Copyright © 2024 Rangeproof Pty Ltd. All rights reserved.
|
||||
//
|
||||
// stringlint:disable
|
||||
|
||||
import Foundation
|
||||
|
||||
// Get the Derived Data path and the project's name
|
||||
let derivedDataPath = getDerivedDataPath() ?? ""
|
||||
let projectName = ProcessInfo.processInfo.environment["PROJECT_NAME"] ?? ""
|
||||
let projectPath = ProcessInfo.processInfo.environment["PROJECT_DIR"] ?? FileManager.default.currentDirectoryPath
|
||||
|
||||
let packageResolutionFilePath = "\(projectPath)/\(projectName).xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved"
|
||||
let packageCheckoutsPath = "\(derivedDataPath)/SourcePackages/checkouts/"
|
||||
let packageArtifactsPath = "\(derivedDataPath)/SourcePackages/artifacts/"
|
||||
|
||||
func getDerivedDataPath() -> String? {
|
||||
// Define the regular expression pattern to extract the DerivedData path
|
||||
let regexPattern = ".*DerivedData/[^/]*"
|
||||
guard
|
||||
let buildDir = ProcessInfo.processInfo.environment["BUILD_DIR"],
|
||||
let regex = try? NSRegularExpression(pattern: regexPattern)
|
||||
else { return nil }
|
||||
|
||||
let range = NSRange(location: 0, length: buildDir.utf16.count)
|
||||
|
||||
// Perform the regex matching
|
||||
if let match = regex.firstMatch(in: buildDir, options: [], range: range) {
|
||||
// Extract the matching portion (the DerivedData path)
|
||||
if let range = Range(match.range, in: buildDir) {
|
||||
return String(buildDir[range])
|
||||
}
|
||||
} else {
|
||||
print("No DerivedData path found in BUILD_DIR")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Function to list all directories (Swift package checkouts) inside the SourcePackages/checkouts directory
|
||||
func listDirectories(atPath path: String) -> [String] {
|
||||
let fileManager = FileManager.default
|
||||
do {
|
||||
let items = try fileManager.contentsOfDirectory(atPath: path)
|
||||
return items.filter { item in
|
||||
var isDir: ObjCBool = false
|
||||
let fullPath = path + "/" + item
|
||||
return fileManager.fileExists(atPath: fullPath, isDirectory: &isDir) && isDir.boolValue
|
||||
}
|
||||
} catch {
|
||||
print("Error reading contents of directory: \(error)")
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// Function to find and read LICENSE files in each package
|
||||
func findLicenses(in packagesPath: String) -> [(package: String, licenseContent: String)] {
|
||||
var licenses: [(package: String, licenseContent: String)] = []
|
||||
let packages: [String] = listDirectories(atPath: packagesPath)
|
||||
|
||||
print("\(packages.count) packages found in \(packagesPath)")
|
||||
|
||||
packages.forEach { package in
|
||||
let packagePath = "\(packagesPath)/\(package)"
|
||||
scanDirectory(atPath: packagePath) { filePath in
|
||||
if filePath.lowercased().contains("license") || filePath.lowercased().contains("copying") {
|
||||
if let licenseContent = try? String(contentsOfFile: filePath, encoding: .utf8) {
|
||||
licenses.append((package, licenseContent))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return licenses
|
||||
}
|
||||
|
||||
func findPackageDependencyNames(in resolutionFilePath: String) throws -> Set<String> {
|
||||
struct ResolvedPackages: Codable {
|
||||
struct Pin: Codable {
|
||||
struct State: Codable {
|
||||
let revision: String
|
||||
let version: String
|
||||
}
|
||||
|
||||
let identity: String
|
||||
let kind: String
|
||||
let location: String
|
||||
let state: State
|
||||
}
|
||||
|
||||
let originHash: String
|
||||
let pins: [Pin]
|
||||
let version: Int
|
||||
}
|
||||
|
||||
do {
|
||||
let data: Data = try Data(contentsOf: URL(fileURLWithPath: resolutionFilePath))
|
||||
let resolvedPackages: ResolvedPackages = try JSONDecoder().decode(ResolvedPackages.self, from: data)
|
||||
|
||||
print("Found \(resolvedPackages.pins.count) resolved packages.")
|
||||
return Set(resolvedPackages.pins.map { $0.identity.lowercased() })
|
||||
}
|
||||
catch {
|
||||
print("error: Failed to load list of resolved packages")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
func scanDirectory(atPath path: String, foundFile: (String) -> Void) {
|
||||
if let enumerator = FileManager.default.enumerator(atPath: path) {
|
||||
for case let file as String in enumerator {
|
||||
let fullPath = "\(path)/\(file)"
|
||||
if FileManager.default.fileExists(atPath: fullPath, isDirectory: nil) {
|
||||
foundFile(fullPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write licenses to a plist file
|
||||
func writePlist(licenses: [(package: String, licenseContent: String)], resolvedPackageNames: Set<String>, outputPath: String) {
|
||||
var plistArray: [[String: String]] = []
|
||||
let finalLicenses: [(package: String, licenseContent: String)] = licenses
|
||||
.filter { resolvedPackageNames.contains($0.package.lowercased()) }
|
||||
.sorted(by: { $0.package.lowercased() < $1.package.lowercased() })
|
||||
|
||||
print("\(finalLicenses.count) being written to plist.")
|
||||
|
||||
finalLicenses.forEach { license in
|
||||
plistArray.append([
|
||||
"Title": license.package,
|
||||
"License": license.licenseContent
|
||||
])
|
||||
}
|
||||
|
||||
let plistData = try! PropertyListSerialization.data(fromPropertyList: plistArray, format: .xml, options: 0)
|
||||
let plistURL = URL(fileURLWithPath: outputPath)
|
||||
try? plistData.write(to: plistURL)
|
||||
}
|
||||
|
||||
// Execute the license discovery process
|
||||
let licenses = findLicenses(in: packageCheckoutsPath) + findLicenses(in: packageArtifactsPath)
|
||||
let resolvedPackageNames = try findPackageDependencyNames(in: packageResolutionFilePath)
|
||||
|
||||
// Specify the path for the output plist
|
||||
let outputPlistPath = "\(projectPath)/\(projectName)/Meta/Settings.bundle/ThirdPartyLicenses.plist"
|
||||
writePlist(licenses: licenses, resolvedPackageNames: resolvedPackageNames, outputPath: outputPlistPath)
|
||||
|
||||
print("Licenses generated successfully at \(outputPlistPath)")
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue