<commit_before>import PackagePlugin
import Foundation

/// Type representing a plugin error
enum Gir2SwiftError: LocalizedError {
    case failedToGetGirNameFromManifest
    case failedToGetGirDirectory(containing: [String])
}

/// The file name of the gir2swift manifest
private let gir2swiftManifest = "gir2swift-manifest.yaml"

func getGirName(_ target: Target) throws -> String {
    let manifest = target.directory.appending(gir2swiftManifest)
    let lines = try String(contentsOf: URL(fileURLWithPath: manifest.string)).split(separator: "\n")
    var girName: String? = nil
    for line in lines {
        if line.hasPrefix("gir-name: ") {
            girName = line.dropFirst(10).trimmingCharacters(in: .whitespacesAndNewlines)
        }
    }

    if let girName = girName {
        return girName
    } else {
        throw Gir2SwiftError.failedToGetGirNameFromManifest
    }
}

func getGirDirectory(containing girFiles: [String]) throws -> Path {
    let possibleDirectories = ["/opt/homebrew/share/gir-1.0", "/usr/local/share/gir-1.0", "/usr/share/gir-1.0"].map(Path.init(_:))
    for directory in possibleDirectories {
        let directoryContainsAllGirs = girFiles.allSatisfy { file in
            let path = directory.appending(file).string
            return FileManager.default.fileExists(atPath: path)
        }
        if directoryContainsAllGirs {
            return directory
        }
    }
    throw Gir2SwiftError.failedToGetGirDirectory(containing: girFiles)
}

/// The gir2swift build plugin
@main struct Gir2SwiftPlugin: BuildToolPlugin {
    /// A Plugin that generates Swift code from a `.gir` FILE
    /// - Parameters:
    ///   - context: information about the package for which the plugin is provided
    ///   - target: the target defined in the package
    /// - Returns: the commands to run during the build
    func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] {
        let targetPackageDirectory = context.package.directory
        let gir2swiftManifest = targetPackageDirectory.appending(gir2swiftManifest)
        let outputDir = context.pluginWorkDirectory.appending("gir2swift-generated").appending(target.name)
        try FileManager.default.createDirectory(atPath: outputDir.string, withIntermediateDirectories: true)

        let girName = try getGirName(target)

        // Determine the list of output files
        let atChar = Character("@").utf8.first!
        let suffixes = ["aliases", "bitfields", "callbacks", "constants", "enumerations", "functions", "unions"] +
                       (0...26).map { String(Character(UnicodeScalar(atChar + UInt8($0)))) }
        var outputFiles = suffixes.map { suffix in
            outputDir.appending("\(girName)-\(suffix).swift")
        }

        outputFiles.append(outputDir.appending("\(girName).swift"))

        // Determine the list of input files
        let targetDir = URL(fileURLWithPath: target.directory.string)
        let contents = try FileManager.default.contentsOfDirectory(at: targetDir, includingPropertiesForKeys: nil)

        var inputFiles = contents.filter { file in
            file.lastPathComponent.hasPrefix(girName)
        }.map { file in
            Path(file.path)
        }

        inputFiles.append(target.directory.appending(gir2swiftManifest.string))

        // Find all girs that this library depends on
        let girFiles = target.recursiveTargetDependencies.compactMap {
            try? getGirName($0)
        }.filter {
            $0 != girName
        }.map {
            $0 + ".gir"
        }

        let girDirectory = try getGirDirectory(containing: girFiles)

        // Construct the arguments
        var arguments = [
            "--alpha-names",
            "-w", target.directory.string,
            "-o", outputDir.string,
            "--manifest", "\(gir2swiftManifest)",
        ]

        arguments.append(contentsOf: girFiles.flatMap { girFile in
            ["-p", girDirectory.appending(girFile).string]
        })

        return [.buildCommand(
            displayName: "Running gir2swift",
            executable: try context.tool(named: "gir2swift").path,<commit_msg>Search for yaml in package directory rather than sources<commit_after>import PackagePlugin
import Foundation

/// Type representing a plugin error
enum Gir2SwiftError: LocalizedError {
    case failedToGetGirNameFromManifest
    case failedToGetGirDirectory(containing: [String])
}

/// The file name of the gir2swift manifest
private let gir2swiftManifest = "gir2swift-manifest.yaml"

func getGirName(_ target: Target) throws -> String {
    let targetPackageDirectory = target.directory.removingLastComponent().removingLastComponent()
    let manifest = targetPackageDirectory.appending(gir2swiftManifest)
    let lines = try String(contentsOf: URL(fileURLWithPath: manifest.string)).split(separator: "\n")
    var girName: String? = nil
    for line in lines {
        if line.hasPrefix("gir-name: ") {
            girName = line.dropFirst(10).trimmingCharacters(in: .whitespacesAndNewlines)
        }
    }

    if let girName = girName {
        return girName
    } else {
        throw Gir2SwiftError.failedToGetGirNameFromManifest
    }
}

func getGirDirectory(containing girFiles: [String]) throws -> Path {
    let possibleDirectories = ["/opt/homebrew/share/gir-1.0", "/usr/local/share/gir-1.0", "/usr/share/gir-1.0"].map(Path.init(_:))
    for directory in possibleDirectories {
        let directoryContainsAllGirs = girFiles.allSatisfy { file in
            let path = directory.appending(file).string
            return FileManager.default.fileExists(atPath: path)
        }
        if directoryContainsAllGirs {
            return directory
        }
    }
    throw Gir2SwiftError.failedToGetGirDirectory(containing: girFiles)
}

/// The gir2swift build plugin
@main struct Gir2SwiftPlugin: BuildToolPlugin {
    /// A Plugin that generates Swift code from a `.gir` FILE
    /// - Parameters:
    ///   - context: information about the package for which the plugin is provided
    ///   - target: the target defined in the package
    /// - Returns: the commands to run during the build
    func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] {
        let targetPackageDirectory = context.package.directory
        let gir2swiftManifest = targetPackageDirectory.appending(gir2swiftManifest)
        let outputDir = context.pluginWorkDirectory.appending("gir2swift-generated").appending(target.name)
        try FileManager.default.createDirectory(atPath: outputDir.string, withIntermediateDirectories: true)

        let girName = try getGirName(target)

        // Determine the list of output files
        let atChar = Character("@").utf8.first!
        let suffixes = ["aliases", "bitfields", "callbacks", "constants", "enumerations", "functions", "unions"] +
                       (0...26).map { String(Character(UnicodeScalar(atChar + UInt8($0)))) }
        var outputFiles = suffixes.map { suffix in
            outputDir.appending("\(girName)-\(suffix).swift")
        }

        outputFiles.append(outputDir.appending("\(girName).swift"))

        // Determine the list of input files
        let targetDir = URL(fileURLWithPath: target.directory.string)
        let contents = try FileManager.default.contentsOfDirectory(at: targetDir, includingPropertiesForKeys: nil)

        var inputFiles = contents.filter { file in
            file.lastPathComponent.hasPrefix(girName)
        }.map { file in
            Path(file.path)
        }

        inputFiles.append(targetPackageDirectory.appending(gir2swiftManifest.string))

        // Find all girs that this library depends on
        let girFiles = target.recursiveTargetDependencies.compactMap {
            try? getGirName($0)
        }.filter {
            $0 != girName
        }.map {
            $0 + ".gir"
        }

        let girDirectory = try getGirDirectory(containing: girFiles)

        // Construct the arguments
        var arguments = [
            "--alpha-names",
            "-w", target.directory.string,
            "-o", outputDir.string,
            "--manifest", "\(gir2swiftManifest)",
        ]

        arguments.append(contentsOf: girFiles.flatMap { girFile in
            ["-p", girDirectory.appending(girFile).string]
        })

        return [.buildCommand(
            displayName: "Running gir2swift",
            executable: try context.tool(named: "gir2swift").path,
{'fraction_non_alphanumeric': 0.102721168571092, 'fraction_numerical': 0.007774767345977147, 'mean_word_length': 2.7204206836108678, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2216422', 'n_tokens_mistral': 2393, 'n_tokens_neox': 2311, 'n_words': 562}