refactor(loader): Throw when template not found

This commit is contained in:
Kyle Fuller
2016-11-30 17:07:38 +00:00
parent 63c2b935f7
commit 2ebb79df8b
8 changed files with 156 additions and 10 deletions

101
Sources/Loader.swift Normal file
View File

@@ -0,0 +1,101 @@
import Foundation
import PathKit
public protocol Loader {
func loadTemplate(name: String) throws -> Template
func loadTemplate(names: [String]) throws -> Template
}
extension Loader {
func loadTemplate(names: [String]) throws -> Template {
for name in names {
do {
return try loadTemplate(name: name)
} catch is TemplateDoesNotExist {
continue
} catch {
throw error
}
}
throw TemplateDoesNotExist(templateNames: names, loader: self)
}
}
// A class for loading a template from disk
public class FileSystemLoader: Loader, CustomStringConvertible {
public let paths: [Path]
public init(paths: [Path]) {
self.paths = paths
}
public init(bundle: [Bundle]) {
self.paths = bundle.map {
return Path($0.bundlePath)
}
}
public var description: String {
return "FileSystemLoader(\(paths))"
}
public func loadTemplate(name: String) throws -> Template {
for path in paths {
let templatePath = try path.safeJoin(path: Path(name))
if !templatePath.exists {
continue
}
return try Template(path: templatePath)
}
throw TemplateDoesNotExist(templateNames: [name], loader: self)
}
public func loadTemplate(names: [String]) throws -> Template {
for path in paths {
for templateName in names {
let templatePath = try path.safeJoin(path: Path(templateName))
if templatePath.exists {
return try Template(path: templatePath)
}
}
}
throw TemplateDoesNotExist(templateNames: names, loader: self)
}
}
extension Path {
func safeJoin(path: Path) throws -> Path {
let newPath = self + path
if !newPath.absolute().description.hasPrefix(absolute().description) {
throw SuspiciousFileOperation(basePath: self, path: newPath)
}
return newPath
}
}
class SuspiciousFileOperation: Error {
let basePath: Path
let path: Path
init(basePath: Path, path: Path) {
self.basePath = basePath
self.path = path
}
var description: String {
return "Path `\(path)` is located outside of base path `\(basePath)`"
}
}