From 30aa5d8c2ddb49ec56596edad23b5c1043737366 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Wed, 17 May 2017 21:30:25 -0700 Subject: remove code --- vendor/github.com/Xe/asarfs/asarfs.go | 117 ---------------------- vendor/github.com/Xe/asarfs/bench_test.go | 156 ------------------------------ vendor/github.com/Xe/asarfs/runtest.go | 24 ----- vendor/github.com/Xe/gopreload/doc.go | 7 -- vendor/github.com/Xe/gopreload/preload.go | 26 ----- vendor/github.com/Xe/ln/filter.go | 66 ------------- vendor/github.com/Xe/ln/formatter.go | 100 ------------------- vendor/github.com/Xe/ln/logger.go | 141 --------------------------- vendor/github.com/Xe/ln/stack.go | 44 --------- 9 files changed, 681 deletions(-) delete mode 100644 vendor/github.com/Xe/asarfs/asarfs.go delete mode 100644 vendor/github.com/Xe/asarfs/bench_test.go delete mode 100644 vendor/github.com/Xe/asarfs/runtest.go delete mode 100644 vendor/github.com/Xe/gopreload/doc.go delete mode 100644 vendor/github.com/Xe/gopreload/preload.go delete mode 100644 vendor/github.com/Xe/ln/filter.go delete mode 100644 vendor/github.com/Xe/ln/formatter.go delete mode 100644 vendor/github.com/Xe/ln/logger.go delete mode 100644 vendor/github.com/Xe/ln/stack.go (limited to 'vendor/github.com/Xe') diff --git a/vendor/github.com/Xe/asarfs/asarfs.go b/vendor/github.com/Xe/asarfs/asarfs.go deleted file mode 100644 index 7d18949..0000000 --- a/vendor/github.com/Xe/asarfs/asarfs.go +++ /dev/null @@ -1,117 +0,0 @@ -package asarfs - -import ( - "io" - "mime" - "net/http" - "os" - "path/filepath" - "strings" - - "layeh.com/asar" -) - -// ASARfs serves the contents of an asar archive as an HTTP handler. -type ASARfs struct { - fin *os.File - ar *asar.Entry - notFound http.Handler -} - -// Close closes the underlying file used for the asar archive. -func (a *ASARfs) Close() error { - return a.fin.Close() -} - -// Open satisfies the http.FileSystem interface for ASARfs. -func (a *ASARfs) Open(name string) (http.File, error) { - if name == "/" { - name = "/index.html" - } - - e := a.ar.Find(strings.Split(name, "/")[1:]...) - if e == nil { - return nil, os.ErrNotExist - } - - f := &file{ - Entry: e, - r: e.Open(), - } - - return f, nil -} - -// ServeHTTP satisfies the http.Handler interface for ASARfs. -func (a *ASARfs) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if r.RequestURI == "/" { - r.RequestURI = "/index.html" - } - - f := a.ar.Find(strings.Split(r.RequestURI, "/")[1:]...) - if f == nil { - a.notFound.ServeHTTP(w, r) - return - } - - ext := filepath.Ext(f.Name) - mimeType := mime.TypeByExtension(ext) - - w.Header().Add("Content-Type", mimeType) - f.WriteTo(w) -} - -// New creates a new ASARfs pointer based on the filepath to the archive and -// a HTTP handler to hit when a file is not found. -func New(archivePath string, notFound http.Handler) (*ASARfs, error) { - fin, err := os.Open(archivePath) - if err != nil { - return nil, err - } - - root, err := asar.Decode(fin) - if err != nil { - return nil, err - } - - a := &ASARfs{ - fin: fin, - ar: root, - notFound: notFound, - } - - return a, nil -} - -// file is an internal shim that mimics http.File for an asar entry. -type file struct { - *asar.Entry - r io.ReadSeeker -} - -func (f *file) Close() error { - f.r = nil - return nil -} - -func (f *file) Read(buf []byte) (n int, err error) { - return f.r.Read(buf) -} - -func (f *file) Seek(offset int64, whence int) (int64, error) { - return f.r.Seek(offset, whence) -} - -func (f *file) Readdir(count int) ([]os.FileInfo, error) { - result := []os.FileInfo{} - - for _, e := range f.Entry.Children { - result = append(result, e.FileInfo()) - } - - return result, nil -} - -func (f *file) Stat() (os.FileInfo, error) { - return f.Entry.FileInfo(), nil -} diff --git a/vendor/github.com/Xe/asarfs/bench_test.go b/vendor/github.com/Xe/asarfs/bench_test.go deleted file mode 100644 index fd332d5..0000000 --- a/vendor/github.com/Xe/asarfs/bench_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// +build go1.8 - -package asarfs - -import ( - "fmt" - "io" - "io/ioutil" - "math/rand" - "net" - "net/http" - "os" - "testing" -) - -func BenchmarkHTTPFileSystem(b *testing.B) { - fs := http.FileServer(http.Dir(".")) - - l, s, err := setupHandler(fs) - if err != nil { - b.Fatal(err) - } - defer l.Close() - defer s.Close() - - url := fmt.Sprintf("http://%s", l.Addr()) - - for n := 0; n < b.N; n++ { - testHandler(url) - } -} - -func BenchmarkASARfs(b *testing.B) { - fs, err := New("./static.asar", http.HandlerFunc(do404)) - if err != nil { - b.Fatal(err) - } - - l, s, err := setupHandler(fs) - if err != nil { - b.Fatal(err) - } - defer l.Close() - defer s.Close() - - url := fmt.Sprintf("http://%s", l.Addr()) - - for n := 0; n < b.N; n++ { - testHandler(url) - } -} - -func BenchmarkPreloadedASARfs(b *testing.B) { - for n := 0; n < b.N; n++ { - testHandler(asarfsurl) - } -} - -func BenchmarkASARfsHTTPFilesystem(b *testing.B) { - fs, err := New("./static.asar", http.HandlerFunc(do404)) - if err != nil { - b.Fatal(err) - } - - l, s, err := setupHandler(http.FileServer(fs)) - if err != nil { - b.Fatal(err) - } - defer l.Close() - defer s.Close() - - url := fmt.Sprintf("http://%s", l.Addr()) - - for n := 0; n < b.N; n++ { - testHandler(url) - } -} - -func BenchmarkPreloadedASARfsHTTPFilesystem(b *testing.B) { - for n := 0; n < b.N; n++ { - testHandler(asarfshttpfsurl) - } -} - -func do404(w http.ResponseWriter, r *http.Request) { - http.Error(w, "Not found", http.StatusNotFound) -} - -func setupHandler(h http.Handler) (net.Listener, *http.Server, error) { - l, err := net.Listen("tcp", ":0") - if err != nil { - panic(err) - } - defer l.Close() - - s := &http.Server{ - Handler: h, - } - go s.ListenAndServe() - - return l, s, nil -} - -func testHandler(u string) error { - num := rand.Intn(9) - num++ - sub := rand.Intn(99) - - fname := fmt.Sprintf("/static/%d/%d%d.json", num, num, sub) - - resp, err := http.Get(u + fname) - if err != nil { - return err - } - defer resp.Body.Close() - - _, err = io.Copy(ioutil.Discard, resp.Body) - if err != nil { - panic(err) - } - - return nil -} - -var ( - asarfsurl string - asarfshttpfsurl string -) - -func TestMain(m *testing.M) { - go func() { - fs, err := New("./static.asar", http.HandlerFunc(do404)) - if err != nil { - } - - l, _, err := setupHandler(fs) - if err != nil { - } - - asarfsurl = fmt.Sprintf("http://%s", l.Addr().String()) - }() - - go func() { - fs, err := New("./static.asar", http.HandlerFunc(do404)) - if err != nil { - } - - l, _, err := setupHandler(http.FileServer(fs)) - if err != nil { - } - - asarfshttpfsurl = fmt.Sprintf("http://%s", l.Addr().String()) - }() - - os.Exit(m.Run()) -} diff --git a/vendor/github.com/Xe/asarfs/runtest.go b/vendor/github.com/Xe/asarfs/runtest.go deleted file mode 100644 index 4b839de..0000000 --- a/vendor/github.com/Xe/asarfs/runtest.go +++ /dev/null @@ -1,24 +0,0 @@ -// +build ignore - -package main - -import ( - "log" - "net/http" - "os" - - "github.com/Xe/asarfs" -) - -func do404(w http.ResponseWriter, r *http.Request) { - http.Error(w, "Not found", http.StatusNotFound) -} - -func main() { - fs, err := asarfs.New("./static.asar", http.HandlerFunc(do404)) - if err != nil { - log.Fatal(err) - } - - http.ListenAndServe(":"+os.Getenv("PORT"), fs) -} diff --git a/vendor/github.com/Xe/gopreload/doc.go b/vendor/github.com/Xe/gopreload/doc.go deleted file mode 100644 index 720c5c1..0000000 --- a/vendor/github.com/Xe/gopreload/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -Package gopreload is a bit of a hack to emulate the behavior of LD_PRELOAD [ld-preload]. -This allows you to have automatically starting instrumentation, etc. - -[ld-preload]: http://man7.org/linux/man-pages/man8/ld.so.8.html (see LD_PRELOAD section) -*/ -package gopreload diff --git a/vendor/github.com/Xe/gopreload/preload.go b/vendor/github.com/Xe/gopreload/preload.go deleted file mode 100644 index 1b5a0c9..0000000 --- a/vendor/github.com/Xe/gopreload/preload.go +++ /dev/null @@ -1,26 +0,0 @@ -//+build linux,go1.8 - -package gopreload - -import ( - "log" - "os" - "plugin" - "strings" -) - -func init() { - gpv := os.Getenv("GO_PRELOAD") - if gpv == "" { - return - } - - for _, elem := range strings.Split(gpv, ",") { - log.Printf("gopreload: trying to open: %s", elem) - _, err := plugin.Open(elem) - if err != nil { - log.Printf("%v from GO_PRELOAD cannot be loaded: %v", elem, err) - continue - } - } -} diff --git a/vendor/github.com/Xe/ln/filter.go b/vendor/github.com/Xe/ln/filter.go deleted file mode 100644 index 586efef..0000000 --- a/vendor/github.com/Xe/ln/filter.go +++ /dev/null @@ -1,66 +0,0 @@ -package ln - -import ( - "io" - "sync" -) - -// Filter interface for defining chain filters -type Filter interface { - Apply(Event) bool - Run() - Close() -} - -// FilterFunc allows simple functions to implement the Filter interface -type FilterFunc func(e Event) bool - -// Apply implements the Filter interface -func (ff FilterFunc) Apply(e Event) bool { - return ff(e) -} - -// Run implements the Filter interface -func (ff FilterFunc) Run() {} - -// Close implements the Filter interface -func (ff FilterFunc) Close() {} - -// WriterFilter implements a filter, which arbitrarily writes to an io.Writer -type WriterFilter struct { - sync.Mutex - Out io.Writer - Formatter Formatter -} - -// NewWriterFilter creates a filter to add to the chain -func NewWriterFilter(out io.Writer, format Formatter) *WriterFilter { - if format == nil { - format = DefaultFormatter - } - return &WriterFilter{ - Out: out, - Formatter: format, - } -} - -// Apply implements the Filter interface -func (w *WriterFilter) Apply(e Event) bool { - output, err := w.Formatter.Format(e) - if err == nil { - w.Lock() - w.Out.Write(output) - w.Unlock() - } - - return true -} - -// Run implements the Filter interface -func (w *WriterFilter) Run() {} - -// Close implements the Filter interface -func (w *WriterFilter) Close() {} - -// NilFilter is safe to return as a Filter, but does nothing -var NilFilter = FilterFunc(func(e Event) bool { return true }) diff --git a/vendor/github.com/Xe/ln/formatter.go b/vendor/github.com/Xe/ln/formatter.go deleted file mode 100644 index 9d67139..0000000 --- a/vendor/github.com/Xe/ln/formatter.go +++ /dev/null @@ -1,100 +0,0 @@ -package ln - -import ( - "bytes" - "fmt" - "time" -) - -var ( - // DefaultTimeFormat represents the way in which time will be formatted by default - DefaultTimeFormat = time.RFC3339 -) - -// Formatter defines the formatting of events -type Formatter interface { - Format(Event) ([]byte, error) -} - -// DefaultFormatter is the default way in which to format events -var DefaultFormatter Formatter - -func init() { - DefaultFormatter = NewTextFormatter() -} - -// TextFormatter formats events as key value pairs. -// Any remaining text not wrapped in an instance of `F` will be -// placed at the end. -type TextFormatter struct { - TimeFormat string -} - -// NewTextFormatter returns a Formatter that outputs as text. -func NewTextFormatter() Formatter { - return &TextFormatter{TimeFormat: DefaultTimeFormat} -} - -// Format implements the Formatter interface -func (t *TextFormatter) Format(e Event) ([]byte, error) { - var writer bytes.Buffer - - writer.WriteString("time=\"") - writer.WriteString(e.Time.Format(t.TimeFormat)) - writer.WriteString("\"") - - for k, v := range e.Data { - writer.WriteByte(' ') - if shouldQuote(k) { - writer.WriteString(fmt.Sprintf("%q", k)) - } else { - writer.WriteString(k) - } - - writer.WriteByte('=') - - switch v.(type) { - case string: - vs, _ := v.(string) - if shouldQuote(vs) { - fmt.Fprintf(&writer, "%q", vs) - } else { - writer.WriteString(vs) - } - case error: - tmperr, _ := v.(error) - es := tmperr.Error() - - if shouldQuote(es) { - fmt.Fprintf(&writer, "%q", es) - } else { - writer.WriteString(es) - } - case time.Time: - tmptime, _ := v.(time.Time) - writer.WriteString(tmptime.Format(time.RFC3339)) - default: - fmt.Fprint(&writer, v) - } - } - - if len(e.Message) > 0 { - fmt.Fprintf(&writer, " _msg=%q", e.Message) - } - - writer.WriteByte('\n') - return writer.Bytes(), nil -} - -func shouldQuote(s string) bool { - for _, b := range s { - if !((b >= 'A' && b <= 'Z') || - (b >= 'a' && b <= 'z') || - (b >= '0' && b <= '9') || - (b == '-' || b == '.' || b == '#' || - b == '/' || b == '_')) { - return true - } - } - return false -} diff --git a/vendor/github.com/Xe/ln/logger.go b/vendor/github.com/Xe/ln/logger.go deleted file mode 100644 index cdfe89e..0000000 --- a/vendor/github.com/Xe/ln/logger.go +++ /dev/null @@ -1,141 +0,0 @@ -package ln - -import ( - "fmt" - "os" - "time" - - "github.com/pkg/errors" -) - -// Logger holds the current priority and list of filters -type Logger struct { - Filters []Filter -} - -// DefaultLogger is the default implementation of Logger -var DefaultLogger *Logger - -func init() { - var defaultFilters []Filter - - // Default to STDOUT for logging, but allow LN_OUT to change it. - out := os.Stdout - if os.Getenv("LN_OUT") == "" { - out = os.Stderr - } - - defaultFilters = append(defaultFilters, NewWriterFilter(out, nil)) - - DefaultLogger = &Logger{ - Filters: defaultFilters, - } - -} - -// F is a key-value mapping for structured data. -type F map[string]interface{} - -type Fer interface { - F() map[string]interface{} -} - -// Event represents an event -type Event struct { - Time time.Time - Data F - Message string -} - -// Log is the generic logging method. -func (l *Logger) Log(xs ...interface{}) { - var bits []interface{} - event := Event{Time: time.Now()} - - addF := func(bf F) { - if event.Data == nil { - event.Data = bf - } else { - for k, v := range bf { - event.Data[k] = v - } - } - } - - // Assemble the event - for _, b := range xs { - if bf, ok := b.(F); ok { - addF(bf) - } else if fer, ok := b.(Fer); ok { - addF(F(fer.F())) - } else { - bits = append(bits, b) - } - } - - event.Message = fmt.Sprint(bits...) - - if os.Getenv("LN_DEBUG_ALL_EVENTS") == "1" { - frame := callersFrame() - if event.Data == nil { - event.Data = make(F) - } - event.Data["_lineno"] = frame.lineno - event.Data["_function"] = frame.function - event.Data["_filename"] = frame.filename - } - - l.filter(event) -} - -func (l *Logger) filter(e Event) { - for _, f := range l.Filters { - if !f.Apply(e) { - return - } - } -} - -// Error logs an error and information about the context of said error. -func (l *Logger) Error(err error, xs ...interface{}) { - data := F{} - frame := callersFrame() - - data["_lineno"] = frame.lineno - data["_function"] = frame.function - data["_filename"] = frame.filename - data["err"] = err - - cause := errors.Cause(err) - if cause != nil { - data["cause"] = cause.Error() - } - - xs = append(xs, data) - - l.Log(xs...) -} - -// Fatal logs this set of values, then exits with status code 1. -func (l *Logger) Fatal(xs ...interface{}) { - l.Log(xs...) - - os.Exit(1) -} - -// Default Implementation - -// Log is the generic logging method. -func Log(xs ...interface{}) { - DefaultLogger.Log(xs...) -} - -// Error logs an error and information about the context of said error. -func Error(err error, xs ...interface{}) { - DefaultLogger.Error(err, xs...) -} - -// Fatal logs this set of values, then exits with status code 1. -func Fatal(xs ...interface{}) { - DefaultLogger.Fatal(xs...) -} diff --git a/vendor/github.com/Xe/ln/stack.go b/vendor/github.com/Xe/ln/stack.go deleted file mode 100644 index 1cf1e7a..0000000 --- a/vendor/github.com/Xe/ln/stack.go +++ /dev/null @@ -1,44 +0,0 @@ -package ln - -import ( - "os" - "runtime" - "strings" -) - -type frame struct { - filename string - function string - lineno int -} - -// skips 2 frames, since Caller returns the current frame, and we need -// the caller's caller. -func callersFrame() frame { - var out frame - pc, file, line, ok := runtime.Caller(3) - if !ok { - return out - } - srcLoc := strings.LastIndex(file, "/src/") - if srcLoc >= 0 { - file = file[srcLoc+5:] - } - out.filename = file - out.function = functionName(pc) - out.lineno = line - - return out -} - -func functionName(pc uintptr) string { - fn := runtime.FuncForPC(pc) - if fn == nil { - return "???" - } - name := fn.Name() - beg := strings.LastIndex(name, string(os.PathSeparator)) - return name[beg+1:] - // end := strings.LastIndex(name, string(os.PathSeparator)) - // return name[end+1 : len(name)] -} -- cgit v1.2.3 From 9cbb20aea2d6b1979a47af9956dbcc8dbe2a2e08 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Sat, 20 May 2017 15:43:42 -0700 Subject: add vendor dependencies --- vendor/github.com/Xe/gopreload/doc.go | 7 + vendor/github.com/Xe/gopreload/preload.go | 26 ++++ vendor/github.com/Xe/jsonfeed/jsonfeed.go | 242 ++++++++++++++++++++++++++++++ vendor/github.com/Xe/ln/filter.go | 66 ++++++++ vendor/github.com/Xe/ln/formatter.go | 110 ++++++++++++++ vendor/github.com/Xe/ln/logger.go | 141 +++++++++++++++++ vendor/github.com/Xe/ln/stack.go | 44 ++++++ 7 files changed, 636 insertions(+) create mode 100644 vendor/github.com/Xe/gopreload/doc.go create mode 100644 vendor/github.com/Xe/gopreload/preload.go create mode 100644 vendor/github.com/Xe/jsonfeed/jsonfeed.go create mode 100644 vendor/github.com/Xe/ln/filter.go create mode 100644 vendor/github.com/Xe/ln/formatter.go create mode 100644 vendor/github.com/Xe/ln/logger.go create mode 100644 vendor/github.com/Xe/ln/stack.go (limited to 'vendor/github.com/Xe') diff --git a/vendor/github.com/Xe/gopreload/doc.go b/vendor/github.com/Xe/gopreload/doc.go new file mode 100644 index 0000000..720c5c1 --- /dev/null +++ b/vendor/github.com/Xe/gopreload/doc.go @@ -0,0 +1,7 @@ +/* +Package gopreload is a bit of a hack to emulate the behavior of LD_PRELOAD [ld-preload]. +This allows you to have automatically starting instrumentation, etc. + +[ld-preload]: http://man7.org/linux/man-pages/man8/ld.so.8.html (see LD_PRELOAD section) +*/ +package gopreload diff --git a/vendor/github.com/Xe/gopreload/preload.go b/vendor/github.com/Xe/gopreload/preload.go new file mode 100644 index 0000000..1b5a0c9 --- /dev/null +++ b/vendor/github.com/Xe/gopreload/preload.go @@ -0,0 +1,26 @@ +//+build linux,go1.8 + +package gopreload + +import ( + "log" + "os" + "plugin" + "strings" +) + +func init() { + gpv := os.Getenv("GO_PRELOAD") + if gpv == "" { + return + } + + for _, elem := range strings.Split(gpv, ",") { + log.Printf("gopreload: trying to open: %s", elem) + _, err := plugin.Open(elem) + if err != nil { + log.Printf("%v from GO_PRELOAD cannot be loaded: %v", elem, err) + continue + } + } +} diff --git a/vendor/github.com/Xe/jsonfeed/jsonfeed.go b/vendor/github.com/Xe/jsonfeed/jsonfeed.go new file mode 100644 index 0000000..e9fa0f2 --- /dev/null +++ b/vendor/github.com/Xe/jsonfeed/jsonfeed.go @@ -0,0 +1,242 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/ + +/* +Package jsonfeed is a set of types and convenience functions for reading and +parsing JSON Feed version 1 as defined here: https://jsonfeed.org/version/1 +*/ +package jsonfeed + +import ( + "encoding/json" + "io" + "time" +) + +// CurrentVersion will point to the current specification of JSON feed +// that this package implements. +const CurrentVersion = "https://jsonfeed.org/version/1" + +// Item is a single article or link in a JSON Feed. +type Item struct { + // ID is unique for that item for that feed over time. If an item + // is ever updated, the id should be unchanged. New items should + // never use a previously-used id. If an id is presented as a number + // or other type, a JSON Feed reader must coerce it to a string. + // Ideally, the id is the full URL of the resource described by the + // item, since URLs make great unique identifiers. + ID string `json:"id"` + + // URL is the URL of the resource described by the item. It’s the + // permalink. This may be the same as the id — but should be present + // regardless. + URL string `json:"url,omitempty"` + + // ExternalURL is the URL of a page elsewhere. This is especially + // useful for linkblogs. If url links to where you’re talking about + // a thing, then this links to the thing you’re talking about. + ExternalURL string `json:"external_url,omitempty"` + + // Title (optional, string) is plain text. Microblog items in + // particular may omit titles. + Title string `json:"title,omitempty"` + + // ContentHTML and ContentText are each optional strings — but one + // or both must be present. This is the HTML or plain text of the + // item. Important: the only place HTML is allowed in this format + // is in content_html. A Twitter-like service might use content_text, + // while a blog might use content_html. Use whichever makes sense + // for your resource. (It doesn’t even have to be the same for each + // item in a feed.) + ContentHTML string `json:"content_html,omitempty"` + ContentText string `json:"content_text,omitempty"` + + // Summary is a plain text sentence or two describing the item. + // This might be presented in a timeline, for instance, where a + // detail view would display all of ContentHTML or ContentText. + Summary string `json:"summary,omitempty"` + + // Image is the URL of the main image for the item. This image + // may also appear in the content_html — if so, it’s a hint to + // the feed reader that this is the main, featured image. Feed + // readers may use the image as a preview (probably resized as + // a thumbnail and placed in a timeline). + Image string `json:"image,omitempty"` + + // BannerImage is the URL of an image to use as a banner. Some + // blogging systems (such as Medium) display a different banner + // image chosen to go with each post, but that image wouldn’t + // otherwise appear in the content_html. A feed reader with a + // detail view may choose to show this banner image at the top + // of the detail view, possibly with the title overlaid. + BannerImage string `json:"banner_image,omitempty"` + + // DatePublished specifies the date of this Item's publication. + DatePublished time.Time `json:"date_published,omitempty"` + + // DateModified specifies the date of this Item's last modification + // (if applicable) + DateModified time.Time `json:"date_modified,omitempty"` + + // Author has the same structure as the top-level author. If not + // specified in an item, then the top-level author, if present, + // is the author of the item. + Author *Author `json:"author,omitempty"` + + // Tags can have any plain text values you want. Tags tend to be + // just one word, but they may be anything. Note: they are not + // the equivalent of Twitter hashtags. Some blogging systems and + // other feed formats call these categories. + Tags []string `json:"tags,omitempty"` + + // Attachments (optional, array) lists related resources. Podcasts, + // for instance, would include an attachment that’s an audio or + // video file. + Attachments []Attachment `json:"attachments,omitempty"` +} + +// Author specifies the feed author. The author object has several members. +// These are all optional, but if you provide an author object, then at +// least one is required. +type Author struct { + // Name is the author's name. + Name string `json:"name,omitempty"` + + // URL is the URL of a site owned by the author. It could be a + // blog, micro-blog, Twitter account, and so on. Ideally the linked-to + // page provides a way to contact the author, but that’s not + // required. The URL could be a mailto: link, though we suspect + // that will be rare. + URL string `json:"url,omitempty"` + + // Avatar is the URL for an image for the author. As with icon, + // it should be square and relatively large — such as 512 x 512 — + // and should use transparency where appropriate, since it may + // be rendered on a non-white background. + Avatar string `json:"avatar,omitempty"` +} + +// Hub describes endpoints that can be used to subscribe to real-time +// notifications from the publisher of this feed. Each object has a type +// and url, both of which are required. +type Hub struct { + Type string `json:"type"` + URL string `json:"url"` +} + +// Attachment is a related resource to an Item. If the Feed describes a +// podcast, this would refer to the episodes of said podcast. +type Attachment struct { + // URL specifies the location of the attachment. + URL string `json:"url"` + + // MIMEType specifies the type of the attachment, such as "audio/mpeg". + MIMEType string `json:"mime_type"` + + // Title is a name for the attachment. Important: if there are multiple + // attachments, and two or more have the exact same title (when title + // is present), then they are considered as alternate representations + // of the same thing. In this way a podcaster, for instance, might + // provide an audio recording in different formats. + Title string `json:"title,omitifempty"` + + // SizeInBytes specifies the attachment filesize in bytes. + SizeInBytes int64 `json:"size_in_bytes,omitempty"` + + // DurationInSeconds specifies how long the attachment takes to listen + // to or watch. + DurationInSeconds int64 `json:"duration_in_seconds,omitempty"` +} + +// Feed is a list that may change over time, and the individual items in the +// list may change. +// +// Think of a blog or microblog, Twitter or Facebook timeline, set of commits +// to a repository, or even a server log. These are all lists, and each could +// be described by a Feed. +// +// A JSON Feed starts with some info at the top: it says where the Feed comes +// from, and may say who created it and so on. +type Feed struct { + // Version is the URL of the version of the format the Feed uses. + Version string `json:"version"` + + // Title is the name of the Feed, which will often correspond to the + // name of the website (blog, for instance), though not necessarily. + Title string `json:"title"` + + // HomePageURL is the URL of the resource that the Feed describes. + // This resource may or may not actually be a “home” page, but it + // should be an HTML page. If a Feed is published on the public web, + // this should be considered as required. But it may not make sense + // in the case of a file created on a desktop computer, when that + // file is not shared or is shared only privately. + // + // This field is strongly reccomended, but not required. + HomePageURL string `json:"home_page_url,omitempty"` + + // FeedURL is the URL of the Feed, and serves as the unique identifier + // for the Feed. As with home_page_url, this should be considered + // required for Feeds on the public web. + // + // This field is strongly reccomended, but not required. + FeedURL string `json:"Feed_url,omitempty"` + + // Description provides more detail, beyond the title, on what the Feed + // is about. A Feed reader may display this text. + Description string `json:"description,omitempty"` + + // UserComment is a description of the purpose of the Feed. This is for + // the use of people looking at the raw JSON, and should be ignored by + // Feed readers. + UserComment string `json:"user_comment,omitempty"` + + // NextURL is the URL of a Feed that provides the next n items, where + // n is determined by the publisher. This allows for pagination, but + // with the expectation that reader software is not required to use it + // and probably won’t use it very often. next_url must not be the same + // as Feed_url, and it must not be the same as a previous next_url + // (to avoid infinite loops). + NextURL string `json:"next_url,omitempty"` + + // Icon is the URL of an image for the Feed suitable to be used in a + // timeline, much the way an avatar might be used. It should be square + // and relatively large — such as 512 x 512 — so that it can be scaled-down + // and so that it can look good on retina displays. It should use transparency + // where appropriate, since it may be rendered on a non-white background. + Icon string `json:"icon,omitempty"` + + // Favicon is the URL of an image for the Feed suitable to be used in a + // source list. It should be square and relatively small, but not smaller + // than 64 x 64 (so that it can look good on retina displays). As with icon, + // this image should use transparency where appropriate, since it may be + // rendered on a non-white background. + Favicon string `json:"favicon,omitempty"` + + // Author specifies the Feed author. + Author Author `json:"author,omitempty"` + + // Expired specifies if the Feed will never update again. A Feed for a + // temporary event, such as an instance of the Olympics, could expire. + // If the value is true, then it’s expired. Any other value, or the + // absence of expired, means the Feed may continue to update. + Expired bool `json:"expired,omitempty"` + + // Hubs describes endpoints that can be used to subscribe to real-time + // notifications from the publisher of this Feed. + Hubs []Hub `json:"hubs,omitempty"` + + // Items is the list of Items in this Feed. + Items []Item `json:"items"` +} + +// Parse reads a JSON feed object out of a reader. +func Parse(r io.Reader) (Feed, error) { + var feed Feed + decoder := json.NewDecoder(r) + if err := decoder.Decode(&feed); err != nil { + return Feed{}, err + } + return feed, nil +} diff --git a/vendor/github.com/Xe/ln/filter.go b/vendor/github.com/Xe/ln/filter.go new file mode 100644 index 0000000..586efef --- /dev/null +++ b/vendor/github.com/Xe/ln/filter.go @@ -0,0 +1,66 @@ +package ln + +import ( + "io" + "sync" +) + +// Filter interface for defining chain filters +type Filter interface { + Apply(Event) bool + Run() + Close() +} + +// FilterFunc allows simple functions to implement the Filter interface +type FilterFunc func(e Event) bool + +// Apply implements the Filter interface +func (ff FilterFunc) Apply(e Event) bool { + return ff(e) +} + +// Run implements the Filter interface +func (ff FilterFunc) Run() {} + +// Close implements the Filter interface +func (ff FilterFunc) Close() {} + +// WriterFilter implements a filter, which arbitrarily writes to an io.Writer +type WriterFilter struct { + sync.Mutex + Out io.Writer + Formatter Formatter +} + +// NewWriterFilter creates a filter to add to the chain +func NewWriterFilter(out io.Writer, format Formatter) *WriterFilter { + if format == nil { + format = DefaultFormatter + } + return &WriterFilter{ + Out: out, + Formatter: format, + } +} + +// Apply implements the Filter interface +func (w *WriterFilter) Apply(e Event) bool { + output, err := w.Formatter.Format(e) + if err == nil { + w.Lock() + w.Out.Write(output) + w.Unlock() + } + + return true +} + +// Run implements the Filter interface +func (w *WriterFilter) Run() {} + +// Close implements the Filter interface +func (w *WriterFilter) Close() {} + +// NilFilter is safe to return as a Filter, but does nothing +var NilFilter = FilterFunc(func(e Event) bool { return true }) diff --git a/vendor/github.com/Xe/ln/formatter.go b/vendor/github.com/Xe/ln/formatter.go new file mode 100644 index 0000000..ecd4743 --- /dev/null +++ b/vendor/github.com/Xe/ln/formatter.go @@ -0,0 +1,110 @@ +package ln + +import ( + "bytes" + "fmt" + "time" +) + +var ( + // DefaultTimeFormat represents the way in which time will be formatted by default + DefaultTimeFormat = time.RFC3339 +) + +// Formatter defines the formatting of events +type Formatter interface { + Format(Event) ([]byte, error) +} + +// DefaultFormatter is the default way in which to format events +var DefaultFormatter Formatter + +func init() { + DefaultFormatter = NewTextFormatter() +} + +// TextFormatter formats events as key value pairs. +// Any remaining text not wrapped in an instance of `F` will be +// placed at the end. +type TextFormatter struct { + TimeFormat string +} + +// NewTextFormatter returns a Formatter that outputs as text. +func NewTextFormatter() Formatter { + return &TextFormatter{TimeFormat: DefaultTimeFormat} +} + +// Format implements the Formatter interface +func (t *TextFormatter) Format(e Event) ([]byte, error) { + var writer bytes.Buffer + + writer.WriteString("time=\"") + writer.WriteString(e.Time.Format(t.TimeFormat)) + writer.WriteString("\"") + + keys := make([]string, len(e.Data)) + i := 0 + + for k := range e.Data { + keys[i] = k + i++ + } + + for _, k := range keys { + v := e.Data[k] + + writer.WriteByte(' ') + if shouldQuote(k) { + writer.WriteString(fmt.Sprintf("%q", k)) + } else { + writer.WriteString(k) + } + + writer.WriteByte('=') + + switch v.(type) { + case string: + vs, _ := v.(string) + if shouldQuote(vs) { + fmt.Fprintf(&writer, "%q", vs) + } else { + writer.WriteString(vs) + } + case error: + tmperr, _ := v.(error) + es := tmperr.Error() + + if shouldQuote(es) { + fmt.Fprintf(&writer, "%q", es) + } else { + writer.WriteString(es) + } + case time.Time: + tmptime, _ := v.(time.Time) + writer.WriteString(tmptime.Format(time.RFC3339)) + default: + fmt.Fprint(&writer, v) + } + } + + if len(e.Message) > 0 { + fmt.Fprintf(&writer, " _msg=%q", e.Message) + } + + writer.WriteByte('\n') + return writer.Bytes(), nil +} + +func shouldQuote(s string) bool { + for _, b := range s { + if !((b >= 'A' && b <= 'Z') || + (b >= 'a' && b <= 'z') || + (b >= '0' && b <= '9') || + (b == '-' || b == '.' || b == '#' || + b == '/' || b == '_')) { + return true + } + } + return false +} diff --git a/vendor/github.com/Xe/ln/logger.go b/vendor/github.com/Xe/ln/logger.go new file mode 100644 index 0000000..cdfe89e --- /dev/null +++ b/vendor/github.com/Xe/ln/logger.go @@ -0,0 +1,141 @@ +package ln + +import ( + "fmt" + "os" + "time" + + "github.com/pkg/errors" +) + +// Logger holds the current priority and list of filters +type Logger struct { + Filters []Filter +} + +// DefaultLogger is the default implementation of Logger +var DefaultLogger *Logger + +func init() { + var defaultFilters []Filter + + // Default to STDOUT for logging, but allow LN_OUT to change it. + out := os.Stdout + if os.Getenv("LN_OUT") == "" { + out = os.Stderr + } + + defaultFilters = append(defaultFilters, NewWriterFilter(out, nil)) + + DefaultLogger = &Logger{ + Filters: defaultFilters, + } + +} + +// F is a key-value mapping for structured data. +type F map[string]interface{} + +type Fer interface { + F() map[string]interface{} +} + +// Event represents an event +type Event struct { + Time time.Time + Data F + Message string +} + +// Log is the generic logging method. +func (l *Logger) Log(xs ...interface{}) { + var bits []interface{} + event := Event{Time: time.Now()} + + addF := func(bf F) { + if event.Data == nil { + event.Data = bf + } else { + for k, v := range bf { + event.Data[k] = v + } + } + } + + // Assemble the event + for _, b := range xs { + if bf, ok := b.(F); ok { + addF(bf) + } else if fer, ok := b.(Fer); ok { + addF(F(fer.F())) + } else { + bits = append(bits, b) + } + } + + event.Message = fmt.Sprint(bits...) + + if os.Getenv("LN_DEBUG_ALL_EVENTS") == "1" { + frame := callersFrame() + if event.Data == nil { + event.Data = make(F) + } + event.Data["_lineno"] = frame.lineno + event.Data["_function"] = frame.function + event.Data["_filename"] = frame.filename + } + + l.filter(event) +} + +func (l *Logger) filter(e Event) { + for _, f := range l.Filters { + if !f.Apply(e) { + return + } + } +} + +// Error logs an error and information about the context of said error. +func (l *Logger) Error(err error, xs ...interface{}) { + data := F{} + frame := callersFrame() + + data["_lineno"] = frame.lineno + data["_function"] = frame.function + data["_filename"] = frame.filename + data["err"] = err + + cause := errors.Cause(err) + if cause != nil { + data["cause"] = cause.Error() + } + + xs = append(xs, data) + + l.Log(xs...) +} + +// Fatal logs this set of values, then exits with status code 1. +func (l *Logger) Fatal(xs ...interface{}) { + l.Log(xs...) + + os.Exit(1) +} + +// Default Implementation + +// Log is the generic logging method. +func Log(xs ...interface{}) { + DefaultLogger.Log(xs...) +} + +// Error logs an error and information about the context of said error. +func Error(err error, xs ...interface{}) { + DefaultLogger.Error(err, xs...) +} + +// Fatal logs this set of values, then exits with status code 1. +func Fatal(xs ...interface{}) { + DefaultLogger.Fatal(xs...) +} diff --git a/vendor/github.com/Xe/ln/stack.go b/vendor/github.com/Xe/ln/stack.go new file mode 100644 index 0000000..1cf1e7a --- /dev/null +++ b/vendor/github.com/Xe/ln/stack.go @@ -0,0 +1,44 @@ +package ln + +import ( + "os" + "runtime" + "strings" +) + +type frame struct { + filename string + function string + lineno int +} + +// skips 2 frames, since Caller returns the current frame, and we need +// the caller's caller. +func callersFrame() frame { + var out frame + pc, file, line, ok := runtime.Caller(3) + if !ok { + return out + } + srcLoc := strings.LastIndex(file, "/src/") + if srcLoc >= 0 { + file = file[srcLoc+5:] + } + out.filename = file + out.function = functionName(pc) + out.lineno = line + + return out +} + +func functionName(pc uintptr) string { + fn := runtime.FuncForPC(pc) + if fn == nil { + return "???" + } + name := fn.Name() + beg := strings.LastIndex(name, string(os.PathSeparator)) + return name[beg+1:] + // end := strings.LastIndex(name, string(os.PathSeparator)) + // return name[end+1 : len(name)] +} -- cgit v1.2.3