前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 Swift 递归搜索目录中文件的内容,同时支持 Glob 模式和正则表达式

使用 Swift 递归搜索目录中文件的内容,同时支持 Glob 模式和正则表达式

原创
作者头像
Swift社区
发布2024-07-05 15:22:36
1060
发布2024-07-05 15:22:36
举报
文章被收录于专栏:Swift社区

前言

如果你新加入一个团队,想要快速的了解团队的领域和团队中拥有的代码库的详细信息。

如果新团队中的代码库在 GitHub / GitLab 中并且你不熟悉代码所有权模型的概念或格式。本篇文章以 GitHub 为例,你可以使用 Glob 模式将一个或多个文件链接到 GitHub 团队。

如果新团队中的代码库有一个 GitHub 的 CODEOWNERS 文件,可以反映拥有的每个文件或文件组。这是对了解整个框架有很大帮助,如果没有,可以尝试创建一个。如下:

  • /Tests/ @MyAwesomeOrg/cool-beans
  • /Modules/Account/Tests/* @MyAwesomeOrg/cool-beans
  • /Modules/Account/Settings/**/Views @MyAwesomeOrg/cool-beans

我曾经经历手动去查找团队拥有的文件中的文本出现的次数,比如固定模块的多次重复使用,这非常的耗费时间。

本篇文章讲帮助大家写一个小脚本来自动完成这项任务,给定一些文本片段和一个 GitHub 团队标签,它将在团队拥有的文件中找到该文本的所有出现次数。

项目设置

首先,要做的第一件事是创建一个可执行的 Swift Package:

代码语言:shell
复制
mkdir find-code-owner && cd find-code-owner
swift package init --name FindCodeOwner --type executable

然后,将 ChimeHQGlobPattern Swift Package 添加为依赖项,以帮助确定包含查询文本的文件是否由提供的 GitHub 团队拥有:

代码语言:swift
复制
// swift-tools-version: 5.10

import PackageDescription

let package = Package(
    name: "FindCodeOwner",
    platforms: [
        .macOS(.v13)
    ],
    dependencies: [
        .package(url: "https://github.com/ChimeHQ/GlobPattern.git", exact: "0.1.1")
    ],
    targets: [
        .executableTarget(
            name: "FindCodeOwner",
            dependencies: ["GlobPattern"],
            swiftSettings: [
                .enableUpcomingFeature("BareSlashRegexLiterals")
            ]
        ),
    ]
)

查找文件

假设我们的团队想要迁移一个名为 Quick 的依赖,我们想要找到所有我们拥有的导入该库的文件。

让我们在我们的可执行目标中编写一些代码来实现这一点:

代码语言:swift
复制
import Foundation
import GlobPattern

struct OwnershipRule {
    let path: String
    let teams: [String]
}

func getRules(from codeOwnersFile: String, relativeTo repository: String) -> [OwnershipRule] {
    guard let content = try? String(contentsOfFile: codeOwnersFile) else {
        return []
    }
    
    return content
        .components(separatedBy: .newlines)
        .filter { $0.isEmpty || $0.hasPrefix("#") }
        .map { createRule(from: $0, relativeTo: repository) }
}

func createRule(from line: String, relativeTo repository: String) -> OwnershipRule {
    let elements = line.components(separatedBy: .whitespaces)
        .filter { !$0.isEmpty }

    let teams = elements
        .enumerated()
        .filter { $0 != 0 && $1.hasPrefix("@") }
        .map(\.1)
    
    return OwnershipRule(path: repository + elements[0], teams: teams)
}

func getOwnersForFile(_ filePath: String, rules: [OwnershipRule]) -> [String] {
    rules
        .reversed()
        .first { rule in
            let globExpression = URL(string: rule.path)?.hasDirectoryPath == true ? rule.path + "*" : rule.path
            let matcher = try? Glob.Pattern(globExpression)
            return matcher?.match(filePath) == true
        }?
        .teams ?? []
}

// 1
let rootRepositoryDirectory = FileManager.default.currentDirectoryPath
let codeOwnersPath = rootRepositoryDirectory + "/.github/CODEOWNERS"

// 2
let allOwnershipRules = getRules(from: codeOwnersPath, relativeTo: rootRepositoryDirectory)

// 3
let matchingSearch = "import Quick"
let dirEnum = FileManager.default.enumerator(atPath: rootRepositoryDirectory)
var matchedFiles = [String]()
while let file = dirEnum?.nextObject() as? String {
    guard file.hasSuffix(".swift") else { continue }

    let fullPath = rootRepositoryDirectory + "/" + file
    if let contents = FileManager.default.contents(atPath: fullPath),
       let stringContents = String(data: contents, encoding: .utf8),
       stringContents.contains(matchingSearch) {

        matchedFiles.append(fullPath)
    }
}

// 4
let matchedFilesOnwedByTeam = matchedFiles
    .filter { fileContainingSearchQuery in
        getOwnersForFile(fileContainingSearchQuery, rules: allOwnershipRules).contains("@MyAwesomeOrg/cool-beans")
    }

// 5
print(matchedFilesOnwedByTeam)

上面这段代码的主要目的是从代码库中查找特定团队拥有的文件,并筛选出其中包含指定文本的文件。让我们逐步解释代码的意义、作用和可扩展性。

读取CODEOWNERS文件

通过 getRules(from: codeOwnersPath, relativeTo: rootRepositoryDirectory) 函数从 CODEOWNERS 文件中获取规则。

这些规则定义了哪些文件或目录由特定团队拥有。

解析规则

getRules(from: codeOwnersPath, relativeTo: rootRepositoryDirectory) 函数解析 CODEOWNERS 文件的内容,生成 OwnershipRule 结构体的数组。

每个 OwnershipRule 结构体包含文件路径和相应的团队。

搜索匹配的文件

脚本使用 FileManager 遍历当前代码库中的所有 .swift 文件。

对于每个文件,检查是否包含了匹配的文本(例如,import Quick)。

确定文件所有者

对于包含匹配文本的文件,使用 getOwnersForFile(_:_:) 函数确定其所有者。

getOwnersForFile(_:_:) 函数根据文件路径和规则数组,确定文件的拥有者团队。

输出结果

将文件所有者为 @MyAwesomeOrg/cool-beans 的匹配文件打印输出。

通过这段脚本可以帮助开发者快速找到特定团队拥有的文件,并检查其中是否包含特定的文本。它的可扩展性取决于 CODEOWNERS 文件的格式和内容,以及要搜索的文本类型。例如,可以扩展代码以支持更多类型的文本搜索,或者为不同的团队提供不同的匹配逻辑。此外,可以根据需要添加更多的文件过滤规则或其他自定义逻辑。

总结

最后我想到了一些更加实用的功能,抽时间给大家分享。在未来,可以考虑添加更多的文件过滤规则或支持其他类型的文本搜索,以增强功能。例如,可以添加对不同文件类型的支持,或者实现更复杂的团队匹配逻辑。另外,还可以考虑添加用户界面和更友好的输出方式,以提升用户体验。

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 项目设置
  • 查找文件
    • 读取CODEOWNERS文件
      • 解析规则
        • 搜索匹配的文件
          • 确定文件所有者
            • 输出结果
            • 总结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档