diff --git a/BUILD b/BUILD index 453ce4e04..bf7e15a9e 100644 --- a/BUILD +++ b/BUILD @@ -89,6 +89,7 @@ swift_library( ":SourceKittenFramework.wrapper", "@sourcekitten_com_github_jpsim_yams//:Yams", "@swiftlint_com_github_scottrhoyt_swifty_text_table//:SwiftyTextTable", + "@com_github_ileitch_swift-filename-matcher//:FilenameMatcher" ] + select({ "@platforms//os:linux": ["@com_github_krzyzanowskim_cryptoswift//:CryptoSwift"], "//conditions:default": [":DyldWarningWorkaround"], diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bc4d8264..b575048de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,10 @@ is enabled by default. [SimplyDanny](https://github.com/SimplyDanny) +* Improve performance when exclude patterns resolve to a large set of files. + [SimplyDanny](https://github.com/SimplyDanny) + [#5018](https://github.com/realm/SwiftLint/issues/5018) + #### Bug Fixes * Ignore super calls with trailing closures in `unneeded_override` rule. diff --git a/MODULE.bazel b/MODULE.bazel index ff17e604d..a016dbbe0 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -14,6 +14,7 @@ bazel_dep(name = "sourcekitten", version = "0.36.0", repo_name = "com_github_jps bazel_dep(name = "swift-syntax", version = "600.0.0", repo_name = "SwiftSyntax") bazel_dep(name = "swift_argument_parser", version = "1.3.1.1", repo_name = "sourcekitten_com_github_apple_swift_argument_parser") bazel_dep(name = "yams", version = "5.1.3", repo_name = "sourcekitten_com_github_jpsim_yams") +bazel_dep(name = "swift-filename-matcher", version = "2.0.0", repo_name = "com_github_ileitch_swift-filename-matcher") swiftlint_repos = use_extension("//bazel:repos.bzl", "swiftlint_repos_bzlmod") use_repo( diff --git a/Package.resolved b/Package.resolved index baa9895fe..b5cb643c4 100644 --- a/Package.resolved +++ b/Package.resolved @@ -36,6 +36,15 @@ "version" : "1.3.1" } }, + { + "identity" : "swift-filename-matcher", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ileitch/swift-filename-matcher", + "state" : { + "revision" : "516ff95f6a06c7a9eff8e944e989c7af076c5cdb", + "version" : "2.0.0" + } + }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 2e4cb6dde..e7e7ea10b 100644 --- a/Package.swift +++ b/Package.swift @@ -36,6 +36,7 @@ let package = Package( .package(url: "https://github.com/scottrhoyt/SwiftyTextTable.git", from: "0.9.0"), .package(url: "https://github.com/JohnSundell/CollectionConcurrencyKit.git", from: "0.2.0"), .package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.8.4")), + .package(url: "https://github.com/ileitch/swift-filename-matcher", .upToNextMinor(from: "2.0.0")), ], targets: [ .plugin( @@ -85,6 +86,7 @@ let package = Package( .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), .product(name: "SwiftyTextTable", package: "SwiftyTextTable"), .product(name: "Yams", package: "Yams"), + .product(name: "FilenameMatcher", package: "swift-filename-matcher"), "SwiftLintCoreMacros", ], swiftSettings: swiftFeatures + strictConcurrency diff --git a/Source/SwiftLintCore/Extensions/String+SwiftLint.swift b/Source/SwiftLintCore/Extensions/String+SwiftLint.swift index 49839438b..73d93adf9 100644 --- a/Source/SwiftLintCore/Extensions/String+SwiftLint.swift +++ b/Source/SwiftLintCore/Extensions/String+SwiftLint.swift @@ -68,11 +68,20 @@ public extension String { /// Returns a new string, converting the path to a canonical absolute path. /// + /// > Important: This method might use an incorrect working directory internally. This can cause test failures + /// in Bazel builds but does not seem to cause trouble in production. + /// /// - returns: A new `String`. func absolutePathStandardized() -> String { bridge().absolutePathRepresentation().bridge().standardizingPath } + /// Like ``absolutePathStandardized()`` but with the working directory that's used everywhere else. + var normalized: String { + let cwd = FileManager.default.currentDirectoryPath.bridge().standardizingPath + return bridge().absolutePathRepresentation(rootDirectory: cwd) + } + var isFile: Bool { if self.isEmpty { return false diff --git a/Source/SwiftLintFramework/Configuration+CommandLine.swift b/Source/SwiftLintFramework/Configuration+CommandLine.swift index c24f5c9c5..987542a5b 100644 --- a/Source/SwiftLintFramework/Configuration+CommandLine.swift +++ b/Source/SwiftLintFramework/Configuration+CommandLine.swift @@ -257,15 +257,12 @@ extension Configuration { guard options.forceExclude else { return files } - let scriptInputPaths = files.compactMap(\.path) - - if options.useExcludingByPrefix { - return filterExcludedPathsByPrefix(in: scriptInputPaths) - .map(SwiftLintFile.init(pathDeferringReading:)) - } - return filterExcludedPaths(excludedPaths(), in: scriptInputPaths) - .map(SwiftLintFile.init(pathDeferringReading:)) + return ( + visitor.options.useExcludingByPrefix + ? filterExcludedPathsByPrefix(in: scriptInputPaths) + : filterExcludedPaths(in: scriptInputPaths) + ).map(SwiftLintFile.init(pathDeferringReading:)) } if !options.quiet { let filesInfo: String @@ -277,14 +274,12 @@ extension Configuration { queuedPrintError("\(options.capitalizedVerb) Swift files \(filesInfo)") } - let excludeLintableFilesBy = options.useExcludingByPrefix - ? Configuration.ExcludeBy.prefix - : .paths(excludedPaths: excludedPaths()) - return options.paths.flatMap { + return visitor.options.paths.flatMap { self.lintableFiles( inPath: $0, - forceExclude: options.forceExclude, - excludeBy: excludeLintableFilesBy) + forceExclude: visitor.options.forceExclude, + excludeByPrefix: visitor.options.useExcludingByPrefix + ) } } diff --git a/Source/SwiftLintFramework/Configuration/Configuration+LintableFiles.swift b/Source/SwiftLintFramework/Configuration/Configuration+LintableFiles.swift index 30ea7be97..67dc6d00c 100644 --- a/Source/SwiftLintFramework/Configuration/Configuration+LintableFiles.swift +++ b/Source/SwiftLintFramework/Configuration/Configuration+LintableFiles.swift @@ -1,25 +1,21 @@ import Foundation extension Configuration { - public enum ExcludeBy { - case prefix - case paths(excludedPaths: [String]) - } - // MARK: Lintable Paths + /// Returns the files that can be linted by SwiftLint in the specified parent path. /// /// - parameter path: The parent path in which to search for lintable files. Can be a directory or a /// file. /// - parameter forceExclude: Whether or not excludes defined in this configuration should be applied even if /// `path` is an exact match. - /// - parameter excludeByPrefix: Whether or not uses excluding by prefix algorithm. + /// - parameter excludeByPrefix: Whether or not it uses the exclude-by-prefix algorithm. /// /// - returns: Files to lint. public func lintableFiles(inPath path: String, forceExclude: Bool, - excludeBy: ExcludeBy) -> [SwiftLintFile] { - lintablePaths(inPath: path, forceExclude: forceExclude, excludeBy: excludeBy) + excludeByPrefix: Bool) -> [SwiftLintFile] { + lintablePaths(inPath: path, forceExclude: forceExclude, excludeByPrefix: excludeByPrefix) .compactMap(SwiftLintFile.init(pathDeferringReading:)) } @@ -29,24 +25,21 @@ extension Configuration { /// file. /// - parameter forceExclude: Whether or not excludes defined in this configuration should be applied even if /// `path` is an exact match. - /// - parameter excludeByPrefix: Whether or not uses excluding by prefix algorithm. + /// - parameter excludeByPrefix: Whether or not it uses the exclude-by-prefix algorithm. /// - parameter fileManager: The lintable file manager to use to search for lintable files. /// /// - returns: Paths for files to lint. internal func lintablePaths( inPath path: String, forceExclude: Bool, - excludeBy: ExcludeBy, + excludeByPrefix: Bool, fileManager: some LintableFileManager = FileManager.default ) -> [String] { if fileManager.isFile(atPath: path) { if forceExclude { - switch excludeBy { - case .prefix: - return filterExcludedPathsByPrefix(in: [path.absolutePathStandardized()]) - case .paths(let excludedPaths): - return filterExcludedPaths(excludedPaths, in: [path.absolutePathStandardized()]) - } + return excludeByPrefix + ? filterExcludedPathsByPrefix(in: [path.normalized]) + : filterExcludedPaths(in: [path.normalized]) } // If path is a file and we're not forcing excludes, skip filtering with excluded/included paths return [path] @@ -57,35 +50,29 @@ extension Configuration { .flatMap(Glob.resolveGlob) .parallelFlatMap { fileManager.filesToLint(inPath: $0, rootDirectory: rootDirectory) } - switch excludeBy { - case .prefix: - return filterExcludedPathsByPrefix(in: pathsForPath, includedPaths) - case .paths(let excludedPaths): - return filterExcludedPaths(excludedPaths, in: pathsForPath, includedPaths) - } + return excludeByPrefix + ? filterExcludedPathsByPrefix(in: pathsForPath + includedPaths) + : filterExcludedPaths(in: pathsForPath + includedPaths) } /// Returns an array of file paths after removing the excluded paths as defined by this configuration. /// - /// - parameter fileManager: The lintable file manager to use to expand the excluded paths into all matching paths. - /// - parameter paths: The input paths to filter. + /// - parameter paths: The input paths to filter. /// /// - returns: The input paths after removing the excluded paths. - public func filterExcludedPaths( - _ excludedPaths: [String], - in paths: [String]... - ) -> [String] { - let allPaths = paths.flatMap { $0 } + public func filterExcludedPaths(in paths: [String]) -> [String] { #if os(Linux) - let result = NSMutableOrderedSet(capacity: allPaths.count) - result.addObjects(from: allPaths) + let result = NSMutableOrderedSet(capacity: paths.count) + result.addObjects(from: paths) #else - let result = NSMutableOrderedSet(array: allPaths) + let result = NSMutableOrderedSet(array: paths) #endif - - result.minusSet(Set(excludedPaths)) - // swiftlint:disable:next force_cast - return result.map { $0 as! String } + let exclusionPatterns = self.excludedPaths.flatMap { + Glob.createFilenameMatchers(root: rootDirectory, pattern: $0) + } + return result.array + .parallelCompactMap { exclusionPatterns.anyMatch(filename: $0 as! String) ? nil : $0 as? String } + // swiftlint:disable:previous force_cast } /// Returns the file paths that are excluded by this configuration using filtering by absolute path prefix. @@ -94,25 +81,12 @@ extension Configuration { /// algorithm `filterExcludedPaths`. /// /// - returns: The input paths after removing the excluded paths. - public func filterExcludedPathsByPrefix(in paths: [String]...) -> [String] { - let allPaths = paths.flatMap { $0 } + public func filterExcludedPathsByPrefix(in paths: [String]) -> [String] { let excludedPaths = self.excludedPaths - .parallelFlatMap { @Sendable in Glob.resolveGlob($0) } - .map { $0.absolutePathStandardized() } - return allPaths.filter { path in + .parallelFlatMap { Glob.resolveGlob($0) } + .map(\.normalized) + return paths.filter { path in !excludedPaths.contains { path.hasPrefix($0) } } } - - /// Returns the file paths that are excluded by this configuration after expanding them using the specified file - /// manager. - /// - /// - parameter fileManager: The file manager to get child paths in a given parent location. - /// - /// - returns: The expanded excluded file paths. - public func excludedPaths(fileManager: some LintableFileManager = FileManager.default) -> [String] { - excludedPaths - .flatMap(Glob.resolveGlob) - .parallelFlatMap { fileManager.filesToLint(inPath: $0, rootDirectory: rootDirectory) } - } } diff --git a/Source/SwiftLintFramework/Helpers/Glob.swift b/Source/SwiftLintFramework/Helpers/Glob.swift index 4ef3cfbac..9ef79f1ca 100644 --- a/Source/SwiftLintFramework/Helpers/Glob.swift +++ b/Source/SwiftLintFramework/Helpers/Glob.swift @@ -1,3 +1,4 @@ +import FilenameMatcher import Foundation #if os(Linux) @@ -36,6 +37,28 @@ struct Glob { .map { $0.absolutePathStandardized() } } + static func createFilenameMatchers(root: String, pattern: String) -> [FilenameMatcher] { + var absolutPathPattern = pattern + if !pattern.starts(with: root) { + // If the root is not already part of the pattern, prepend it. + absolutPathPattern = root + (root.hasSuffix("/") ? "" : "/") + absolutPathPattern + } + if pattern.hasSuffix(".swift") || pattern.hasSuffix("/**") { + // Suffix is already well defined. + return [FilenameMatcher(pattern: absolutPathPattern)] + } + if pattern.hasSuffix("/") { + // Matching all files in the folder. + return [FilenameMatcher(pattern: absolutPathPattern + "**")] + } + // The pattern could match files in the last folder in the path or all contained files if the last component + // represents folders. + return [ + FilenameMatcher(pattern: absolutPathPattern), + FilenameMatcher(pattern: absolutPathPattern + "/**"), + ] + } + // MARK: Private private static func expandGlobstar(pattern: String) -> [String] { diff --git a/Tests/IntegrationTests/IntegrationTests.swift b/Tests/IntegrationTests/IntegrationTests.swift index c4830a3ed..fcf3e561d 100644 --- a/Tests/IntegrationTests/IntegrationTests.swift +++ b/Tests/IntegrationTests/IntegrationTests.swift @@ -19,7 +19,7 @@ final class IntegrationTests: SwiftLintTestCase { let swiftFiles = config.lintableFiles( inPath: "", forceExclude: false, - excludeBy: .paths(excludedPaths: config.excludedPaths())) + excludeByPrefix: false) XCTAssert( swiftFiles.contains(where: { #filePath.bridge().absolutePathRepresentation() == $0.path }), "current file should be included" @@ -40,7 +40,7 @@ final class IntegrationTests: SwiftLintTestCase { let swiftFiles = config.lintableFiles( inPath: "", forceExclude: false, - excludeBy: .paths(excludedPaths: config.excludedPaths())) + excludeByPrefix: false) let storage = RuleStorage() let corrections = swiftFiles.parallelFlatMap { Linter(file: $0, configuration: config).collect(into: storage).correct(using: storage) diff --git a/Tests/SwiftLintFrameworkTests/ConfigurationTests.swift b/Tests/SwiftLintFrameworkTests/ConfigurationTests.swift index f88852c94..2fa222e1a 100644 --- a/Tests/SwiftLintFrameworkTests/ConfigurationTests.swift +++ b/Tests/SwiftLintFrameworkTests/ConfigurationTests.swift @@ -288,10 +288,9 @@ final class ConfigurationTests: SwiftLintTestCase { excludedPaths: ["directory/excluded", "directory/ExcludedFile.swift"] ) - let excludedPaths = configuration.excludedPaths(fileManager: fileManager) let paths = configuration.lintablePaths(inPath: "", forceExclude: false, - excludeBy: .paths(excludedPaths: excludedPaths), + excludeByPrefix: false, fileManager: fileManager) XCTAssertEqual(["directory/File1.swift", "directory/File2.swift"].absolutePathsStandardized(), paths) } @@ -299,10 +298,9 @@ final class ConfigurationTests: SwiftLintTestCase { func testForceExcludesFile() { let fileManager = TestFileManager() let configuration = Configuration(excludedPaths: ["directory/ExcludedFile.swift"]) - let excludedPaths = configuration.excludedPaths(fileManager: fileManager) let paths = configuration.lintablePaths(inPath: "directory/ExcludedFile.swift", forceExclude: true, - excludeBy: .paths(excludedPaths: excludedPaths), + excludeByPrefix: false, fileManager: fileManager) XCTAssertEqual([], paths) } @@ -311,10 +309,9 @@ final class ConfigurationTests: SwiftLintTestCase { let fileManager = TestFileManager() let configuration = Configuration(includedPaths: ["directory"], excludedPaths: ["directory/ExcludedFile.swift", "directory/excluded"]) - let excludedPaths = configuration.excludedPaths(fileManager: fileManager) let paths = configuration.lintablePaths(inPath: "", forceExclude: true, - excludeBy: .paths(excludedPaths: excludedPaths), + excludeByPrefix: false, fileManager: fileManager) XCTAssertEqual(["directory/File1.swift", "directory/File2.swift"].absolutePathsStandardized(), paths) } @@ -322,10 +319,9 @@ final class ConfigurationTests: SwiftLintTestCase { func testForceExcludesDirectory() { let fileManager = TestFileManager() let configuration = Configuration(excludedPaths: ["directory/excluded", "directory/ExcludedFile.swift"]) - let excludedPaths = configuration.excludedPaths(fileManager: fileManager) let paths = configuration.lintablePaths(inPath: "directory", forceExclude: true, - excludeBy: .paths(excludedPaths: excludedPaths), + excludeByPrefix: false, fileManager: fileManager) XCTAssertEqual(["directory/File1.swift", "directory/File2.swift"].absolutePathsStandardized(), paths) } @@ -333,19 +329,17 @@ final class ConfigurationTests: SwiftLintTestCase { func testForceExcludesDirectoryThatIsNotInExcludedButHasChildrenThatAre() { let fileManager = TestFileManager() let configuration = Configuration(excludedPaths: ["directory/excluded", "directory/ExcludedFile.swift"]) - let excludedPaths = configuration.excludedPaths(fileManager: fileManager) let paths = configuration.lintablePaths(inPath: "directory", forceExclude: true, - excludeBy: .paths(excludedPaths: excludedPaths), + excludeByPrefix: false, fileManager: fileManager) XCTAssertEqual(["directory/File1.swift", "directory/File2.swift"].absolutePathsStandardized(), paths) } func testLintablePaths() { - let excluded = Configuration.default.excludedPaths(fileManager: TestFileManager()) let paths = Configuration.default.lintablePaths(inPath: Mock.Dir.level0, forceExclude: false, - excludeBy: .paths(excludedPaths: excluded)) + excludeByPrefix: false) let filenames = paths.map { $0.bridge().lastPathComponent }.sorted() let expectedFilenames = [ "DirectoryLevel1.swift", @@ -361,7 +355,7 @@ final class ConfigurationTests: SwiftLintTestCase { let configuration = Configuration(includedPaths: ["**/Level2"]) let paths = configuration.lintablePaths(inPath: Mock.Dir.level0, forceExclude: true, - excludeBy: .paths(excludedPaths: configuration.excludedPaths)) + excludeByPrefix: false) let filenames = paths.map { $0.bridge().lastPathComponent }.sorted() let expectedFilenames = ["Level2.swift", "Level3.swift"] @@ -374,10 +368,9 @@ final class ConfigurationTests: SwiftLintTestCase { excludedPaths: [Mock.Dir.level3.stringByAppendingPathComponent("*.swift")] ) - let excludedPaths = configuration.excludedPaths() let lintablePaths = configuration.lintablePaths(inPath: "", forceExclude: false, - excludeBy: .paths(excludedPaths: excludedPaths)) + excludeByPrefix: false) XCTAssertEqual(lintablePaths, []) } @@ -492,7 +485,7 @@ extension ConfigurationTests { ) let paths = configuration.lintablePaths(inPath: Mock.Dir.level0, forceExclude: false, - excludeBy: .prefix) + excludeByPrefix: true) let filenames = paths.map { $0.bridge().lastPathComponent } XCTAssertEqual(filenames, ["Level2.swift"]) } @@ -502,7 +495,7 @@ extension ConfigurationTests { let configuration = Configuration(excludedPaths: ["Level1/Level2/Level3/Level3.swift"]) let paths = configuration.lintablePaths(inPath: "Level1/Level2/Level3/Level3.swift", forceExclude: true, - excludeBy: .prefix) + excludeByPrefix: true) XCTAssertEqual([], paths) } @@ -512,7 +505,7 @@ extension ConfigurationTests { excludedPaths: ["Level1/Level1.swift"]) let paths = configuration.lintablePaths(inPath: "Level1", forceExclude: true, - excludeBy: .prefix) + excludeByPrefix: true) let filenames = paths.map { $0.bridge().lastPathComponent }.sorted() XCTAssertEqual(["Level2.swift", "Level3.swift"], filenames) } @@ -526,7 +519,7 @@ extension ConfigurationTests { ) let paths = configuration.lintablePaths(inPath: ".", forceExclude: true, - excludeBy: .prefix) + excludeByPrefix: true) let filenames = paths.map { $0.bridge().lastPathComponent }.sorted() XCTAssertEqual(["Level0.swift", "Level1.swift"], filenames) } @@ -540,7 +533,7 @@ extension ConfigurationTests { ) let paths = configuration.lintablePaths(inPath: ".", forceExclude: true, - excludeBy: .prefix) + excludeByPrefix: true) let filenames = paths.map { $0.bridge().lastPathComponent } XCTAssertEqual(["Level0.swift"], filenames) } @@ -552,7 +545,7 @@ extension ConfigurationTests { excludedPaths: ["Level1/*/*.swift", "Level1/*/*/*.swift"]) let paths = configuration.lintablePaths(inPath: "Level1", forceExclude: false, - excludeBy: .prefix) + excludeByPrefix: true) let filenames = paths.map { $0.bridge().lastPathComponent }.sorted() XCTAssertEqual(filenames, ["Level1.swift"]) } @@ -606,7 +599,7 @@ extension ConfigurationTests { private extension Sequence where Element == String { func absolutePathsStandardized() -> [String] { - map { $0.absolutePathStandardized() } + map(\.normalized) } } diff --git a/Tests/SwiftLintFrameworkTests/GlobTests.swift b/Tests/SwiftLintFrameworkTests/GlobTests.swift index 04730dc09..81b53677b 100644 --- a/Tests/SwiftLintFrameworkTests/GlobTests.swift +++ b/Tests/SwiftLintFrameworkTests/GlobTests.swift @@ -82,4 +82,31 @@ final class GlobTests: SwiftLintTestCase { let files = Glob.resolveGlob(mockPath.stringByAppendingPathComponent("**/*.swift")) XCTAssertEqual(files.sorted(), expectedFiles.sorted()) } + + func testCreateFilenameMatchers() { + func assertGlobMatch(root: String, pattern: String, filename: String) { + let matchers = Glob.createFilenameMatchers(root: root, pattern: pattern) + XCTAssert(matchers.anyMatch(filename: filename)) + } + + assertGlobMatch(root: "/a/b/", pattern: "c/*.swift", filename: "/a/b/c/d.swift") + assertGlobMatch(root: "/a", pattern: "**/*.swift", filename: "/a/b/c/d.swift") + assertGlobMatch(root: "/a", pattern: "**/*.swift", filename: "/a/b.swift") + assertGlobMatch(root: "", pattern: "**/*.swift", filename: "/a/b.swift") + assertGlobMatch(root: "", pattern: "a/**/b.swift", filename: "a/b.swift") + assertGlobMatch(root: "", pattern: "a/**/b.swift", filename: "a/c/b.swift") + assertGlobMatch(root: "", pattern: "**/*.swift", filename: "a.swift") + assertGlobMatch(root: "", pattern: "a/**/*.swift", filename: "a/b/c.swift") + assertGlobMatch(root: "", pattern: "a/**/*.swift", filename: "a/b.swift") + assertGlobMatch(root: "/a/b", pattern: "/a/b/c/*.swift", filename: "/a/b/c/d.swift") + assertGlobMatch(root: "/a/", pattern: "/a/b/c/*.swift", filename: "/a/b/c/d.swift") + + assertGlobMatch(root: "", pattern: "/a/b/c", filename: "/a/b/c/d.swift") + assertGlobMatch(root: "", pattern: "/a/b/c/", filename: "/a/b/c/d.swift") + assertGlobMatch(root: "", pattern: "/a/b/c/*.swift", filename: "/a/b/c/d.swift") + assertGlobMatch(root: "", pattern: "/d.swift/*.swift", filename: "/d.swift/e.swift") + assertGlobMatch(root: "", pattern: "/a/**", filename: "/a/b/c/d.swift") + assertGlobMatch(root: "", pattern: "**/*Test*", filename: "/a/b/c/MyTest2.swift") + assertGlobMatch(root: "", pattern: "**/*Test*", filename: "/a/b/MyTests/c.swift") + } } diff --git a/bazel/repos.bzl b/bazel/repos.bzl index 47f2aa9d3..53d99188e 100644 --- a/bazel/repos.bzl +++ b/bazel/repos.bzl @@ -64,6 +64,13 @@ def swiftlint_repos(bzlmod = False): url = "https://github.com/krzyzanowskim/CryptoSwift/archive/refs/tags/1.8.4.tar.gz", ) + http_archive( + name = "com_github_ileitch_swift-filename-matcher", + sha256 = "1adbb1eb042910f996689827f7dee217bebf7c5178f34178bcfe468b5b3268a2", + strip_prefix = "swift-filename-matcher-2.0.0", + url = "https://github.com/ileitch/swift-filename-matcher/archive/refs/tags/2.0.0.tar.gz", + ) + def _swiftlint_repos_bzlmod(_): swiftlint_repos(bzlmod = True) diff --git a/tools/oss-check b/tools/oss-check index 77a70c836..f1d0a05ca 100755 --- a/tools/oss-check +++ b/tools/oss-check @@ -45,6 +45,7 @@ end.parse! class Repo attr_accessor :name attr_accessor :github_location + attr_accessor :keep_config attr_accessor :config attr_accessor :commit_hash attr_accessor :branch_exit_value @@ -52,9 +53,10 @@ class Repo attr_accessor :main_exit_value attr_accessor :main_duration - def initialize(name, github_location, config=nil) + def initialize(name, github_location, keep_config=false, config=nil) @name = name @github_location = github_location + @keep_config = keep_config @config = config end @@ -140,7 +142,9 @@ def setup_repos puts "Cloning #{repo}" perform("git clone #{repo.git_url} --depth 1 #{dir} 2> /dev/null") swiftlint_config = "#{dir}/.swiftlint.yml" - FileUtils.rm_rf(swiftlint_config) + if !repo.keep_config + FileUtils.rm_rf(swiftlint_config) + end if repo.config File.open(swiftlint_config, 'a') do |file| file.puts(repo.config) @@ -292,7 +296,7 @@ end @repos = [ Repo.new('Aerial', 'JohnCoates/Aerial'), Repo.new('Alamofire', 'Alamofire/Alamofire'), - Repo.new('Brave', 'brave/brave-ios'), + Repo.new('Brave', 'brave/brave-ios', true), Repo.new('DuckDuckGo', 'duckduckgo/iOS'), Repo.new('Firefox', 'mozilla-mobile/firefox-ios'), Repo.new('Kickstarter', 'kickstarter/ios-oss'), @@ -303,9 +307,9 @@ end Repo.new('Quick', 'Quick/Quick'), Repo.new('Realm', 'realm/realm-swift'), Repo.new('Sourcery', 'krzysztofzablocki/Sourcery'), - Repo.new('Swift', 'apple/swift', 'included: stdlib'), + Repo.new('Swift', 'apple/swift', false, 'included: stdlib'), Repo.new('VLC', 'videolan/vlc-ios'), - Repo.new('Wire', 'wireapp/wire-ios', 'excluded: wire-ios/Templates/Viper'), + Repo.new('Wire', 'wireapp/wire-ios', false, 'excluded: wire-ios/Templates/Viper'), Repo.new('WordPress', 'wordpress-mobile/WordPress-iOS') ]