2016-08-30 21:44:58 +03:00
|
|
|
/**
|
|
|
|
* Tae Won Ha - http://taewon.de - @hataewon
|
|
|
|
* See LICENSE
|
|
|
|
*/
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
|
2017-02-28 00:45:26 +03:00
|
|
|
fileprivate let whitespaceCharSet = CharacterSet.whitespaces
|
2016-08-30 21:44:58 +03:00
|
|
|
|
2016-09-11 15:28:56 +03:00
|
|
|
class FileItemIgnorePattern: Hashable, CustomStringConvertible {
|
2017-02-28 00:45:26 +03:00
|
|
|
|
|
|
|
static func ==(lhs: FileItemIgnorePattern, rhs: FileItemIgnorePattern) -> Bool {
|
|
|
|
return lhs.pattern == rhs.pattern
|
|
|
|
}
|
|
|
|
|
|
|
|
static func from(string str: String) -> Set<FileItemIgnorePattern> {
|
|
|
|
if str.trimmingCharacters(in: whitespaceCharSet).characters.count == 0 {
|
|
|
|
return Set()
|
|
|
|
}
|
|
|
|
|
|
|
|
let patterns: [FileItemIgnorePattern] = str
|
|
|
|
.components(separatedBy: ",")
|
|
|
|
.flatMap {
|
|
|
|
let trimmed = $0.trimmingCharacters(in: whitespaceCharSet)
|
|
|
|
if trimmed.characters.count == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return FileItemIgnorePattern(pattern: trimmed)
|
|
|
|
}
|
|
|
|
|
|
|
|
return Set(patterns)
|
|
|
|
}
|
|
|
|
|
|
|
|
static func toString(_ set: Set<FileItemIgnorePattern>) -> String {
|
|
|
|
return Array(set)
|
|
|
|
.map { $0.pattern }
|
|
|
|
.sorted()
|
|
|
|
.joined(separator: ", ")
|
|
|
|
}
|
|
|
|
|
2016-08-30 21:44:58 +03:00
|
|
|
var hashValue: Int {
|
|
|
|
return self.pattern.hashValue
|
|
|
|
}
|
2016-09-11 15:28:56 +03:00
|
|
|
|
|
|
|
var description: String {
|
2016-09-11 15:44:17 +03:00
|
|
|
return "<FileItemIgnorePattern: pattern=\(self.pattern), folderPattern=\(self.folderPattern)>"
|
2016-09-11 15:28:56 +03:00
|
|
|
}
|
2016-08-30 21:44:58 +03:00
|
|
|
|
|
|
|
let folderPattern: Bool
|
|
|
|
let pattern: String
|
|
|
|
|
2016-09-25 18:50:33 +03:00
|
|
|
fileprivate let patternAsFileSysRep: UnsafeMutablePointer<Int8>
|
2016-08-30 21:44:58 +03:00
|
|
|
|
|
|
|
init(pattern: String) {
|
|
|
|
self.pattern = pattern
|
|
|
|
self.folderPattern = pattern.hasPrefix("*/")
|
|
|
|
|
|
|
|
let fileSysRep = (pattern as NSString).fileSystemRepresentation
|
|
|
|
let len = Int(strlen(fileSysRep))
|
|
|
|
|
2016-09-25 18:50:33 +03:00
|
|
|
self.patternAsFileSysRep = UnsafeMutablePointer<Int8>.allocate(capacity: len + 1)
|
2016-08-30 21:44:58 +03:00
|
|
|
memcpy(self.patternAsFileSysRep, fileSysRep, len)
|
|
|
|
self.patternAsFileSysRep[len] = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
deinit {
|
|
|
|
let len = Int(strlen(self.patternAsFileSysRep))
|
2016-09-25 18:50:33 +03:00
|
|
|
self.patternAsFileSysRep.deallocate(capacity: len + 1)
|
2016-08-30 21:44:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func match(absolutePath path: String) -> Bool {
|
|
|
|
let matches: Int32
|
|
|
|
let absolutePath = path as NSString
|
|
|
|
|
|
|
|
if self.folderPattern {
|
|
|
|
matches = fnmatch(self.patternAsFileSysRep,
|
|
|
|
absolutePath.fileSystemRepresentation,
|
|
|
|
FNM_LEADING_DIR | FNM_NOESCAPE)
|
|
|
|
} else {
|
|
|
|
matches = fnmatch(self.patternAsFileSysRep,
|
|
|
|
(absolutePath.lastPathComponent as NSString).fileSystemRepresentation,
|
|
|
|
FNM_NOESCAPE)
|
|
|
|
}
|
|
|
|
|
|
|
|
return matches != FNM_NOMATCH
|
|
|
|
}
|
2016-09-25 18:50:33 +03:00
|
|
|
}
|