Permalink
Cannot retrieve contributors at this time
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?
Noze.io/Samples/connect-git/GitLogMiddleware.swift
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
98 lines (86 sloc)
2.75 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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() | |
} | |
} |