mirror of
https://github.com/munki/munki.git
synced 2026-01-08 23:50:18 -06:00
Support for Repo plugins
This commit is contained in:
@@ -20,6 +20,51 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Loads a Repo plugin from a dylib
|
||||
/// implementation lifted from
|
||||
/// https://theswiftdev.com/building-and-loading-dynamic-libraries-at-runtime-in-swift/
|
||||
func loadRepoPlugin(at path: String) throws -> RepoPluginBuilder {
|
||||
typealias InitFunction = @convention(c) () -> UnsafeMutableRawPointer
|
||||
|
||||
let openRes = dlopen(path, RTLD_NOW | RTLD_LOCAL)
|
||||
if openRes != nil {
|
||||
defer {
|
||||
dlclose(openRes)
|
||||
}
|
||||
|
||||
let symbolName = "createPlugin"
|
||||
let sym = dlsym(openRes, symbolName)
|
||||
|
||||
if sym != nil {
|
||||
let f: InitFunction = unsafeBitCast(sym, to: InitFunction.self)
|
||||
let pluginPointer = f()
|
||||
let builder = Unmanaged<RepoPluginBuilder>.fromOpaque(pluginPointer).takeRetainedValue()
|
||||
return builder
|
||||
} else {
|
||||
throw MunkiError("Could not find symbol \(symbolName) in lib: \(path)")
|
||||
}
|
||||
} else {
|
||||
if let err = dlerror() {
|
||||
throw MunkiError("Error opening lib: \(String(format: "%s", err)), path: \(path)")
|
||||
} else {
|
||||
throw MunkiError("Error opening lib: unknown error, path: \(path)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Try to load a Repo plugin from our RepoPlugins directory
|
||||
func findRepoInPlugins(_ name: String, url: String) throws -> Repo? {
|
||||
let pluginName = name + ".plugin"
|
||||
let repoPluginsDir = (Bundle.main.bundlePath as NSString).appendingPathComponent("RepoPlugins")
|
||||
let repoPluginNames = (try? FileManager.default.contentsOfDirectory(atPath: repoPluginsDir)) ?? []
|
||||
if repoPluginNames.contains(pluginName) {
|
||||
let pluginPath = (repoPluginsDir as NSString).appendingPathComponent(pluginName)
|
||||
let repoPlugin = try loadRepoPlugin(at: pluginPath)
|
||||
return repoPlugin.connect(url)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Factory function that returns an instance of a specific Repo class
|
||||
func repoConnect(url: String, plugin: String = "FileRepo") throws -> Repo {
|
||||
switch plugin {
|
||||
@@ -28,6 +73,9 @@ func repoConnect(url: String, plugin: String = "FileRepo") throws -> Repo {
|
||||
case "GitFileRepo":
|
||||
return try GitFileRepo(url)
|
||||
default:
|
||||
if let repo = try findRepoInPlugins(plugin, url: url) {
|
||||
return repo
|
||||
}
|
||||
throw MunkiError("No repo plugin named \"\(plugin)\"")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,19 @@
|
||||
//
|
||||
// Created by Greg Neagle on 5/8/25.
|
||||
//
|
||||
// Copyright 2024-2025 Greg Neagle.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
@@ -4,6 +4,19 @@
|
||||
//
|
||||
// Created by Greg Neagle on 7/15/24.
|
||||
//
|
||||
// Copyright 2024-2025 Greg Neagle.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user