<commit_before>package main

import (
	"bufio"
	"bytes"
	"log"
	"net/http"
	"time"

	"github.com/bmizerany/lpx"
	"github.com/heroku/slog"
	"github.com/kr/logfmt"
)

var (
	TokenPrefix = []byte("t.")
	Heroku      = []byte("heroku")
)

// "Parse tree" from hell
func serveDrain(w http.ResponseWriter, r *http.Request) {
	ctx := slog.Context{}
	defer func() { LogWithContext(ctx) }()

	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		ctx.Count("errors.drain.wrong.method", 1)
		return
	}

	id := r.Header.Get("Logplex-Drain-Token")

	if id == "" {
		w.WriteHeader(http.StatusBadRequest)
		ctx.Count("errors.drain.missing.token", 1)
		return
	}

	ctx.Count("batch", 1)

	parseStart := time.Now()
	lp := lpx.NewReader(bufio.NewReader(r.Body))

	for lp.Next() {
		ctx.Count("lines.total", 1)
		header := lp.Header()

		// If the syslog App Name Header field containts what looks like a log token,
		// let's assume it's an override of the id and we're getting the data from the magic
		// channel
		if bytes.HasPrefix(header.Name, TokenPrefix) {
			id = string(header.Name)
		}

		msg := lp.Bytes()
		switch {
		case bytes.Equal(header.Name, Heroku), bytes.HasPrefix(header.Name, TokenPrefix):
			t, e := time.Parse("2006-01-02T15:04:05.000000+00:00", string(lp.Header().Time))
			if e != nil {
				log.Printf("Error Parsing Time(%s): %q\n", string(lp.Header().Time), e)
				continue
			}
			timestamp := t.UnixNano() / int64(time.Microsecond)

			pid := string(header.Procid)
			switch pid {
			case "router":

				switch {
				// router logs with a H error code in them
				case bytes.Contains(msg, keyCodeH):
					ctx.Count("lines.router.error", 1)
					re := routerError{}
					err := logfmt.Unmarshal(msg, &re)
					if err != nil {
						log.Printf("logfmt unmarshal error: %s\n", err)
						continue
					}
					routerEventPoints <- []interface{}{timestamp, id, re.Code}

				// likely a standard router log
				default:
					ctx.Count("lines.router", 1)
					rm := routerMsg{}
					err := logfmt.Unmarshal(msg, &rm)
					if err != nil {
						log.Printf("logfmt unmarshal error: %s\n", err)
						continue
					}
					routerPoints <- []interface{}{timestamp, id, rm.Status, rm.Service}
				}

				// Non router logs, so either dynos, runtime, etc
			default:
				switch {
				case bytes.HasPrefix(msg, dynoErrorSentinel):
					ctx.Count("lines.dyno.error", 1)
					de, err := parseBytesToDynoError(msg)
					if err != nil {
						log.Printf("Unable to parse dyno error message: %q\n", err)
					}
					dynoEventsPoints <- []interface{}{timestamp, id, string(lp.Header().Procid), "R", de.Code, string(msg)}

				case bytes.Contains(msg, dynoMemMsgSentinel):
					ctx.Count("lines.dyno.mem", 1)
					dm := dynoMemMsg{}
					err := logfmt.Unmarshal(msg, &dm)
					if err != nil {
						log.Printf("logfmt unmarshal error: %s\n", err)
						continue
					}
					if dm.Source != "" {
						dynoMemPoints <- []interface{}{timestamp, id, dm.Source, dm.MemoryCache, dm.MemoryPgpgin, dm.MemoryPgpgout, dm.MemoryRSS, dm.MemorySwap, dm.MemoryTotal}
					}
				case bytes.Contains(msg, dynoLoadMsgSentinel):
					ctx.Count("lines.dyno.load", 1)
					dm := dynoLoadMsg{}
					err := logfmt.Unmarshal(msg, &dm)
					if err != nil {
						log.Printf("logfmt unmarshal error: %s\n", err)
						continue
					}
					if dm.Source != "" {
						dynoLoadPoints <- []interface{}{timestamp, id, dm.Source, dm.LoadAvg1Min, dm.LoadAvg5Min, dm.LoadAvg15Min}
					}
				default: // unknown
					ctx.Count("lines.unknown.heroku", 1)
					if Debug {
						log.Printf("Unknown Heroku Line - Header: PRI: %s, Time: %s, Hostname: %s, Name: %s, ProcId: %s, MsgId: %s - Body: %s",
							header.PrivalVersion,
							header.Time,
							header.Hostname,
							header.Name,
							header.Procid,
							header.Msgid,
							string(msg),
						)
					}
				}
			}
		default: // non heroku lines
			ctx.Count("lines.unknown.user", 1)
			if Debug {
				log.Printf("Unknown User Line - Header: PRI: %s, Time: %s, Hostname: %s, Name: %s, ProcId: %s, MsgId: %s - Body: %s",
					header.PrivalVersion,
					header.Time,
					header.Hostname,
					header.Name,
					header.Procid,
					header.Msgid,
					string(msg),
				)
			}
		}
	}
	ctx.MeasureSince("lines.parse.time", parseStart)

	w.WriteHeader(http.StatusNoContent)
}
<commit_msg>Content-Length: 0<commit_after>package main

import (
	"bufio"
	"bytes"
	"log"
	"net/http"
	"time"

	"github.com/bmizerany/lpx"
	"github.com/heroku/slog"
	"github.com/kr/logfmt"
)

var (
	TokenPrefix = []byte("t.")
	Heroku      = []byte("heroku")
)

// "Parse tree" from hell
func serveDrain(w http.ResponseWriter, r *http.Request) {
	ctx := slog.Context{}
	defer func() { LogWithContext(ctx) }()
	w.Header().Set("Content-Length", "0")

	if r.Method != "POST" {
		w.WriteHeader(http.StatusMethodNotAllowed)
		ctx.Count("errors.drain.wrong.method", 1)
		return
	}

	id := r.Header.Get("Logplex-Drain-Token")

	if id == "" {
		w.WriteHeader(http.StatusBadRequest)
		ctx.Count("errors.drain.missing.token", 1)
		return
	}

	ctx.Count("batch", 1)

	parseStart := time.Now()
	lp := lpx.NewReader(bufio.NewReader(r.Body))

	for lp.Next() {
		ctx.Count("lines.total", 1)
		header := lp.Header()

		// If the syslog App Name Header field containts what looks like a log token,
		// let's assume it's an override of the id and we're getting the data from the magic
		// channel
		if bytes.HasPrefix(header.Name, TokenPrefix) {
			id = string(header.Name)
		}

		msg := lp.Bytes()
		switch {
		case bytes.Equal(header.Name, Heroku), bytes.HasPrefix(header.Name, TokenPrefix):
			t, e := time.Parse("2006-01-02T15:04:05.000000+00:00", string(lp.Header().Time))
			if e != nil {
				log.Printf("Error Parsing Time(%s): %q\n", string(lp.Header().Time), e)
				continue
			}
			timestamp := t.UnixNano() / int64(time.Microsecond)

			pid := string(header.Procid)
			switch pid {
			case "router":

				switch {
				// router logs with a H error code in them
				case bytes.Contains(msg, keyCodeH):
					ctx.Count("lines.router.error", 1)
					re := routerError{}
					err := logfmt.Unmarshal(msg, &re)
					if err != nil {
						log.Printf("logfmt unmarshal error: %s\n", err)
						continue
					}
					routerEventPoints <- []interface{}{timestamp, id, re.Code}

				// likely a standard router log
				default:
					ctx.Count("lines.router", 1)
					rm := routerMsg{}
					err := logfmt.Unmarshal(msg, &rm)
					if err != nil {
						log.Printf("logfmt unmarshal error: %s\n", err)
						continue
					}
					routerPoints <- []interface{}{timestamp, id, rm.Status, rm.Service}
				}

				// Non router logs, so either dynos, runtime, etc
			default:
				switch {
				case bytes.HasPrefix(msg, dynoErrorSentinel):
					ctx.Count("lines.dyno.error", 1)
					de, err := parseBytesToDynoError(msg)
					if err != nil {
						log.Printf("Unable to parse dyno error message: %q\n", err)
					}
					dynoEventsPoints <- []interface{}{timestamp, id, string(lp.Header().Procid), "R", de.Code, string(msg)}

				case bytes.Contains(msg, dynoMemMsgSentinel):
					ctx.Count("lines.dyno.mem", 1)
					dm := dynoMemMsg{}
					err := logfmt.Unmarshal(msg, &dm)
					if err != nil {
						log.Printf("logfmt unmarshal error: %s\n", err)
						continue
					}
					if dm.Source != "" {
						dynoMemPoints <- []interface{}{timestamp, id, dm.Source, dm.MemoryCache, dm.MemoryPgpgin, dm.MemoryPgpgout, dm.MemoryRSS, dm.MemorySwap, dm.MemoryTotal}
					}
				case bytes.Contains(msg, dynoLoadMsgSentinel):
					ctx.Count("lines.dyno.load", 1)
					dm := dynoLoadMsg{}
					err := logfmt.Unmarshal(msg, &dm)
					if err != nil {
						log.Printf("logfmt unmarshal error: %s\n", err)
						continue
					}
					if dm.Source != "" {
						dynoLoadPoints <- []interface{}{timestamp, id, dm.Source, dm.LoadAvg1Min, dm.LoadAvg5Min, dm.LoadAvg15Min}
					}
				default: // unknown
					ctx.Count("lines.unknown.heroku", 1)
					if Debug {
						log.Printf("Unknown Heroku Line - Header: PRI: %s, Time: %s, Hostname: %s, Name: %s, ProcId: %s, MsgId: %s - Body: %s",
							header.PrivalVersion,
							header.Time,
							header.Hostname,
							header.Name,
							header.Procid,
							header.Msgid,
							string(msg),
						)
					}
				}
			}
		default: // non heroku lines
			ctx.Count("lines.unknown.user", 1)
			if Debug {
				log.Printf("Unknown User Line - Header: PRI: %s, Time: %s, Hostname: %s, Name: %s, ProcId: %s, MsgId: %s - Body: %s",
					header.PrivalVersion,
					header.Time,
					header.Hostname,
					header.Name,
					header.Procid,
					header.Msgid,
					string(msg),
				)
			}
		}
	}
	ctx.MeasureSince("lines.parse.time", parseStart)

	w.WriteHeader(http.StatusNoContent)
}
<|endoftext|>


<commit_before>// Copyright 2015 Ethan Miller. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package editor

import (
	"fmt"
	"strings"
	"unicode"

	"github.com/millere/jk/keys"
	"github.com/millere/jk/tagbuf"
	"github.com/millere/window"
	"github.com/nsf/termbox-go"
)

// A View contains a buffer and knows how to draw it to an area
type View struct {
	parent     *Editor
	buffer     *subview
	tag        *subview
	statusArea *window.Area
	mode       *Mode
	modeName   string
	modes      *map[string]*Mode
	target     *subview
}

type subview struct {
	area      *window.Area
	C         Cursor
	back      WriteBuffer
	firstLine int
}

// A Cursor indicates where the cursor is
// 0, 0 is the first position in a file
type Cursor struct {
	Line, Column int
}

// ViewWithBuffer creates a new view and area with the given buffer in the editor.
func (e *Editor) ViewWithBuffer(a WriteBuffer, m string, x, y, w, h int) (View, error) {
	mode, ok := e.modes[m]
	if !ok {
		return View{}, fmt.Errorf("Mode \"%v\" does not exist", m)
	}
	tagarea := window.New(x, y, w, 1)
	bufarea := window.New(x, y+1, w, h-1)
	statusarea := window.New(x, y+h-1, w, 1)
	v := View{
		parent: e,
		buffer: &subview{
			area: bufarea,
			C:    Cursor{0, 0},
			back: a,
		},
		tag: &subview{
			area: tagarea,
			C:    Cursor{0, 0},
			back: tagbuf.New(),
		},

		mode:       mode,
		modeName:   m,
		modes:      &e.modes,
		statusArea: statusarea,
	}
	v.target = v.buffer
	return v, nil
}

// Draw draws a View into its area
func (v *View) Draw() {
	v.drawTag()
	v.drawBuffer()
	v.drawStatusBar()
}

func (v *View) drawTag() {
	line, _ := v.tag.back.Get()
	_, w := v.tag.area.Size()
	v.tag.area.WriteLine(line, 0, 0, w, termbox.ColorBlack, termbox.ColorWhite)
	if v.tag == v.target {
		v.tag.area.SetCursor(v.tag.C.Column, 0)
	}
}

func (v *View) drawBuffer() {
	tabStop := 4
	var tabsAtCursor int
	v.buffer.area.Clear()

	_, h := v.buffer.area.Size()
	for l := 0; l < h; l++ {
		tabs := 0
		line, err := v.buffer.back.GetLine(l + v.buffer.firstLine)
		if l+v.buffer.firstLine == v.buffer.C.Line && v.buffer.C.Column-1 >= 0 {
			tabsAtCursor = strings.Count(line[:v.buffer.C.Column-1], "\t")
		}
		if err != nil {
			break
		}
		for i, c := range line {
			if c == '\t' {
				tabs++
			}
			v.buffer.area.SetCell(i+tabStop*tabs, l, c, termbox.ColorDefault, termbox.ColorDefault)
		}
	}
	if v.buffer == v.target {
		v.buffer.area.SetCursor(v.buffer.C.Column+4*tabsAtCursor, v.buffer.C.Line)
	}
}

func (v *View) drawStatusBar() {
	v.statusArea.Clear()
	_, w := v.statusArea.Size()
	v.statusArea.WriteLine(v.modeName, 0, 0, w, termbox.ColorBlack, termbox.ColorWhite)
}

// SetCursor sets the cursor to absolute coordinates in the file
func (v *View) SetCursor(row, column int) {
	// if buffer is empty, cursor can only be at 0,0
	if v.target.back.Len() == 0 {
		v.target.C.Column = 0
		v.target.C.Line = 0
	} else {
		total := v.target.back.Lines()
		if row >= total {
			row = total - 1
		}
		line, err := v.target.back.GetLine(row)
		if err != nil {
			row = v.target.C.Line
		}
		l := len(line)
		if l > 0 && line[l-1] == '\n' {
			l -= 1
		}
		if column > l {
			column = l
		}
		if column < 0 {
			column = 0
		}
		v.target.C.Column = column
		v.target.C.Line = row
	}

}

// MoveCursor moves the cursor relative to where it is now
func (v *View) MoveCursor(dc, dr int) {
	v.SetCursor(v.target.C.Line+dr, v.target.C.Column+dc)
}

// SetMode sets a view's mode, so that it handles events per that mode
func (v *View) SetMode(m *Mode, n string) {
	if v.mode.OnExit != nil {
		v.mode.OnExit(v)
	}
	v.mode = m
	v.modeName = n
	if v.mode.OnEnter != nil {
		v.mode.OnEnter(v)
	}
}

// Do tells a view to handle a keypress according to its mode
func (v *View) Do(k keys.Keypress) error {
	f, ok := v.mode.EventMap[k]
	if ok {
		return f(v, 1)
	}
	LogItAll.Printf("No function bound to key %v", k)
	return nil

}

// InsertChar inserts the single rune r at the cursor
func (v *View) InsertChar(c byte) {
	off := v.target.back.OffsetOf(v.target.C.Line, v.target.C.Column)
	//LogItAll.Println("Inserting", c, "at", v.C.Line, v.C.Column, "giving an offset of", off)
	v.target.back.WriteAt([]byte{c}, off)

}

// DeleteBackwards deletes one character backwards
func (v *View) DeleteBackwards() {
	offset := v.target.back.OffsetOf(v.target.C.Line, v.target.C.Column)
	//LogItAll.Println("Delete:", v.C.Line, v.C.Column, offset-2)
	if offset < 1 {
		return
	}
	v.target.back.Delete(1, offset-2)
}

func (v *View) resultUnderCursor() ([]byte, error) {
	line, err := v.target.back.GetLine(v.target.C.Line)
	if err != nil {
		return nil, err
	}

	var i, j int

	LogItAll.Println("In line:", string(line), "C:", v.target.C.Column)
	for n, c := range string(line) {
		if n < v.target.C.Column && unicode.IsSpace(c) {
			LogItAll.Println("setting i to", n)
			i = n + 1
		}
		if n >= v.target.C.Column && unicode.IsSpace(c) {
			LogItAll.Println("setting j to", n)
			j = n
			break
		}
	}
	// if no space after...
	if j == 0 {
		j = len(line)
	}

	LogItAll.Println("Command:", string(line[i:j]), "i:", i, "j:", j)
	return v.parent.Interpret("(" + string(line[i:j]) + ")")
}

func (v *View) ExecInsertUnderCursor() error {
	toIns, err := v.resultUnderCursor()
	if err != nil {
		return err
	}

	v.buffer.back.WriteAt(toIns,
		v.buffer.back.OffsetOf(v.buffer.C.Line, v.buffer.C.Column))
	return nil
}

func (v *View) AlternateTag() {
	if v.target == v.buffer {
		v.target = v.tag
	} else {
		v.target = v.buffer
	}
}
<commit_msg>Modeline indicates buffers<commit_after>// Copyright 2015 Ethan Miller. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package editor

import (
	"fmt"
	"strings"
	"unicode"

	"github.com/millere/jk/keys"
	"github.com/millere/jk/tagbuf"
	"github.com/millere/window"
	"github.com/nsf/termbox-go"
)

// A View contains a buffer and knows how to draw it to an area
type View struct {
	parent     *Editor
	buffer     *subview
	tag        *subview
	statusArea *window.Area
	mode       *Mode
	modeName   string
	modes      *map[string]*Mode
	target     *subview
}

type subview struct {
	area      *window.Area
	C         Cursor
	back      WriteBuffer
	firstLine int
}

// A Cursor indicates where the cursor is
// 0, 0 is the first position in a file
type Cursor struct {
	Line, Column int
}

// ViewWithBuffer creates a new view and area with the given buffer in the editor.
func (e *Editor) ViewWithBuffer(a WriteBuffer, m string, x, y, w, h int) (View, error) {
	mode, ok := e.modes[m]
	if !ok {
		return View{}, fmt.Errorf("Mode \"%v\" does not exist", m)
	}
	tagarea := window.New(x, y, w, 1)
	bufarea := window.New(x, y+1, w, h-1)
	statusarea := window.New(x, y+h-1, w, 1)
	v := View{
		parent: e,
		buffer: &subview{
			area: bufarea,
			C:    Cursor{0, 0},
			back: a,
		},
		tag: &subview{
			area: tagarea,
			C:    Cursor{0, 0},
			back: tagbuf.New(),
		},

		mode:       mode,
		modeName:   m,
		modes:      &e.modes,
		statusArea: statusarea,
	}
	v.target = v.buffer
	return v, nil
}

// Draw draws a View into its area
func (v *View) Draw() {
	v.drawTag()
	v.drawBuffer()
	v.drawStatusBar()
}

func (v *View) drawTag() {
	line, _ := v.tag.back.Get()
	_, w := v.tag.area.Size()
	v.tag.area.WriteLine(line, 0, 0, w, termbox.ColorBlack, termbox.ColorWhite)
	if v.tag == v.target {
		v.tag.area.SetCursor(v.tag.C.Column, 0)
	}
}

func (v *View) drawBuffer() {
	tabStop := 4
	var tabsAtCursor int
	v.buffer.area.Clear()

	_, h := v.buffer.area.Size()
	for l := 0; l < h; l++ {
		tabs := 0
		line, err := v.buffer.back.GetLine(l + v.buffer.firstLine)
		if l+v.buffer.firstLine == v.buffer.C.Line && v.buffer.C.Column-1 >= 0 {
			tabsAtCursor = strings.Count(line[:v.buffer.C.Column-1], "\t")
		}
		if err != nil {
			break
		}
		for i, c := range line {
			if c == '\t' {
				tabs++
			}
			v.buffer.area.SetCell(i+tabStop*tabs, l, c, termbox.ColorDefault, termbox.ColorDefault)
		}
	}
	if v.buffer == v.target {
		v.buffer.area.SetCursor(v.buffer.C.Column+4*tabsAtCursor, v.buffer.C.Line)
	}
}

func (v *View) drawStatusBar() {
	v.statusArea.Clear()
	_, w := v.statusArea.Size()
	modeline := fmt.Sprintf("%s [buffer %d/%d]",
		v.modeName,
		v.parent.currentView+1,
		len(v.parent.views),
	)
	v.statusArea.WriteLine(modeline, 0, 0, w, termbox.ColorBlack, termbox.ColorWhite)
}

// SetCursor sets the cursor to absolute coordinates in the file
func (v *View) SetCursor(row, column int) {
	// if buffer is empty, cursor can only be at 0,0
	if v.target.back.Len() == 0 {
		v.target.C.Column = 0
		v.target.C.Line = 0
	} else {
		total := v.target.back.Lines()
		if row >= total {
			row = total - 1
		}
		line, err := v.target.back.GetLine(row)
		if err != nil {
			row = v.target.C.Line
		}
		l := len(line)
		if l > 0 && line[l-1] == '\n' {
			l -= 1
		}
		if column > l {
			column = l
		}
		if column < 0 {
			column = 0
		}
		v.target.C.Column = column
		v.target.C.Line = row
	}

}

// MoveCursor moves the cursor relative to where it is now
func (v *View) MoveCursor(dc, dr int) {
	v.SetCursor(v.target.C.Line+dr, v.target.C.Column+dc)
}

// SetMode sets a view's mode, so that it handles events per that mode
func (v *View) SetMode(m *Mode, n string) {
	if v.mode.OnExit != nil {
		v.mode.OnExit(v)
	}
	v.mode = m
	v.modeName = n
	if v.mode.OnEnter != nil {
		v.mode.OnEnter(v)
	}
}

// Do tells a view to handle a keypress according to its mode
func (v *View) Do(k keys.Keypress) error {
	f, ok := v.mode.EventMap[k]
	if ok {
		return f(v, 1)
	}
	LogItAll.Printf("No function bound to key %v", k)
	return nil

}

// InsertChar inserts the single rune r at the cursor
func (v *View) InsertChar(c byte) {
	off := v.target.back.OffsetOf(v.target.C.Line, v.target.C.Column)
	//LogItAll.Println("Inserting", c, "at", v.C.Line, v.C.Column, "giving an offset of", off)
	v.target.back.WriteAt([]byte{c}, off)

}

// DeleteBackwards deletes one character backwards
func (v *View) DeleteBackwards() {
	offset := v.target.back.OffsetOf(v.target.C.Line, v.target.C.Column)
	//LogItAll.Println("Delete:", v.C.Line, v.C.Column, offset-2)
	if offset < 1 {
		return
	}
	v.target.back.Delete(1, offset-2)
}

func (v *View) resultUnderCursor() ([]byte, error) {
	line, err := v.target.back.GetLine(v.target.C.Line)
	if err != nil {
		return nil, err
	}

	var i, j int

	LogItAll.Println("In line:", string(line), "C:", v.target.C.Column)
	for n, c := range string(line) {
		if n < v.target.C.Column && unicode.IsSpace(c) {
			LogItAll.Println("setting i to", n)
			i = n + 1
		}
		if n >= v.target.C.Column && unicode.IsSpace(c) {
			LogItAll.Println("setting j to", n)
			j = n
			break
		}
	}
	// if no space after...
	if j == 0 {
		j = len(line)
	}

	LogItAll.Println("Command:", string(line[i:j]), "i:", i, "j:", j)
	return v.parent.Interpret("(" + string(line[i:j]) + ")")
}

func (v *View) ExecInsertUnderCursor() error {
	toIns, err := v.resultUnderCursor()
	if err != nil {
		return err
	}

	v.buffer.back.WriteAt(toIns,
		v.buffer.back.OffsetOf(v.buffer.C.Line, v.buffer.C.Column))
	return nil
}

func (v *View) AlternateTag() {
	if v.target == v.buffer {
		v.target = v.tag
	} else {
		v.target = v.buffer
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package repo

import (
	"io/ioutil"
	"path"
	"strings"

	"github.com/gogits/git-module"
	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/auth"
	"github.com/gogits/gogs/modules/base"
	"github.com/gogits/gogs/modules/context"
	"github.com/gogits/gogs/modules/log"
	"github.com/gogits/gogs/modules/setting"
	"github.com/gogits/gogs/modules/template"
)

const (
	EDIT_FILE         base.TplName = "repo/editor/edit"
	EDIT_DIFF_PREVIEW base.TplName = "repo/editor/diff_preview"
	DELETE_FILE       base.TplName = "repo/editor/delete"
)

func editFile(ctx *context.Context, isNewFile bool) {
	ctx.Data["PageIsEdit"] = true
	ctx.Data["IsNewFile"] = isNewFile
	ctx.Data["RequireHighlightJS"] = true
	ctx.Data["RequireSimpleMDE"] = true

	branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName

	var treeNames []string
	if len(ctx.Repo.TreePath) > 0 {
		treeNames = strings.Split(ctx.Repo.TreePath, "/")
	}

	if !isNewFile {
		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
		if err != nil {
			if git.IsErrNotExist(err) {
				ctx.Handle(404, "GetTreeEntryByPath", err)
			} else {
				ctx.Handle(500, "GetTreeEntryByPath", err)
			}
			return
		}

		// No way to edit a directory online.
		if entry.IsDir() {
			ctx.Handle(404, "", nil)
			return
		}

		blob := entry.Blob()
		dataRc, err := blob.Data()
		if err != nil {
			ctx.Handle(404, "blob.Data", err)
			return
		}

		ctx.Data["FileSize"] = blob.Size()
		ctx.Data["FileName"] = blob.Name()

		buf := make([]byte, 1024)
		n, _ := dataRc.Read(buf)
		if n > 0 {
			buf = buf[:n]
		}

		// Only text file are editable online.
		_, isTextFile := base.IsTextFile(buf)
		if !isTextFile {
			ctx.Handle(404, "", nil)
			return
		}

		d, _ := ioutil.ReadAll(dataRc)
		buf = append(buf, d...)
		if err, content := template.ToUTF8WithErr(buf); err != nil {
			if err != nil {
				log.Error(4, "ToUTF8WithErr: %v", err)
			}
			ctx.Data["FileContent"] = string(buf)
		} else {
			ctx.Data["FileContent"] = content
		}
	} else {
		treeNames = append(treeNames, "") // Append empty string to allow user name the new file.
	}

	ctx.Data["TreePath"] = ctx.Repo.TreePath
	ctx.Data["TreeNames"] = treeNames
	ctx.Data["BranchLink"] = branchLink
	ctx.Data["commit_summary"] = ""
	ctx.Data["commit_message"] = ""
	ctx.Data["commit_choice"] = "direct"
	ctx.Data["new_branch_name"] = ""
	ctx.Data["last_commit"] = ctx.Repo.Commit.ID
	ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
	ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
	ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")

	ctx.HTML(200, EDIT_FILE)
}

func EditFile(ctx *context.Context) {
	editFile(ctx, false)
}

func NewFile(ctx *context.Context) {
	editFile(ctx, true)
}

func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bool) {
	ctx.Data["PageIsEdit"] = true
	ctx.Data["IsNewFile"] = isNewFile
	ctx.Data["RequireHighlightJS"] = true
	ctx.Data["RequireSimpleMDE"] = true

	oldBranchName := ctx.Repo.BranchName
	branchName := oldBranchName
	branchLink := ctx.Repo.RepoLink + "/src/" + branchName
	oldTreePath := ctx.Repo.TreePath
	lastCommit := form.LastCommit
	form.LastCommit = ctx.Repo.Commit.ID.String()

	if form.CommitChoice == "commit-to-new-branch" {
		branchName = form.NewBranchName
	}

	form.TreePath = strings.Trim(form.TreePath, " /")

	var treeNames []string
	if len(form.TreePath) > 0 {
		treeNames = strings.Split(form.TreePath, "/")
	}

	ctx.Data["TreePath"] = form.TreePath
	ctx.Data["TreeNames"] = treeNames
	ctx.Data["BranchLink"] = branchLink
	ctx.Data["FileContent"] = form.Content
	ctx.Data["commit_summary"] = form.CommitSummary
	ctx.Data["commit_message"] = form.CommitMessage
	ctx.Data["commit_choice"] = form.CommitChoice
	ctx.Data["new_branch_name"] = branchName
	ctx.Data["last_commit"] = form.LastCommit
	ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
	ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
	ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")

	if ctx.HasError() {
		ctx.HTML(200, EDIT_FILE)
		return
	}

	if len(form.TreePath) == 0 {
		ctx.Data["Err_TreePath"] = true
		ctx.RenderWithErr(ctx.Tr("repo.editor.filename_cannot_be_empty"), EDIT_FILE, &form)
		return
	}

	if oldBranchName != branchName {
		if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
			ctx.Data["Err_NewBranchName"] = true
			ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), EDIT_FILE, &form)
			return
		}
	}

	var newTreePath string
	for index, part := range treeNames {
		newTreePath = path.Join(newTreePath, part)
		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(newTreePath)
		if err != nil {
			if git.IsErrNotExist(err) {
				// Means there is no item with that name, so we're good
				break
			}

			ctx.Handle(500, "GetTreeEntryByPath", err)
			return
		}
		if index != len(treeNames)-1 {
			if !entry.IsDir() {
				ctx.Data["Err_TreePath"] = true
				ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), EDIT_FILE, &form)
				return
			}
		} else {
			if entry.IsDir() {
				ctx.Data["Err_TreePath"] = true
				ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", part), EDIT_FILE, &form)
				return
			}
		}
	}

	if !isNewFile {
		_, err := ctx.Repo.Commit.GetTreeEntryByPath(oldTreePath)
		if err != nil {
			if git.IsErrNotExist(err) {
				ctx.Data["Err_TreePath"] = true
				ctx.RenderWithErr(ctx.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), EDIT_FILE, &form)
			} else {
				ctx.Handle(500, "GetTreeEntryByPath", err)
			}
			return
		}
		if lastCommit != ctx.Repo.CommitID {
			files, err := ctx.Repo.Commit.GetFilesChangedSinceCommit(lastCommit)
			if err != nil {
				ctx.Handle(500, "GetFilesChangedSinceCommit", err)
				return
			}

			for _, file := range files {
				if file == form.TreePath {
					ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+lastCommit+"..."+ctx.Repo.CommitID), EDIT_FILE, &form)
					return
				}
			}
		}
	}

	if oldTreePath != form.TreePath {
		// We have a new filename (rename or completely new file) so we need to make sure it doesn't already exist, can't clobber.
		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(form.TreePath)
		if err != nil {
			if !git.IsErrNotExist(err) {
				ctx.Handle(500, "GetTreeEntryByPath", err)
				return
			}
		}
		if entry != nil {
			ctx.Data["Err_TreePath"] = true
			ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), EDIT_FILE, &form)
			return
		}
	}

	message := strings.TrimSpace(form.CommitSummary)
	if len(message) == 0 {
		if isNewFile {
			message = ctx.Tr("repo.editor.add", form.TreePath)
		} else {
			message = ctx.Tr("repo.editor.update", form.TreePath)
		}
	}

	form.CommitMessage = strings.TrimSpace(form.CommitMessage)
	if len(form.CommitMessage) > 0 {
		message += "\n\n" + form.CommitMessage
	}

	if err := ctx.Repo.Repository.UpdateRepoFile(ctx.User, models.UpdateRepoFileOptions{
		LastCommitID: lastCommit,
		OldBranch:    oldBranchName,
		NewBranch:    branchName,
		OldTreeName:  oldTreePath,
		NewTreeName:  form.TreePath,
		Message:      message,
		Content:      form.Content,
		IsNewFile:    isNewFile,
	}); err != nil {
		ctx.Data["Err_TreePath"] = true
		ctx.RenderWithErr(ctx.Tr("repo.editor.failed_to_update_file", err), EDIT_FILE, &form)
		return
	}

	ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + form.TreePath)
}

func EditFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
	editFilePost(ctx, form, false)
}

func NewFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
	editFilePost(ctx, form, true)
}

func DiffPreviewPost(ctx *context.Context, form auth.EditPreviewDiffForm) {
	treePath := ctx.Repo.TreePath
	content := form.Content

	entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treePath)
	if err != nil {
		ctx.Error(500, "GetTreeEntryByPath: "+err.Error())
		return
	} else if entry.IsDir() {
		ctx.Error(422)
		return
	}

	diff, err := ctx.Repo.Repository.GetDiffPreview(ctx.Repo.BranchName, treePath, content)
	if err != nil {
		ctx.Error(500, "GetDiffPreview: "+err.Error())
		return
	}

	if diff.NumFiles() == 0 {
		ctx.PlainText(200, []byte(ctx.Tr("repo.editor.no_changes_to_show")))
		return
	}
	ctx.Data["File"] = diff.Files[0]

	ctx.HTML(200, EDIT_DIFF_PREVIEW)
}

func DeleteFile(ctx *context.Context) {
	ctx.Data["PageIsDelete"] = true
	ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName
	ctx.Data["TreePath"] = ctx.Repo.TreePath
	ctx.Data["commit_summary"] = ""
	ctx.Data["commit_message"] = ""
	ctx.Data["commit_choice"] = "direct"
	ctx.Data["new_branch_name"] = ""
	ctx.HTML(200, DELETE_FILE)
}

func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
	ctx.Data["PageIsDelete"] = true
	ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName
	ctx.Data["TreePath"] = ctx.Repo.TreePath

	oldBranchName := ctx.Repo.BranchName
	branchName := oldBranchName
	treePath := ctx.Repo.TreePath

	if form.CommitChoice == "commit-to-new-branch" {
		branchName = form.NewBranchName
	}
	ctx.Data["commit_summary"] = form.CommitSummary
	ctx.Data["commit_message"] = form.CommitMessage
	ctx.Data["commit_choice"] = form.CommitChoice
	ctx.Data["new_branch_name"] = branchName

	if ctx.HasError() {
		ctx.HTML(200, DELETE_FILE)
		return
	}

	if oldBranchName != branchName {
		if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
			ctx.Data["Err_NewBranchName"] = true
			ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), DELETE_FILE, &form)
			return
		}
	}

	message := strings.TrimSpace(form.CommitSummary)
	if len(message) == 0 {
		message = ctx.Tr("repo.editor.delete", treePath)
	}

	form.CommitMessage = strings.TrimSpace(form.CommitMessage)
	if len(form.CommitMessage) > 0 {
		message += "\n\n" + form.CommitMessage
	}

	if err := ctx.Repo.Repository.DeleteRepoFile(ctx.User, models.DeleteRepoFileOptions{
		LastCommitID: ctx.Repo.CommitID,
		OldBranch:    oldBranchName,
		NewBranch:    branchName,
		TreePath:     treePath,
		Message:      message,
	}); err != nil {
		ctx.Handle(500, "DeleteRepoFile", err)
		return
	}

	ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", treePath))
	ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName)
}
<commit_msg>#3516 enforce line ending to be \n from web editor<commit_after>// Copyright 2016 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package repo

import (
	"io/ioutil"
	"path"
	"strings"

	"github.com/gogits/git-module"
	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/auth"
	"github.com/gogits/gogs/modules/base"
	"github.com/gogits/gogs/modules/context"
	"github.com/gogits/gogs/modules/log"
	"github.com/gogits/gogs/modules/setting"
	"github.com/gogits/gogs/modules/template"
)

const (
	EDIT_FILE         base.TplName = "repo/editor/edit"
	EDIT_DIFF_PREVIEW base.TplName = "repo/editor/diff_preview"
	DELETE_FILE       base.TplName = "repo/editor/delete"
)

func editFile(ctx *context.Context, isNewFile bool) {
	ctx.Data["PageIsEdit"] = true
	ctx.Data["IsNewFile"] = isNewFile
	ctx.Data["RequireHighlightJS"] = true
	ctx.Data["RequireSimpleMDE"] = true

	branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName

	var treeNames []string
	if len(ctx.Repo.TreePath) > 0 {
		treeNames = strings.Split(ctx.Repo.TreePath, "/")
	}

	if !isNewFile {
		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
		if err != nil {
			if git.IsErrNotExist(err) {
				ctx.Handle(404, "GetTreeEntryByPath", err)
			} else {
				ctx.Handle(500, "GetTreeEntryByPath", err)
			}
			return
		}

		// No way to edit a directory online.
		if entry.IsDir() {
			ctx.Handle(404, "", nil)
			return
		}

		blob := entry.Blob()
		dataRc, err := blob.Data()
		if err != nil {
			ctx.Handle(404, "blob.Data", err)
			return
		}

		ctx.Data["FileSize"] = blob.Size()
		ctx.Data["FileName"] = blob.Name()

		buf := make([]byte, 1024)
		n, _ := dataRc.Read(buf)
		if n > 0 {
			buf = buf[:n]
		}

		// Only text file are editable online.
		_, isTextFile := base.IsTextFile(buf)
		if !isTextFile {
			ctx.Handle(404, "", nil)
			return
		}

		d, _ := ioutil.ReadAll(dataRc)
		buf = append(buf, d...)
		if err, content := template.ToUTF8WithErr(buf); err != nil {
			if err != nil {
				log.Error(4, "ToUTF8WithErr: %v", err)
			}
			ctx.Data["FileContent"] = string(buf)
		} else {
			ctx.Data["FileContent"] = content
		}
	} else {
		treeNames = append(treeNames, "") // Append empty string to allow user name the new file.
	}

	ctx.Data["TreePath"] = ctx.Repo.TreePath
	ctx.Data["TreeNames"] = treeNames
	ctx.Data["BranchLink"] = branchLink
	ctx.Data["commit_summary"] = ""
	ctx.Data["commit_message"] = ""
	ctx.Data["commit_choice"] = "direct"
	ctx.Data["new_branch_name"] = ""
	ctx.Data["last_commit"] = ctx.Repo.Commit.ID
	ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
	ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
	ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")

	ctx.HTML(200, EDIT_FILE)
}

func EditFile(ctx *context.Context) {
	editFile(ctx, false)
}

func NewFile(ctx *context.Context) {
	editFile(ctx, true)
}

func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bool) {
	ctx.Data["PageIsEdit"] = true
	ctx.Data["IsNewFile"] = isNewFile
	ctx.Data["RequireHighlightJS"] = true
	ctx.Data["RequireSimpleMDE"] = true

	oldBranchName := ctx.Repo.BranchName
	branchName := oldBranchName
	branchLink := ctx.Repo.RepoLink + "/src/" + branchName
	oldTreePath := ctx.Repo.TreePath
	lastCommit := form.LastCommit
	form.LastCommit = ctx.Repo.Commit.ID.String()

	if form.CommitChoice == "commit-to-new-branch" {
		branchName = form.NewBranchName
	}

	form.TreePath = strings.Trim(form.TreePath, " /")

	var treeNames []string
	if len(form.TreePath) > 0 {
		treeNames = strings.Split(form.TreePath, "/")
	}

	ctx.Data["TreePath"] = form.TreePath
	ctx.Data["TreeNames"] = treeNames
	ctx.Data["BranchLink"] = branchLink
	ctx.Data["FileContent"] = form.Content
	ctx.Data["commit_summary"] = form.CommitSummary
	ctx.Data["commit_message"] = form.CommitMessage
	ctx.Data["commit_choice"] = form.CommitChoice
	ctx.Data["new_branch_name"] = branchName
	ctx.Data["last_commit"] = form.LastCommit
	ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
	ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
	ctx.Data["PreviewableFileModes"] = strings.Join(setting.Repository.Editor.PreviewableFileModes, ",")

	if ctx.HasError() {
		ctx.HTML(200, EDIT_FILE)
		return
	}

	if len(form.TreePath) == 0 {
		ctx.Data["Err_TreePath"] = true
		ctx.RenderWithErr(ctx.Tr("repo.editor.filename_cannot_be_empty"), EDIT_FILE, &form)
		return
	}

	if oldBranchName != branchName {
		if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
			ctx.Data["Err_NewBranchName"] = true
			ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), EDIT_FILE, &form)
			return
		}
	}

	var newTreePath string
	for index, part := range treeNames {
		newTreePath = path.Join(newTreePath, part)
		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(newTreePath)
		if err != nil {
			if git.IsErrNotExist(err) {
				// Means there is no item with that name, so we're good
				break
			}

			ctx.Handle(500, "GetTreeEntryByPath", err)
			return
		}
		if index != len(treeNames)-1 {
			if !entry.IsDir() {
				ctx.Data["Err_TreePath"] = true
				ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", part), EDIT_FILE, &form)
				return
			}
		} else {
			if entry.IsDir() {
				ctx.Data["Err_TreePath"] = true
				ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", part), EDIT_FILE, &form)
				return
			}
		}
	}

	if !isNewFile {
		_, err := ctx.Repo.Commit.GetTreeEntryByPath(oldTreePath)
		if err != nil {
			if git.IsErrNotExist(err) {
				ctx.Data["Err_TreePath"] = true
				ctx.RenderWithErr(ctx.Tr("repo.editor.file_editing_no_longer_exists", oldTreePath), EDIT_FILE, &form)
			} else {
				ctx.Handle(500, "GetTreeEntryByPath", err)
			}
			return
		}
		if lastCommit != ctx.Repo.CommitID {
			files, err := ctx.Repo.Commit.GetFilesChangedSinceCommit(lastCommit)
			if err != nil {
				ctx.Handle(500, "GetFilesChangedSinceCommit", err)
				return
			}

			for _, file := range files {
				if file == form.TreePath {
					ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+lastCommit+"..."+ctx.Repo.CommitID), EDIT_FILE, &form)
					return
				}
			}
		}
	}

	if oldTreePath != form.TreePath {
		// We have a new filename (rename or completely new file) so we need to make sure it doesn't already exist, can't clobber.
		entry, err := ctx.Repo.Commit.GetTreeEntryByPath(form.TreePath)
		if err != nil {
			if !git.IsErrNotExist(err) {
				ctx.Handle(500, "GetTreeEntryByPath", err)
				return
			}
		}
		if entry != nil {
			ctx.Data["Err_TreePath"] = true
			ctx.RenderWithErr(ctx.Tr("repo.editor.file_already_exists", form.TreePath), EDIT_FILE, &form)
			return
		}
	}

	message := strings.TrimSpace(form.CommitSummary)
	if len(message) == 0 {
		if isNewFile {
			message = ctx.Tr("repo.editor.add", form.TreePath)
		} else {
			message = ctx.Tr("repo.editor.update", form.TreePath)
		}
	}

	form.CommitMessage = strings.TrimSpace(form.CommitMessage)
	if len(form.CommitMessage) > 0 {
		message += "\n\n" + form.CommitMessage
	}

	if err := ctx.Repo.Repository.UpdateRepoFile(ctx.User, models.UpdateRepoFileOptions{
		LastCommitID: lastCommit,
		OldBranch:    oldBranchName,
		NewBranch:    branchName,
		OldTreeName:  oldTreePath,
		NewTreeName:  form.TreePath,
		Message:      message,
		Content:      strings.Replace(form.Content, "\r", "", -1),
		IsNewFile:    isNewFile,
	}); err != nil {
		ctx.Data["Err_TreePath"] = true
		ctx.RenderWithErr(ctx.Tr("repo.editor.failed_to_update_file", err), EDIT_FILE, &form)
		return
	}

	ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName + "/" + form.TreePath)
}

func EditFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
	editFilePost(ctx, form, false)
}

func NewFilePost(ctx *context.Context, form auth.EditRepoFileForm) {
	editFilePost(ctx, form, true)
}

func DiffPreviewPost(ctx *context.Context, form auth.EditPreviewDiffForm) {
	treePath := ctx.Repo.TreePath

	entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treePath)
	if err != nil {
		ctx.Error(500, "GetTreeEntryByPath: "+err.Error())
		return
	} else if entry.IsDir() {
		ctx.Error(422)
		return
	}

	diff, err := ctx.Repo.Repository.GetDiffPreview(ctx.Repo.BranchName, treePath, form.Content)
	if err != nil {
		ctx.Error(500, "GetDiffPreview: "+err.Error())
		return
	}

	if diff.NumFiles() == 0 {
		ctx.PlainText(200, []byte(ctx.Tr("repo.editor.no_changes_to_show")))
		return
	}
	ctx.Data["File"] = diff.Files[0]

	ctx.HTML(200, EDIT_DIFF_PREVIEW)
}

func DeleteFile(ctx *context.Context) {
	ctx.Data["PageIsDelete"] = true
	ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName
	ctx.Data["TreePath"] = ctx.Repo.TreePath
	ctx.Data["commit_summary"] = ""
	ctx.Data["commit_message"] = ""
	ctx.Data["commit_choice"] = "direct"
	ctx.Data["new_branch_name"] = ""
	ctx.HTML(200, DELETE_FILE)
}

func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
	ctx.Data["PageIsDelete"] = true
	ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchName
	ctx.Data["TreePath"] = ctx.Repo.TreePath

	oldBranchName := ctx.Repo.BranchName
	branchName := oldBranchName
	treePath := ctx.Repo.TreePath

	if form.CommitChoice == "commit-to-new-branch" {
		branchName = form.NewBranchName
	}
	ctx.Data["commit_summary"] = form.CommitSummary
	ctx.Data["commit_message"] = form.CommitMessage
	ctx.Data["commit_choice"] = form.CommitChoice
	ctx.Data["new_branch_name"] = branchName

	if ctx.HasError() {
		ctx.HTML(200, DELETE_FILE)
		return
	}

	if oldBranchName != branchName {
		if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
			ctx.Data["Err_NewBranchName"] = true
			ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchName), DELETE_FILE, &form)
			return
		}
	}

	message := strings.TrimSpace(form.CommitSummary)
	if len(message) == 0 {
		message = ctx.Tr("repo.editor.delete", treePath)
	}

	form.CommitMessage = strings.TrimSpace(form.CommitMessage)
	if len(form.CommitMessage) > 0 {
		message += "\n\n" + form.CommitMessage
	}

	if err := ctx.Repo.Repository.DeleteRepoFile(ctx.User, models.DeleteRepoFileOptions{
		LastCommitID: ctx.Repo.CommitID,
		OldBranch:    oldBranchName,
		NewBranch:    branchName,
		TreePath:     treePath,
		Message:      message,
	}); err != nil {
		ctx.Handle(500, "DeleteRepoFile", err)
		return
	}

	ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", treePath))
	ctx.Redirect(ctx.Repo.RepoLink + "/src/" + branchName)
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package user

import (
	"encoding/json"
	"errors"
	"fmt"
	// "strings"
	"time"

	"github.com/macaron-contrib/oauth2"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/log"
	"github.com/gogits/gogs/modules/middleware"
	"github.com/gogits/gogs/modules/setting"
	"github.com/gogits/gogs/modules/social"
)

func SocialSignIn(ctx *middleware.Context) {
	if setting.OauthService == nil {
		ctx.Handle(404, "OAuth2 service not enabled", nil)
		return
	}

	next := setting.AppSubUrl + "/user/login"
	info := ctx.Session.Get(oauth2.KEY_TOKEN)
	if info == nil {
		ctx.Redirect(next)
		return
	}

	name := ctx.Params(":name")
	connect, ok := social.SocialMap[name]
	if !ok {
		ctx.Handle(404, "social login not enabled", errors.New(name))
		return
	}

	tk := new(oauth2.Token)
	if err := json.Unmarshal(info.([]byte), tk); err != nil {
		ctx.Handle(500, "Unmarshal token", err)
		return
	}

	ui, err := connect.UserInfo(tk, ctx.Req.URL)
	if err != nil {
		ctx.Handle(500, fmt.Sprintf("UserInfo(%s)", name), err)
		return
	}
	log.Info("social.SocialSignIn(social login): %s", ui)

	oa, err := models.GetOauth2(ui.Identity)
	switch err {
	case nil:
		ctx.Session.Set("uid", oa.User.Id)
		ctx.Session.Set("uname", oa.User.Name)
	case models.ErrOauth2RecordNotExist:
		raw, _ := json.Marshal(tk)
		oa = &models.Oauth2{
			Uid:      -1,
			Type:     connect.Type(),
			Identity: ui.Identity,
			Token:    string(raw),
		}
		log.Trace("social.SocialSignIn(oa): %v", oa)
		if err = models.AddOauth2(oa); err != nil {
			log.Error(4, "social.SocialSignIn(add oauth2): %v", err) // 501
			return
		}
	case models.ErrOauth2NotAssociated:
		next = setting.AppSubUrl + "/user/sign_up"
	default:
		ctx.Handle(500, "social.SocialSignIn(GetOauth2)", err)
		return
	}

	oa.Updated = time.Now()
	if err = models.UpdateOauth2(oa); err != nil {
		log.Error(4, "UpdateOauth2: %v", err)
	}

	ctx.Session.Set("socialId", oa.Id)
	ctx.Session.Set("socialName", ui.Name)
	ctx.Session.Set("socialEmail", ui.Email)
	log.Trace("social.SocialSignIn(social ID): %v", oa.Id)
	ctx.Redirect(next)
}
<commit_msg>safe check<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package user

import (
	"encoding/json"
	"errors"
	"fmt"
	// "strings"
	"time"

	"github.com/macaron-contrib/oauth2"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/modules/log"
	"github.com/gogits/gogs/modules/middleware"
	"github.com/gogits/gogs/modules/setting"
	"github.com/gogits/gogs/modules/social"
)

func SocialSignIn(ctx *middleware.Context) {
	if setting.OauthService == nil {
		ctx.Handle(404, "OAuth2 service not enabled", nil)
		return
	}

	next := setting.AppSubUrl + "/user/login"
	info := ctx.Session.Get(oauth2.KEY_TOKEN)
	if info == nil {
		ctx.Redirect(next)
		return
	}

	name := ctx.Params(":name")
	connect, ok := social.SocialMap[name]
	if !ok {
		ctx.Handle(404, "social login not enabled", errors.New(name))
		return
	}

	tk := new(oauth2.Token)
	if err := json.Unmarshal(info.([]byte), tk); err != nil {
		ctx.Handle(500, "Unmarshal token", err)
		return
	}

	ui, err := connect.UserInfo(tk, ctx.Req.URL)
	if err != nil {
		ctx.Handle(500, fmt.Sprintf("UserInfo(%s)", name), err)
		return
	}
	if len(ui.Identity) == 0 {
		ctx.Handle(404, "no identity is presented", errors.New(name))
		return
	}
	log.Info("social.SocialSignIn(social login): %s", ui)

	oa, err := models.GetOauth2(ui.Identity)
	switch err {
	case nil:
		ctx.Session.Set("uid", oa.User.Id)
		ctx.Session.Set("uname", oa.User.Name)
	case models.ErrOauth2RecordNotExist:
		raw, _ := json.Marshal(tk)
		oa = &models.Oauth2{
			Uid:      -1,
			Type:     connect.Type(),
			Identity: ui.Identity,
			Token:    string(raw),
		}
		log.Trace("social.SocialSignIn(oa): %v", oa)
		if err = models.AddOauth2(oa); err != nil {
			log.Error(4, "social.SocialSignIn(add oauth2): %v", err) // 501
			return
		}
	case models.ErrOauth2NotAssociated:
		next = setting.AppSubUrl + "/user/sign_up"
	default:
		ctx.Handle(500, "social.SocialSignIn(GetOauth2)", err)
		return
	}

	oa.Updated = time.Now()
	if err = models.UpdateOauth2(oa); err != nil {
		log.Error(4, "UpdateOauth2: %v", err)
	}

	ctx.Session.Set("socialId", oa.Id)
	ctx.Session.Set("socialName", ui.Name)
	ctx.Session.Set("socialEmail", ui.Email)
	log.Trace("social.SocialSignIn(social ID): %v", oa.Id)
	ctx.Redirect(next)
}
<|endoftext|>


<commit_before>// srclib-docco is a docco-like static documentation generator.
// TODO: write this in a literal style.
package srclib_docco

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"

	"github.com/jessevdk/go-flags"
	"github.com/sourcegraph/annotate"
	"github.com/sourcegraph/syntaxhighlight"
)

var CLI = flags.NewNamedParser("src-docco", flags.Default)

var GlobalOpt struct {
	Verbose bool `short:"v" description:"show verbose output"`
}

var vLogger = log.New(os.Stderr, "", 0)

func vLogf(format string, v ...interface{}) {
	if !GlobalOpt.Verbose {
		return
	}
	vLogger.Printf(format, v...)
}

func vLog(v ...interface{}) {
	if !GlobalOpt.Verbose {
		return
	}
	vLogger.Println(v...)
}

func init() {
	CLI.LongDescription = "TODO"
	CLI.AddGroup("Global options", "", &GlobalOpt)

	_, err := CLI.AddCommand("gen",
		"generate documentation",
		"Generate docco-like documentation for a thing",
		&genCmd,
	)
	if err != nil {
		log.Fatal(err)
	}
}

// TODO: add limitations help output.

type GenCmd struct {
	Dir string `long:"dir" description:"The root directory for the project"`
	// TODO: must be relative to Dir.
	SiteDirName string `long:"site-dir" description:"The directory name for the output files" default:"site"`
}

var genCmd GenCmd

// Source units have lots of information associated with them, but we
// only care about the files.
type unit struct {
	Files []string
}

type units []unit

func (us units) collateFiles() []string {
	var fs []string
	for _, u := range us {
		for _, f := range u.Files {
			fs = append(fs, f)
		}
	}
	return fs
}

type failedCmd struct {
	cmd interface{}
	err interface{}
}

// TODO: Is this correct?
func (f failedCmd) Error() string {
	return fmt.Sprintf("command %v failed: %s", f.cmd, f.err)
}

func ensureSrclibExists() error {
	cmd := exec.Command("src", "version")
	stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}
	cmd.Stdout, cmd.Stderr = stdout, stderr
	if err := cmd.Run(); err != nil {
		return fmt.Errorf(
			"error with srclib: %v, %s, %s",
			err,
			stdout.String(),
			stderr.String(),
		)
	}
	return nil
}

func command(argv []string) (cmd *exec.Cmd, stdout *bytes.Buffer, stderr *bytes.Buffer) {
	if len(argv) == 0 {
		panic("command: argv must have at least one item")
	}
	cmd = exec.Command(argv[0], argv[1:]...)
	stdout, stderr = &bytes.Buffer{}, &bytes.Buffer{}
	cmd.Stdout, cmd.Stderr = stdout, stderr
	return cmd, stdout, stderr
}

func (c *GenCmd) Execute(args []string) error {
	if err := ensureSrclibExists(); err != nil {
		log.Fatal(err)
	}

	// First, we need to get a list of all of the files that we
	// want to generate.
	//
	// We could import sourcegraph.com/sourcegraph/srclib, but I
	// want to demonstrate how to use its command line interface.
	var dir string
	if c.Dir == "" {
		d, err := os.Getwd()
		if err != nil {
			log.Fatal(err)
		}
		dir = d
	} else {
		d, err := filepath.Abs(c.Dir)
		if err != nil {
			log.Fatal(err)
		}
		dir = d
	}
	argv := []string{"src", "api", "units", dir}
	cmd, stdout, stderr := command(argv)
	vLogf("Running %v", argv)
	// TODO: remove failedCmd
	if err := cmd.Run(); err != nil {
		log.Fatal(failedCmd{argv, []interface{}{err, stdout.String(), stderr.String()}})
	}
	if stdout.Len() == 0 {
		log.Fatal(failedCmd{argv, "no output"})
	}
	var us units
	if err := json.Unmarshal(stdout.Bytes(), &us); err != nil {
		log.Fatal(err)
	}
	return genSite(dir, c.SiteDirName, us.collateFiles())
}

func genSite(root, siteName string, files []string) error {
	vLog("Generating Site")
	// Here's the plan:
	// * Make sitePath directory
	// * Annotate one file at a time
	// * Thow it into a file
	// * Ignore srclib shit for now
	sitePath := filepath.Join(root, siteName)
	if err := os.MkdirAll(sitePath, 0755); err != nil {
		log.Fatal(err)
	}
	for _, f := range files {
		vLog("Processing", f)
		src, err := ioutil.ReadFile(filepath.Join(root, f))
		if err != nil {
			return err
		}
		htmlFile := "/" + f + ".html"
		as, err := ann(src, root, f, htmlFile)
		if err != nil {
			return err
		}
		vLog("Never get here")
		if err := os.MkdirAll(filepath.Dir(filepath.Join(sitePath, htmlFile)), 0755); err != nil {
			log.Fatal(err)
		}
		w, err := os.Create(filepath.Join(sitePath, htmlFile))
		if err != nil {
			return err
		}
		if err := writeAnns(w, src, as); err != nil {
			return err
		}
	}
	return nil
}

type annotation struct {
	annotate.Annotation
	Comment bool
}

type htmlAnnotator syntaxhighlight.HTMLConfig

func (c htmlAnnotator) class(kind syntaxhighlight.Kind) string {
	switch kind {
	case syntaxhighlight.String:
		return c.String
	case syntaxhighlight.Keyword:
		return c.Keyword
	case syntaxhighlight.Comment:
		return c.Comment
	case syntaxhighlight.Type:
		return c.Type
	case syntaxhighlight.Literal:
		return c.Literal
	case syntaxhighlight.Punctuation:
		return c.Punctuation
	case syntaxhighlight.Plaintext:
		return c.Plaintext
	case syntaxhighlight.Tag:
		return c.Tag
	case syntaxhighlight.HTMLTag:
		return c.HTMLTag
	case syntaxhighlight.HTMLAttrName:
		return c.HTMLAttrName
	case syntaxhighlight.HTMLAttrValue:
		return c.HTMLAttrValue
	case syntaxhighlight.Decimal:
		return c.Decimal
	}
	return ""
}

func (a htmlAnnotator) Annotate(start int, kind syntaxhighlight.Kind, tokText string) (*annotate.Annotation, error) {
	class := a.class(kind)
	if class == "" {
		return nil, nil
	}
	return &annotate.Annotation{
		Start: start,
		End:   start + len(tokText),
		Left:  []byte(class),
		Right: nil,
	}, nil
}

func ann(src []byte, root, file, htmlFile string) ([]annotation, error) {
	vLog("Annotating", file)
	annotations, err := syntaxhighlight.Annotate(src, htmlAnnotator(syntaxhighlight.DefaultHTMLConfig))
	if err != nil {
		return nil, err
	}
	sort.Sort(annotations)
	as := make([]annotation, 0, len(annotations))
	argv := []string{"src", "api", "list", "--file", filepath.Join(root, file)}
	cmd, stdout, stderr := command(argv)
	vLog("Running", argv)
	if err := cmd.Run(); err != nil {
		return nil, failedCmd{argv, []interface{}{err, stdout.String(), stderr.String()}}
	}
	type ref struct {
		DefUnit string
		DefPath string
		Start   uint32
	}
	refs := []ref{}
	if err := json.Unmarshal(stdout.Bytes(), &refs); err != nil {
		log.Fatal(err)
	}
	var refAtIndex int
	refAt := func(start uint32) (r ref, found bool) {
		for refAtIndex < len(refs) {
			if refs[refAtIndex].Start == start {
				refAtIndex++
				return r, true
			} else if refs[refAtIndex].Start < start {
				refAtIndex++
			} else { // refs[refAtIndex].Start > start
				return ref{}, false
			}
		}
		return ref{}, false
	}
	for _, a := range annotations {
		if string(a.Left) == "com" {
			as = append(as, annotation{*a, true})
			continue
		}
		r, found := refAt(uint32(a.Start))
		if !found {
			a.Left = []byte(fmt.Sprintf(`<span class="%s">`, string(a.Left)))
			a.Right = []byte(`</span>`)
			as = append(as, annotation{*a, false})
			continue
		}
		a.Left = []byte(fmt.Sprintf(
			`<span class="%s" id="%s"><a href="%s">`,
			string(a.Left),
			filepath.Join(r.DefUnit, r.DefPath),
			htmlFile,
		))
		a.Right = []byte(`</span></a>`)
		as = append(as, annotation{*a, false})
	}
	return as, nil
}

func writeAnns(w io.Writer, src []byte, as []annotation) error {
	vLog("Writing annotations")
	line := 0
	if _, err := w.Write([]byte(fmt.Sprintf(`<pre><div line=%d>`, line))); err != nil {
		return err
	}
	addDivs := func(src []byte) []byte {
		buf := &bytes.Buffer{}
		buf.Grow(len(src))
		for _, b := range src {
			if b == '\n' {
				line++
				buf.Write([]byte(fmt.Sprintf("
\n
", line)))
				continue
			}
			buf.WriteByte(b)
		}
		return buf.Bytes()
	}
	defer func() {
		w.Write([]byte("
\n
"))
	}()
	for i := 0; i < len(src); {
		log.Println(i)
		if len(as) == 0 {
			_, err := w.Write(addDivs(src[i:]))
			return err
		}
		a := as[0]
		if i > a.Start {
			log.Fatal("writeAnns: illegal state: i > a.Start")
		}
		if i < a.Start {
			if _, err := w.Write(addDivs(src[i : i+1])); err != nil {
				return err
			}
			i++
			continue
		}
		// i == a.Start
		for _, b := range src[a.Start:a.End] {
			if b == '\n' {
				log.Fatal(`writeAnns: illegal state: \n in annotation`)
			}
		}
		if _, err := w.Write([]byte(strings.Join([]string{
			string(a.Left),
			string(src[a.Start:a.End]),
			string(a.Right),
		}, ""))); err != nil {
			return err
		}
		i = a.End
		as = as[1:]
	}
	return nil
}

func Main() error {
	//log.SetPrefix("")
	log.SetFlags(log.Lshortfile)
	_, err := CLI.Parse()
	return err
}
<commit_msg>clean up comments<commit_after>// srclib-docco is a docco-like static documentation generator.
// TODO: write this in a literal style.
package srclib_docco

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"strings"

	"github.com/jessevdk/go-flags"
	"github.com/sourcegraph/annotate"
	"github.com/sourcegraph/syntaxhighlight"
)

var CLI = flags.NewNamedParser("src-docco", flags.Default)

var GlobalOpt struct {
	Verbose bool `short:"v" description:"show verbose output"`
}

var vLogger = log.New(os.Stderr, "", 0)

func vLogf(format string, v ...interface{}) {
	if !GlobalOpt.Verbose {
		return
	}
	vLogger.Printf(format, v...)
}

func vLog(v ...interface{}) {
	if !GlobalOpt.Verbose {
		return
	}
	vLogger.Println(v...)
}

func init() {
	CLI.LongDescription = "TODO"
	CLI.AddGroup("Global options", "", &GlobalOpt)

	_, err := CLI.AddCommand("gen",
		"generate documentation",
		"Generate docco-like documentation for a thing",
		&genCmd,
	)
	if err != nil {
		log.Fatal(err)
	}
}

// TODO: add limitations help output.

type GenCmd struct {
	Dir string `long:"dir" description:"The root directory for the project"`
	// TODO: must be relative to Dir.
	SiteDirName string `long:"site-dir" description:"The directory name for the output files" default:"site"`
}

var genCmd GenCmd

// Source units have lots of information associated with them, but we
// only care about the files.
type unit struct {
	Files []string
}

type units []unit

func (us units) collateFiles() []string {
	var fs []string
	for _, u := range us {
		for _, f := range u.Files {
			fs = append(fs, f)
		}
	}
	return fs
}

type failedCmd struct {
	cmd interface{}
	err interface{}
}

// TODO: Is this correct?
func (f failedCmd) Error() string {
	return fmt.Sprintf("command %v failed: %s", f.cmd, f.err)
}

func ensureSrclibExists() error {
	cmd := exec.Command("src", "version")
	stdout, stderr := &bytes.Buffer{}, &bytes.Buffer{}
	cmd.Stdout, cmd.Stderr = stdout, stderr
	if err := cmd.Run(); err != nil {
		return fmt.Errorf(
			"error with srclib: %v, %s, %s",
			err,
			stdout.String(),
			stderr.String(),
		)
	}
	return nil
}

func command(argv []string) (cmd *exec.Cmd, stdout *bytes.Buffer, stderr *bytes.Buffer) {
	if len(argv) == 0 {
		panic("command: argv must have at least one item")
	}
	cmd = exec.Command(argv[0], argv[1:]...)
	stdout, stderr = &bytes.Buffer{}, &bytes.Buffer{}
	cmd.Stdout, cmd.Stderr = stdout, stderr
	return cmd, stdout, stderr
}

func (c *GenCmd) Execute(args []string) error {
	if err := ensureSrclibExists(); err != nil {
		log.Fatal(err)
	}

	// First, we need to get a list of all of the files that we
	// want to generate.
	//
	// We could import sourcegraph.com/sourcegraph/srclib, but I
	// want to demonstrate how to use its command line interface.
	var dir string
	if c.Dir == "" {
		d, err := os.Getwd()
		if err != nil {
			log.Fatal(err)
		}
		dir = d
	} else {
		d, err := filepath.Abs(c.Dir)
		if err != nil {
			log.Fatal(err)
		}
		dir = d
	}
	argv := []string{"src", "api", "units", dir}
	cmd, stdout, stderr := command(argv)
	vLogf("Running %v", argv)
	// TODO: remove failedCmd
	if err := cmd.Run(); err != nil {
		log.Fatal(failedCmd{argv, []interface{}{err, stdout.String(), stderr.String()}})
	}
	if stdout.Len() == 0 {
		log.Fatal(failedCmd{argv, "no output"})
	}
	var us units
	if err := json.Unmarshal(stdout.Bytes(), &us); err != nil {
		log.Fatal(err)
	}
	return genSite(dir, c.SiteDirName, us.collateFiles())
}

func genSite(root, siteName string, files []string) error {
	vLog("Generating Site")
	sitePath := filepath.Join(root, siteName)
	if err := os.MkdirAll(sitePath, 0755); err != nil {
		log.Fatal(err)
	}
	for _, f := range files {
		vLog("Processing", f)
		src, err := ioutil.ReadFile(filepath.Join(root, f))
		if err != nil {
			return err
		}
		htmlFile := "/" + f + ".html"
		as, err := ann(src, root, f, htmlFile)
		if err != nil {
			return err
		}
		vLog("Never get here")
		if err := os.MkdirAll(filepath.Dir(filepath.Join(sitePath, htmlFile)), 0755); err != nil {
			log.Fatal(err)
		}
		w, err := os.Create(filepath.Join(sitePath, htmlFile))
		if err != nil {
			return err
		}
		if err := writeAnns(w, src, as); err != nil {
			return err
		}
	}
	return nil
}

type annotation struct {
	annotate.Annotation
	Comment bool
}

type htmlAnnotator syntaxhighlight.HTMLConfig

func (c htmlAnnotator) class(kind syntaxhighlight.Kind) string {
	switch kind {
	case syntaxhighlight.String:
		return c.String
	case syntaxhighlight.Keyword:
		return c.Keyword
	case syntaxhighlight.Comment:
		return c.Comment
	case syntaxhighlight.Type:
		return c.Type
	case syntaxhighlight.Literal:
		return c.Literal
	case syntaxhighlight.Punctuation:
		return c.Punctuation
	case syntaxhighlight.Plaintext:
		return c.Plaintext
	case syntaxhighlight.Tag:
		return c.Tag
	case syntaxhighlight.HTMLTag:
		return c.HTMLTag
	case syntaxhighlight.HTMLAttrName:
		return c.HTMLAttrName
	case syntaxhighlight.HTMLAttrValue:
		return c.HTMLAttrValue
	case syntaxhighlight.Decimal:
		return c.Decimal
	}
	return ""
}

func (a htmlAnnotator) Annotate(start int, kind syntaxhighlight.Kind, tokText string) (*annotate.Annotation, error) {
	class := a.class(kind)
	if class == "" {
		return nil, nil
	}
	return &annotate.Annotation{
		Start: start,
		End:   start + len(tokText),
		Left:  []byte(class),
		Right: nil,
	}, nil
}

func ann(src []byte, root, file, htmlFile string) ([]annotation, error) {
	vLog("Annotating", file)
	annotations, err := syntaxhighlight.Annotate(src, htmlAnnotator(syntaxhighlight.DefaultHTMLConfig))
	if err != nil {
		return nil, err
	}
	sort.Sort(annotations)
	as := make([]annotation, 0, len(annotations))
	argv := []string{"src", "api", "list", "--file", filepath.Join(root, file)}
	cmd, stdout, stderr := command(argv)
	vLog("Running", argv)
	if err := cmd.Run(); err != nil {
		return nil, failedCmd{argv, []interface{}{err, stdout.String(), stderr.String()}}
	}
	type ref struct {
		DefUnit string
		DefPath string
		Start   uint32
	}
	refs := []ref{}
	if err := json.Unmarshal(stdout.Bytes(), &refs); err != nil {
		log.Fatal(err)
	}
	var refAtIndex int
	refAt := func(start uint32) (r ref, found bool) {
		for refAtIndex < len(refs) {
			if refs[refAtIndex].Start == start {
				refAtIndex++
				return r, true
			} else if refs[refAtIndex].Start < start {
				refAtIndex++
			} else { // refs[refAtIndex].Start > start
				return ref{}, false
			}
		}
		return ref{}, false
	}
	for _, a := range annotations {
		if string(a.Left) == "com" {
			as = append(as, annotation{*a, true})
			continue
		}
		r, found := refAt(uint32(a.Start))
		if !found {
			a.Left = []byte(fmt.Sprintf(`<span class="%s">`, string(a.Left)))
			a.Right = []byte(`</span>`)
			as = append(as, annotation{*a, false})
			continue
		}
		a.Left = []byte(fmt.Sprintf(
			`<span class="%s" id="%s"><a href="%s">`,
			string(a.Left),
			filepath.Join(r.DefUnit, r.DefPath),
			htmlFile,
		))
		a.Right = []byte(`</span></a>`)
		as = append(as, annotation{*a, false})
	}
	return as, nil
}

func writeAnns(w io.Writer, src []byte, as []annotation) error {
	vLog("Writing annotations")
	line := 0
	if _, err := w.Write([]byte(fmt.Sprintf(`<pre><div line=%d>`, line))); err != nil {
		return err
	}
	addDivs := func(src []byte) []byte {
		buf := &bytes.Buffer{}
		buf.Grow(len(src))
		for _, b := range src {
			if b == '\n' {
				line++
				buf.Write([]byte(fmt.Sprintf("
\n
", line)))
				continue
			}
			buf.WriteByte(b)
		}
		return buf.Bytes()
	}
	defer func() {
		w.Write([]byte("
\n
"))
	}()
	for i := 0; i < len(src); {
		log.Println(i)
		if len(as) == 0 {
			_, err := w.Write(addDivs(src[i:]))
			return err
		}
		a := as[0]
		if i > a.Start {
			log.Fatal("writeAnns: illegal state: i > a.Start")
		}
		if i < a.Start {
			if _, err := w.Write(addDivs(src[i : i+1])); err != nil {
				return err
			}
			i++
			continue
		}
		// i == a.Start
		for _, b := range src[a.Start:a.End] {
			if b == '\n' {
				log.Fatal(`writeAnns: illegal state: \n in annotation`)
			}
		}
		if _, err := w.Write([]byte(strings.Join([]string{
			string(a.Left),
			string(src[a.Start:a.End]),
			string(a.Right),
		}, ""))); err != nil {
			return err
		}
		i = a.End
		as = as[1:]
	}
	return nil
}

func Main() error {
	log.SetFlags(log.Lshortfile)
	_, err := CLI.Parse()
	return err
}
<|endoftext|>


<commit_before>package main

import (
    "bufio"
    "io"
    "fmt"
    "os"
    "strings"
    "regexp"
    "net/http"
    "archive/zip"
    "path/filepath"
)

func Unzip(src, dest string, base *strings.Replacer) error {
    r, err := zip.OpenReader(src)
    if err != nil {
        return err
    }
    defer func() {
        if err := r.Close(); err != nil {
            panic(err)
        }
    }()

    os.MkdirAll(dest, 0755)

    // Closure to address file descriptors issue with all the deferred .Close() methods
    extract := func(f *zip.File) error {
        rc, err := f.Open()
        if err != nil {
            return err
        }
        defer func() {
            if err := rc.Close(); err != nil {
                panic(err)
            }
        }()

        path := filepath.Join(dest, base.Replace(f.Name))

        if f.FileInfo().IsDir() {
            os.MkdirAll(path, f.Mode())
        } else {
            f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
            if err != nil {
                return err
            }
            defer func() {
                if err := f.Close(); err != nil {
                    panic(err)
                }
            }()

            _, err = io.Copy(f, rc)
            if err != nil {
                return err
            }
        }
        return nil
    }

    for _, f := range r.File {
        err := extract(f)
        if err != nil {
            return err
        }
    }

    return nil
}

func Download(uri, file string) (int64, error) {
    out, err := os.Create(file)
    if err != nil {
        return -1, err
    }
    defer out.Close()

    resp, err := http.Get(uri)
    if err != nil {
        return -1, err
    }
    defer resp.Body.Close()

    size, err := io.Copy(out, resp.Body)
    if err != nil {
        return -1, err
    }

    return size, nil
}

func Transform(input string, base string, yield func(string)) (error) {
    transformations := map[string]func([]string) error{
        "FROM (.+)"    : func(matches []string) error {
            if "" == base {
                base = matches[1]
                yield("FROM " + base)
                return nil
            } else if (matches[1] == base) {
                return nil
            }
            return fmt.Errorf("Expecting %q, have %q in %q", base, matches[1], input)
        },
        "INCLUDE (.+)" : func(matches []string) error {
            yield("# Included from " + matches[1])

            include := regexp.MustCompile("github.com/([^/]+)/([^/]+)").FindStringSubmatch(matches[1])
            if len(include) > 0 {
                vendor := include[1]
                name := include[2]

                target := filepath.Join("vendor", vendor, name)
                zip := filepath.Join(target, "master.zip")

                if err := os.MkdirAll(target, 0700); err != nil {
                    return err
                }

                _, err := Download("https://github.com/" + vendor + "/" + name + "/archive/master.zip", zip)
                if err != nil {
                    return err
                }

                if err := Unzip(zip, target, strings.NewReplacer(name + "-master/", "")); err != nil {
                    return err
                }

                Transform(filepath.Join(target, "Dockerfile.in"), base, yield)
            }
            return nil
        },
    }

    file, err := os.Open(input)
    if err != nil {
        return err
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text()
        transformed := false

        for pattern, action := range transformations {
            matches := regexp.MustCompile(pattern).FindStringSubmatch(line)
            if len(matches) > 0 {
                if err := action(matches); err != nil {
                    return err
                }
                transformed = true
                break
            }
        }

        if !transformed {
            yield(line)
        }
    }

    if err := scanner.Err(); err != nil {
        return err
    }

    return nil
}

func main() {
    err := Transform("Dockerfile.in", "", func(line string) { fmt.Println(line) })

    if (err != nil) {
        fmt.Println(err)
        os.Exit(1)
    }
}<commit_msg>Format<commit_after>package main

import (
    "archive/zip"
    "bufio"
    "fmt"
    "io"
    "net/http"
    "os"
    "path/filepath"
    "regexp"
    "strings"
)

func Unzip(src, dest string, base *strings.Replacer) error {
    r, err := zip.OpenReader(src)
    if err != nil {
        return err
    }
    defer func() {
        if err := r.Close(); err != nil {
            panic(err)
        }
    }()

    os.MkdirAll(dest, 0755)

    // Closure to address file descriptors issue with all the deferred .Close() methods
    extract := func(f *zip.File) error {
        rc, err := f.Open()
        if err != nil {
            return err
        }
        defer func() {
            if err := rc.Close(); err != nil {
                panic(err)
            }
        }()

        path := filepath.Join(dest, base.Replace(f.Name))

        if f.FileInfo().IsDir() {
            os.MkdirAll(path, f.Mode())
        } else {
            f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
            if err != nil {
                return err
            }
            defer func() {
                if err := f.Close(); err != nil {
                    panic(err)
                }
            }()

            _, err = io.Copy(f, rc)
            if err != nil {
                return err
            }
        }
        return nil
    }

    for _, f := range r.File {
        err := extract(f)
        if err != nil {
            return err
        }
    }

    return nil
}

func Download(uri, file string) (int64, error) {
    out, err := os.Create(file)
    if err != nil {
        return -1, err
    }
    defer out.Close()

    resp, err := http.Get(uri)
    if err != nil {
        return -1, err
    }
    defer resp.Body.Close()

    size, err := io.Copy(out, resp.Body)
    if err != nil {
        return -1, err
    }

    return size, nil
}

func Transform(input string, base string, yield func(string)) error {
    transformations := map[string]func([]string) error{
        "FROM (.+)": func(matches []string) error {
            if "" == base {
                base = matches[1]
                yield("FROM " + base)
                return nil
            } else if matches[1] == base {
                return nil
            }
            return fmt.Errorf("Expecting %q, have %q in %q", base, matches[1], input)
        },
        "INCLUDE (.+)": func(matches []string) error {
            yield("# Included from " + matches[1])

            include := regexp.MustCompile("github.com/([^/]+)/([^/]+)").FindStringSubmatch(matches[1])
            if len(include) > 0 {
                vendor := include[1]
                name := include[2]

                target := filepath.Join("vendor", vendor, name)
                zip := filepath.Join(target, "master.zip")

                if err := os.MkdirAll(target, 0700); err != nil {
                    return err
                }

                _, err := Download("https://github.com/"+vendor+"/"+name+"/archive/master.zip", zip)
                if err != nil {
                    return err
                }

                if err := Unzip(zip, target, strings.NewReplacer(name+"-master/", "")); err != nil {
                    return err
                }

                Transform(filepath.Join(target, "Dockerfile.in"), base, yield)
            }
            return nil
        },
    }

    file, err := os.Open(input)
    if err != nil {
        return err
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        line := scanner.Text()
        transformed := false

        for pattern, action := range transformations {
            matches := regexp.MustCompile(pattern).FindStringSubmatch(line)
            if len(matches) > 0 {
                if err := action(matches); err != nil {
                    return err
                }
                transformed = true
                break
            }
        }

        if !transformed {
            yield(line)
        }
    }

    if err := scanner.Err(); err != nil {
        return err
    }

    return nil
}

func main() {
    err := Transform("Dockerfile.in", "", func(line string) { fmt.Println(line) })

    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package bot

import (
	"errors"
	"io"
	"net/http"
	"time"

	"github.com/moovweb/gokogiri"
	"github.com/moovweb/gokogiri/xpath"
)

var elementNotFound = errors.New("Element not found in document")

func httpGet(l string) ([]byte, error) {
	var buf []byte
	tr := &http.Transport{
		TLSHandshakeTimeout:   5 * time.Second,
		ResponseHeaderTimeout: 5 * time.Second,
	}
	client := &http.Client{Transport: tr}

	resp, err := client.Get(l)
	if err != nil {
		return []byte{}, err
	}

	// 5MiB
	if resp.ContentLength > 5*1024*1024 || resp.ContentLength < 0 {
		buf = make([]byte, 5*1024*1024)
	} else if resp.ContentLength == 0 {
		return []byte{}, nil
	} else {
		buf = make([]byte, resp.ContentLength)
	}

	i, err := io.ReadFull(resp.Body, buf)
	if err == io.ErrUnexpectedEOF {
		buf = buf[:i]
	} else if err != nil {
		return []byte{}, err
	}

	return buf, nil
}

func httpGetXpath(l, x string) (string, error) {
	buf, err := httpGet(l)
	if err != nil {
		return "", err
	}

	doc, err := gokogiri.ParseHtml(buf)
	defer doc.Free()
	if err != nil {
		return "", err
	}

	xpath := xpath.Compile(x)
	sr, err := doc.Root().Search(xpath)
	if err != nil {
		return "", err
	}

	if len(sr) > 0 {
		return sr[0].InnerHtml(), nil
	} else {
		return "", elementNotFound
	}
}
<commit_msg>Add a reply helper to reduce code duplication.<commit_after>// Copyright 2015 Robert S. Gerus. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package bot

import (
	"errors"
	"io"
	"net/http"
	"time"

	"github.com/moovweb/gokogiri"
	"github.com/moovweb/gokogiri/xpath"

	cfg "github.com/arachnist/gorepost/config"
	"github.com/arachnist/gorepost/irc"
)

var elementNotFound = errors.New("Element not found in document")

func httpGet(l string) ([]byte, error) {
	var buf []byte
	tr := &http.Transport{
		TLSHandshakeTimeout:   5 * time.Second,
		ResponseHeaderTimeout: 5 * time.Second,
	}
	client := &http.Client{Transport: tr}

	resp, err := client.Get(l)
	if err != nil {
		return []byte{}, err
	}

	// 5MiB
	if resp.ContentLength > 5*1024*1024 || resp.ContentLength < 0 {
		buf = make([]byte, 5*1024*1024)
	} else if resp.ContentLength == 0 {
		return []byte{}, nil
	} else {
		buf = make([]byte, resp.ContentLength)
	}

	i, err := io.ReadFull(resp.Body, buf)
	if err == io.ErrUnexpectedEOF {
		buf = buf[:i]
	} else if err != nil {
		return []byte{}, err
	}

	return buf, nil
}

func httpGetXpath(l, x string) (string, error) {
	buf, err := httpGet(l)
	if err != nil {
		return "", err
	}

	doc, err := gokogiri.ParseHtml(buf)
	defer doc.Free()
	if err != nil {
		return "", err
	}

	xpath := xpath.Compile(x)
	sr, err := doc.Root().Search(xpath)
	if err != nil {
		return "", err
	}

	if len(sr) > 0 {
		return sr[0].InnerHtml(), nil
	} else {
		return "", elementNotFound
	}
}

func reply(msg irc.Message, text string) irc.Message {
	if msg.Params[0] == cfg.LookupString(msg.Context, "Nick") {
		return irc.Message{
			Command:  "PRIVMSG",
			Params:   []string{msg.Prefix.Name},
			Trailing: text,
		}
	} else {
		return irc.Message{
			Command:  "PRIVMSG",
			Params:   msg.Params,
			Trailing: text,
		}
	}
}
<|endoftext|>


<commit_before>package onedrive

import (
	"fmt"
	"net/http"
)

type StorageState string

const (
	NormalStorageState   StorageState = "normal"
	NearingStorageState  StorageState = "nearing"
	CriticalStorageState StorageState = "critical"
	ExceededStorageState StorageState = "exceeded"
)

// DriveService manages the communication with Drive related API endpoints
type DriveService struct {
	*OneDrive
}

// The Identity type represents an identity of an actor. For example, and actor
// can be a user, device, or application.
// See: http://onedrive.github.io/resources/identity.htm
type Identity struct {
	ID          string `json:"id"`
	DisplayName string `json:"displayName"`
}

// The IdentitySet type is a keyed collection of Identity objects. It is used
// to represent a set of identities associated with various events for an item,
// such as created by or last modified by.
// See: http://onedrive.github.io/resources/identitySet.htm
type IdentitySet struct {
	User        *Identity `json:"user"`
	Application *Identity `json:"application"`
	Device      *Identity `json:"device"`
}

// The Quota facet groups storage space quota-related information on OneDrive
// into a single structure.
// See: http://onedrive.github.io/facets/quotainfo_facet.htm
type Quota struct {
	Total     int64  `json:"total"`
	Used      int64  `json:"used"`
	Remaining int64  `json:"remaining"`
	Deleted   int64  `json:"deleted"`
	State     string `json:"state"`
}

// Drives represents a list of Drives
type Drives struct {
	List []*Drive `json:"value"`
}

// The Drive resource represents a drive in OneDrive. It provides information
// about the owner of the drive, total and available storage space, and exposes
// a collection of all the Items contained within the drive.
// See: http://onedrive.github.io/resources/drive.htm
type Drive struct {
	ID        string      `json:"id"`
	DriveType string      `json:"driveType"`
	Owner     IdentitySet `json:"owner"`
	Quota     Quota       `json:"quota"`
}

// Get returns a Drive for the authenticated user. If no driveID is provided
// the users default Drive is returned. A user will always have at least one
// Drive available -- the default Drive.
func (ds *DriveService) Get(driveID string) (*Drive, *http.Response, error) {
	var path string

	switch driveID {
	case "":
		path = "/drive"
		break
	case "root":
		path = "/drive/root"
		break
	default:
		path = fmt.Sprintf("/drives/%s", driveID)
	}

	req, err := ds.newRequest("GET", path, nil, nil)
	if err != nil {
		return nil, nil, err
	}

	drive := new(Drive)
	resp, err := ds.do(req, drive)
	if err != nil {
		return nil, resp, err
	}

	return drive, resp, nil
}

// GetDefaultDrive is a convenience function to return the users default Drive
func (ds *DriveService) GetDefaultDrive() (*Drive, *http.Response, error) {
	return ds.Get("")
}

// GetRootDrive is a convenience function to return the users root folder of the
// users default Drive
func (ds *DriveService) GetRootDrive() (*Drive, *http.Response, error) {
	return ds.Get("root")
}

// List returns all the Drives available to the authenticated user
func (ds *DriveService) List() (*Drives, *http.Response, error) {
	req, err := ds.newRequest("GET", "/drives", nil, nil)
	if err != nil {
		return nil, nil, err
	}

	drives := new(Drives)
	resp, err := ds.do(req, drives)
	if err != nil {
		return nil, resp, err
	}

	return drives, resp, nil
}

// ListChildren returns a collection of all the Items under the Drive.
func (ds *DriveService) ListChildren(driveID string) (*Items, *http.Response, error) {
	var path string

	switch driveID {
	case "root":
		path = "/drive/root/children"
		break
	default:
		path = fmt.Sprintf("/drives/%s/root/children", driveID)
	}

	req, err := ds.newRequest("GET", path, nil, nil)
	if err != nil {
		return nil, nil, err
	}

	items := new(Items)
	resp, err := ds.do(req, items)
	if err != nil {
		return nil, resp, err
	}

	return items, resp, nil
}
<commit_msg>Remove unused constants<commit_after>package onedrive

import (
	"fmt"
	"net/http"
)

// DriveService manages the communication with Drive related API endpoints
type DriveService struct {
	*OneDrive
}

// The Identity type represents an identity of an actor. For example, and actor
// can be a user, device, or application.
// See: http://onedrive.github.io/resources/identity.htm
type Identity struct {
	ID          string `json:"id"`
	DisplayName string `json:"displayName"`
}

// The IdentitySet type is a keyed collection of Identity objects. It is used
// to represent a set of identities associated with various events for an item,
// such as created by or last modified by.
// See: http://onedrive.github.io/resources/identitySet.htm
type IdentitySet struct {
	User        *Identity `json:"user"`
	Application *Identity `json:"application"`
	Device      *Identity `json:"device"`
}

// The Quota facet groups storage space quota-related information on OneDrive
// into a single structure.
// See: http://onedrive.github.io/facets/quotainfo_facet.htm
type Quota struct {
	Total     int64  `json:"total"`
	Used      int64  `json:"used"`
	Remaining int64  `json:"remaining"`
	Deleted   int64  `json:"deleted"`
	State     string `json:"state"`
}

// Drives represents a list of Drives
type Drives struct {
	List []*Drive `json:"value"`
}

// The Drive resource represents a drive in OneDrive. It provides information
// about the owner of the drive, total and available storage space, and exposes
// a collection of all the Items contained within the drive.
// See: http://onedrive.github.io/resources/drive.htm
type Drive struct {
	ID        string      `json:"id"`
	DriveType string      `json:"driveType"`
	Owner     IdentitySet `json:"owner"`
	Quota     Quota       `json:"quota"`
}

// Get returns a Drive for the authenticated user. If no driveID is provided
// the users default Drive is returned. A user will always have at least one
// Drive available -- the default Drive.
func (ds *DriveService) Get(driveID string) (*Drive, *http.Response, error) {
	var path string

	switch driveID {
	case "":
		path = "/drive"
		break
	case "root":
		path = "/drive/root"
		break
	default:
		path = fmt.Sprintf("/drives/%s", driveID)
	}

	req, err := ds.newRequest("GET", path, nil, nil)
	if err != nil {
		return nil, nil, err
	}

	drive := new(Drive)
	resp, err := ds.do(req, drive)
	if err != nil {
		return nil, resp, err
	}

	return drive, resp, nil
}

// GetDefaultDrive is a convenience function to return the users default Drive
func (ds *DriveService) GetDefaultDrive() (*Drive, *http.Response, error) {
	return ds.Get("")
}

// GetRootDrive is a convenience function to return the users root folder of the
// users default Drive
func (ds *DriveService) GetRootDrive() (*Drive, *http.Response, error) {
	return ds.Get("root")
}

// List returns all the Drives available to the authenticated user
func (ds *DriveService) List() (*Drives, *http.Response, error) {
	req, err := ds.newRequest("GET", "/drives", nil, nil)
	if err != nil {
		return nil, nil, err
	}

	drives := new(Drives)
	resp, err := ds.do(req, drives)
	if err != nil {
		return nil, resp, err
	}

	return drives, resp, nil
}

// ListChildren returns a collection of all the Items under the Drive.
func (ds *DriveService) ListChildren(driveID string) (*Items, *http.Response, error) {
	var path string

	switch driveID {
	case "root":
		path = "/drive/root/children"
		break
	default:
		path = fmt.Sprintf("/drives/%s/root/children", driveID)
	}

	req, err := ds.newRequest("GET", path, nil, nil)
	if err != nil {
		return nil, nil, err
	}

	items := new(Items)
	resp, err := ds.do(req, items)
	if err != nil {
		return nil, resp, err
	}

	return items, resp, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package zap

import (
	"encoding/base64"
	"fmt"
	"math"
	"time"

	"go.uber.org/zap/internal/buffers"
	"go.uber.org/zap/zapcore"
)

// Skip constructs a no-op field.
func Skip() zapcore.Field {
	return zapcore.Field{Type: zapcore.SkipType}
}

// Base64 constructs a field that eagerly base64-encodes bytes.
func Base64(key string, val []byte) zapcore.Field {
	return String(key, base64.StdEncoding.EncodeToString(val))
}

// Bool constructs a field with the given key and value.
func Bool(key string, val bool) zapcore.Field {
	var ival int64
	if val {
		ival = 1
	}
	return zapcore.Field{Key: key, Type: zapcore.BoolType, Integer: ival}
}

// Float64 constructs a field with the given key and value. The way the
// floating-point value is represented is encoder-dependent, so marshaling is
// necessarily lazy.
func Float64(key string, val float64) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.Float64Type, Integer: int64(math.Float64bits(val))}
}

// Int constructs a field with the given key and value.
func Int(key string, val int) zapcore.Field {
	return Int64(key, int64(val))
}

// Int64 constructs a field with the given key and value.
func Int64(key string, val int64) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.Int64Type, Integer: val}
}

// Uint constructs a field with the given key and value.
func Uint(key string, val uint) zapcore.Field {
	return Uint64(key, uint64(val))
}

// Uint64 constructs a field with the given key and value.
func Uint64(key string, val uint64) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.Uint64Type, Integer: int64(val)}
}

// Uintptr constructs a field with the given key and value.
func Uintptr(key string, val uintptr) zapcore.Field {
	return Uint64(key, uint64(val))
}

// String constructs a field with the given key and value.
func String(key string, val string) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.StringType, String: val}
}

// Stringer constructs a field with the given key and the output of the value's
// String method. The Stringer's String method is called lazily.
func Stringer(key string, val fmt.Stringer) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.StringerType, Interface: val}
}

// Time constructs a zapcore.Field with the given key and value. It represents a
// time.Time as an integer number of milliseconds since epoch. Conversion to an
// int64 happens eagerly.
func Time(key string, val time.Time) zapcore.Field {
	return Int64(key, timeToMillis(val))
}

// Error constructs a field that lazily stores err.Error() under the key
// "error". If passed a nil error, the field is a no-op. This is purely a
// convenience for a common error-logging idiom; use String("someFieldName",
// err.Error()) to customize the key.
func Error(err error) zapcore.Field {
	if err == nil {
		return Skip()
	}
	return zapcore.Field{Key: "error", Type: zapcore.ErrorType, Interface: err}
}

// Stack constructs a field that stores a stacktrace of the current goroutine
// under the key "stacktrace". Keep in mind that taking a stacktrace is eager
// and extremely expensive (relatively speaking); this function both makes an
// allocation and takes ~10 microseconds.
func Stack() zapcore.Field {
	// Try to avoid allocating a buffer.
	buf := buffers.Get()
	// Returning the stacktrace as a string costs an allocation, but saves us
	// from expanding the zapcore.Field union struct to include a byte slice. Since
	// taking a stacktrace is already so expensive (~10us), the extra allocation
	// is okay.
	field := String("stacktrace", takeStacktrace(buf[:cap(buf)], false))
	buffers.Put(buf)
	return field
}

// Duration constructs a field with the given key and value. It represents
// durations as an integer number of nanoseconds.
func Duration(key string, val time.Duration) zapcore.Field {
	return Int64(key, int64(val))
}

// Object constructs a field with the given key and ObjectMarshaler. It
// provides a flexible, but still type-safe and efficient, way to add map- or
// struct-like user-defined types to the logging context. The struct's
// MarshalLogObject method is called lazily.
func Object(key string, val zapcore.ObjectMarshaler) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: val}
}

// Reflect constructs a field with the given key and an arbitrary object. It uses
// an encoding-appropriate, reflection-based function to lazily serialize nearly
// any object into the logging context, but it's relatively slow and
// allocation-heavy.
//
// If encoding fails (e.g., trying to serialize a map[int]string to JSON), Reflect
// includes the error message in the final log output.
func Reflect(key string, val interface{}) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.ReflectType, Interface: val}
}

// Nest takes a key and a variadic number of zapcore.Fields and creates a nested
// namespace.
func Nest(key string, fields ...zapcore.Field) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: zapcore.Fields(fields)}
}

// Any takes a key and an arbitrary value and chooses the best way to represent
// them as a field, falling back to a reflection-based approach only if
// necessary.
func Any(key string, value interface{}) zapcore.Field {
	switch val := value.(type) {
	case zapcore.ObjectMarshaler:
		return Object(key, val)
	case bool:
		return Bool(key, val)
	case float64:
		return Float64(key, val)
	case float32:
		return Float64(key, float64(val))
	case int:
		return Int(key, val)
	case int64:
		return Int64(key, val)
	case int32:
		return Int64(key, int64(val))
	case int16:
		return Int64(key, int64(val))
	case int8:
		return Int64(key, int64(val))
	case uint:
		return Uint(key, val)
	case uint64:
		return Uint64(key, val)
	case uint32:
		return Uint64(key, uint64(val))
	case uint16:
		return Uint64(key, uint64(val))
	case uint8:
		return Uint64(key, uint64(val))
	case uintptr:
		return Uintptr(key, val)
	case string:
		return String(key, val)
	case error:
		return String(key, val.Error())
	case time.Time:
		return Time(key, val)
	case time.Duration:
		return Duration(key, val)
	case fmt.Stringer:
		return String(key, val.String())
	default:
		return Reflect(key, val)
	}
}
<commit_msg>Add test coverage for zap.Any<commit_after>// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package zap

import (
	"encoding/base64"
	"fmt"
	"math"
	"time"

	"go.uber.org/zap/internal/buffers"
	"go.uber.org/zap/zapcore"
)

// Skip constructs a no-op field.
func Skip() zapcore.Field {
	return zapcore.Field{Type: zapcore.SkipType}
}

// Base64 constructs a field that eagerly base64-encodes bytes.
func Base64(key string, val []byte) zapcore.Field {
	return String(key, base64.StdEncoding.EncodeToString(val))
}

// Bool constructs a field with the given key and value.
func Bool(key string, val bool) zapcore.Field {
	var ival int64
	if val {
		ival = 1
	}
	return zapcore.Field{Key: key, Type: zapcore.BoolType, Integer: ival}
}

// Float64 constructs a field with the given key and value. The way the
// floating-point value is represented is encoder-dependent, so marshaling is
// necessarily lazy.
func Float64(key string, val float64) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.Float64Type, Integer: int64(math.Float64bits(val))}
}

// Int constructs a field with the given key and value.
func Int(key string, val int) zapcore.Field {
	return Int64(key, int64(val))
}

// Int64 constructs a field with the given key and value.
func Int64(key string, val int64) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.Int64Type, Integer: val}
}

// Uint constructs a field with the given key and value.
func Uint(key string, val uint) zapcore.Field {
	return Uint64(key, uint64(val))
}

// Uint64 constructs a field with the given key and value.
func Uint64(key string, val uint64) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.Uint64Type, Integer: int64(val)}
}

// Uintptr constructs a field with the given key and value.
func Uintptr(key string, val uintptr) zapcore.Field {
	return Uint64(key, uint64(val))
}

// String constructs a field with the given key and value.
func String(key string, val string) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.StringType, String: val}
}

// Stringer constructs a field with the given key and the output of the value's
// String method. The Stringer's String method is called lazily.
func Stringer(key string, val fmt.Stringer) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.StringerType, Interface: val}
}

// Time constructs a zapcore.Field with the given key and value. It represents a
// time.Time as an integer number of milliseconds since epoch. Conversion to an
// int64 happens eagerly.
func Time(key string, val time.Time) zapcore.Field {
	return Int64(key, timeToMillis(val))
}

// Error constructs a field that lazily stores err.Error() under the key
// "error". If passed a nil error, the field is a no-op. This is purely a
// convenience for a common error-logging idiom; use String("someFieldName",
// err.Error()) to customize the key.
func Error(err error) zapcore.Field {
	if err == nil {
		return Skip()
	}
	return zapcore.Field{Key: "error", Type: zapcore.ErrorType, Interface: err}
}

// Stack constructs a field that stores a stacktrace of the current goroutine
// under the key "stacktrace". Keep in mind that taking a stacktrace is eager
// and extremely expensive (relatively speaking); this function both makes an
// allocation and takes ~10 microseconds.
func Stack() zapcore.Field {
	// Try to avoid allocating a buffer.
	buf := buffers.Get()
	// Returning the stacktrace as a string costs an allocation, but saves us
	// from expanding the zapcore.Field union struct to include a byte slice. Since
	// taking a stacktrace is already so expensive (~10us), the extra allocation
	// is okay.
	field := String("stacktrace", takeStacktrace(buf[:cap(buf)], false))
	buffers.Put(buf)
	return field
}

// Duration constructs a field with the given key and value. It represents
// durations as an integer number of nanoseconds.
func Duration(key string, val time.Duration) zapcore.Field {
	return Int64(key, int64(val))
}

// Object constructs a field with the given key and ObjectMarshaler. It
// provides a flexible, but still type-safe and efficient, way to add map- or
// struct-like user-defined types to the logging context. The struct's
// MarshalLogObject method is called lazily.
func Object(key string, val zapcore.ObjectMarshaler) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: val}
}

// Reflect constructs a field with the given key and an arbitrary object. It uses
// an encoding-appropriate, reflection-based function to lazily serialize nearly
// any object into the logging context, but it's relatively slow and
// allocation-heavy.
//
// If encoding fails (e.g., trying to serialize a map[int]string to JSON), Reflect
// includes the error message in the final log output.
func Reflect(key string, val interface{}) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.ReflectType, Interface: val}
}

// Nest takes a key and a variadic number of zapcore.Fields and creates a nested
// namespace.
func Nest(key string, fields ...zapcore.Field) zapcore.Field {
	return zapcore.Field{Key: key, Type: zapcore.ObjectMarshalerType, Interface: zapcore.Fields(fields)}
}

// Any takes a key and an arbitrary value and chooses the best way to represent
// them as a field, falling back to a reflection-based approach only if
// necessary.
func Any(key string, value interface{}) zapcore.Field {
	switch val := value.(type) {
	case zapcore.ObjectMarshaler:
		return Object(key, val)
	case bool:
		return Bool(key, val)
	case float64:
		return Float64(key, val)
	case float32:
		return Float64(key, float64(val))
	case int:
		return Int(key, val)
	case int64:
		return Int64(key, val)
	case int32:
		return Int64(key, int64(val))
	case int16:
		return Int64(key, int64(val))
	case int8:
		return Int64(key, int64(val))
	case uint:
		return Uint(key, val)
	case uint64:
		return Uint64(key, val)
	case uint32:
		return Uint64(key, uint64(val))
	case uint16:
		return Uint64(key, uint64(val))
	case uint8:
		return Uint64(key, uint64(val))
	case uintptr:
		return Uintptr(key, val)
	case string:
		return String(key, val)
	case error:
		return String(key, val.Error())
	case time.Time:
		return Time(key, val)
	case time.Duration:
		return Duration(key, val)
	case fmt.Stringer:
		return Stringer(key, val)
	default:
		return Reflect(key, val)
	}
}
<|endoftext|>