Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
// Noze.io Simple Connect based WebServer
import core
import streams
import http
import connect
import console
import child_process
// This is a demo on how to transform stuff in a streaming
// way along the piping queue.
//
// What it does:
// - we call `git log` and pipe the stdout
// - into `readlines`, which transforms the bytes into [String] lines
// - those are piped into the `linesToRecords` function, which
// produces `GitLogEntry` structs, which are then piped into
// - the `recordsToHTML` function, which produces HTML bytes
// - which are finally piped into the response
// Lots of piping going on.
struct GitLogEntry {
let commit : String
let author : String
let email : String
let date : String
}
extension String { // add stuff missing in String w/o Foundation
func componentsSeparated(by c: Character) -> [ String ] {
#if swift(>=3.2)
return split(separator: c).map { String($0) }
#else
return characters.split(separator: c).map { String($0) }
#endif
}
}
func linesToRecords(chunk : [String]?,
push : ( [GitLogEntry]? ) -> Void,
end : ( Error?, [GitLogEntry]? ) -> Void)
{
guard let lines = chunk else { end(nil,nil); return }
let records : [ GitLogEntry ] = lines.map { line in
let fields = line.componentsSeparated(by: "|")
guard fields.count > 3 else {
print("SHORT LINE: \(line) \(fields)")
return GitLogEntry(commit:line, author:"", email:"", date:"")
}
return GitLogEntry(
commit: fields[0],
author: fields[1],
email: fields[2],
date: fields[3]
)
}
end(nil, records)
}
func recordsToHTML(chunk : [ GitLogEntry ]?,
push : ( [UInt8]? ) -> Void,
end : ( Error?, [UInt8]? ) -> Void)
{
guard let records = chunk else { end(nil,nil); return }
for r in records {
let s =
"<tr><td>\(r.date)</td><td>\(r.author)</td><td>\(r.commit)</td></tr>"
push(Array<UInt8>(s.utf8)) // `res` expects bytes
}
end(nil, nil)
}
/// This is the actual middleware function
func gitLog(req: IncomingMessage, res: ServerResponse, next: (Any...) -> Void) {
res.write("<h3>git log</h3>")
res.write("<table border='1'>")
res.write("<tr><th>Date</th><th>Author</th><th>Commit</th></tr>")
let s = spawn("git", "log", "-100", "--pretty=format:%H|%an|<%ae>|%ad")
| readlines
| through2(linesToRecords)
| through2(recordsToHTML)
// Swift3 2016-05-09 falls apart on this, maybe this is due to
// operator ordering (| vs .)?
_ = s.pipe(res, endOnFinish: false)
.onError { error in
print("Pipe error: \(error)")
}
.onUnpipe { _ in
// TODO: sometimes the socket is closed before this happens?
res.write("</table>")
res.end()
}
}