<commit_before>/*
 * Copyright (c) 2013 Dario Castañé.
 * This file is part of Zingy.
 *
 * Zingy is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Zingy is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Zingy.  If not, see <http://www.gnu.org/licenses/>.
 */
package main

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/moovweb/gokogiri"
	"github.com/moovweb/gokogiri/html"
	"github.com/moovweb/gokogiri/xml"
	markdown "github.com/russross/blackfriday"
	thtml "html/template"
	ttext "text/template"
	"io"
	"io/ioutil"
	yaml "launchpad.net/goyaml"
	"os"
	"os/exec"
	pathes "path"
	"path/filepath"
	"reflect"
	"strings"
)

var cmdGenerate = &Subcommand{
	UsageLine: "generate",
}

type Generator struct {
	Config ConfigSection
	Layout *thtml.Template
}

func (gen *Generator) GetDeployPath() string {
	return gen.Config.GetZString("deploy")
}

func (gen *Generator) BuildDeployPath(path string) string {
	return filepath.Join(gen.GetDeployPath(), path)
}

func (gen *Generator) Generate(path string, data *ZingyData) (err error) {
	writer, err := os.OpenFile(gen.BuildDeployPath(data.Path), os.O_CREATE|os.O_TRUNC|os.O_RDWR, os.FileMode(ZNG_DEFAULT_FILE_PERM))
	if err != nil {
		return
	}
	defer writer.Close()
	return gen.Layout.Execute(writer, data)
}

type ZingyData struct {
	Body   thtml.HTML
	Title  string
	Path   string
	Site   ZingySiteData
	Page   map[interface{}]interface{}
	config ConfigSection
}

type ZingySiteData struct {
	BaseURL string
	Image   string
}

func (zd *ZingyData) URL() string {
	return fmt.Sprintf("%s%s", zd.Site.BaseURL, zd.Path)
}

func (zd *ZingyData) Extra(path string) (value string, err error) {
	path = pathes.Clean(path)
	if pathes.IsAbs(path) {
		path = path[1:]
	}
	steps := strings.Split(path, "/")
	last := len(steps) - 1
	key, steps := steps[last], steps[:last]
	section := zd.config
	for _, step := range steps {
		section = section.GetSection(step)
		if section == nil {
			err = errors.New("not found")
			return
		}
	}
	value = section.GetString(key)
	return
}

func NewZingyData(path string, config ConfigSection) (data ZingyData) {
	if strings.HasSuffix(path, ".md") {
		path = strings.Replace(path, ".md", ".html", -1)
	}
	data.Path = fmt.Sprintf("/%s", path)
	data.config = config
	data.Site.BaseURL = config.GetSection("site").GetString("baseurl")
	data.Site.Image = config.GetSection("site").GetString("image")
	return
}

func init() {
	cmdGenerate.Run = func() {
		var (
			gen Generator
			err error
		)
		if gen.Config, err = NewConfig(); err != nil {
			panic(err)
		}
		if gen.Layout, err = thtml.ParseFiles(gen.Config.GetZString("layout")); err != nil {
			panic(err)
		}
		deployPath := gen.GetDeployPath()
		if _, err := os.Stat(deployPath); err == nil {
			if err = os.RemoveAll(deployPath); err != nil {
				panic(err)
			}
		}
		if err = os.Mkdir(deployPath, os.FileMode(ZNG_DEFAULT_DIR_PERM)); err != nil {
			panic(err)
		}
		walk := func(path string, info os.FileInfo, err error) error {
			return gen.walk(path, info, err)
		}
		if err := filepath.Walk(".", walk); err != nil {
			panic(err)
		}
	}
	cmdGenerate.Init()
}

func (gen *Generator) walk(path string, info os.FileInfo, err error) (ierr error) {
	if strings.HasPrefix(path, ".") {
		return nil
	}
	switch {
	case info.IsDir():
		ierr = os.Mkdir(gen.BuildDeployPath(path), os.FileMode(ZNG_DEFAULT_DIR_PERM))
	case strings.HasSuffix(path, ".md"):
		ierr = gen.renderMarkdown(path)
	case strings.HasSuffix(path, ".html"):
		ierr = gen.renderHTML(path)
	default:
		ierr = gen.copy(gen.BuildDeployPath(path), path)
	}
	return
}

func (gen *Generator) renderMarkdown(path string) (err error) {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}
	md := markdown.MarkdownCommon(input)
	return gen.render(path, md)
}

func (gen *Generator) renderHTML(path string) (err error) {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}
	return gen.render(path, input)
}

func (gen *Generator) render(path string, input []byte) (err error) {
	template, err := ttext.New("current").Parse(string(input))
	if err != nil {
		return
	}
	var processed bytes.Buffer
	data := NewZingyData(path, gen.Config)
	if err = template.Execute(&processed, &data); err != nil {
		return
	}
	doc, err := gokogiri.ParseHtml(processed.Bytes())
	if err != nil {
		return
	}
	defer doc.Free()
	if err = gen.handleEmbedTags(doc); err != nil {
		return
	}
	gen.cleanUnnecessaryPTags(doc)
	data.Page, err = gen.extractPageConfig(doc)
	if err != nil {
		fmt.Println(path, "=>", err)
		err = nil
	}
	data.Title = gen.getTitle(doc)
	body, err := doc.Search("//body")
	if err != nil {
		return
	}
	data.Body = thtml.HTML(body[0].InnerHtml())
	return gen.Generate(path, &data)
}

func (gen *Generator) cleanUnnecessaryPTags(doc *html.HtmlDocument) (err error) {
	ps, err := doc.Search("//p")
	if err != nil {
		return
	}
	for _, p := range ps {
		hasText := false
		child := p.FirstChild()
		for child != nil {
			typ := child.NodeType()
			if typ == xml.XML_TEXT_NODE {
				hasText = true
				break
			}
			child = child.NextSibling()
		}
		if !hasText {
			parent := p.Parent()
			child = p.FirstChild()
			for child != nil {
				parent.AddChild(child)
				child = child.NextSibling()
			}
			p.Remove()
		}
	}
	return
}

func (gen *Generator) getTitle(doc *html.HtmlDocument) (title string) {
	result, _ := doc.Search("//h1")
	if len(result) > 0 {
		title = result[0].FirstChild().Content()
	}
	return
}

func (gen *Generator) extractPageConfig(doc *html.HtmlDocument) (config map[interface{}]interface{}, err error) {
	result, _ := doc.Search("//comment()")
	if len(result) > 0 {
		err = yaml.Unmarshal([]byte(result[0].Content()), &config)
	}
	return
}

func (gen *Generator) copy(dstPath string, srcPath string) (err error) {
	src, err := os.Open(srcPath)
	if err != nil {
		return
	}
	defer src.Close()
	dst, err := os.OpenFile(dstPath, os.O_CREATE|os.O_TRUNC|os.O_RDWR, os.FileMode(ZNG_DEFAULT_FILE_PERM))
	if err != nil {
		return
	}
	defer dst.Close()
	_, err = io.Copy(dst, src)
	return
}

func (gen *Generator) Markdown(e xml.Node, doc *html.HtmlDocument) (err error) {
	src := e.Attribute("src").Value()
	mdInput, err := ioutil.ReadFile(src)
	if err != nil {
		return err
	}
	md := markdown.MarkdownCommon(mdInput)
	mdDoc, err := gokogiri.ParseHtml(md)
	if err != nil {
		return err
	}
	partial, err := mdDoc.Search("//body")
	if err != nil {
		return err
	}
	parent := e.Parent()
	child := partial[0].FirstChild()
	for child != nil {
		parent.AddChild(child)
		child = child.NextSibling()
	}
	e.Remove()
	return
}

func (gen *Generator) handleEmbedTags(doc *html.HtmlDocument) (err error) {
	result, err := doc.Search("//embed")
	if err != nil {
		return
	}
	for _, e := range result {
		plugin := gen.resolveMIMETypePlugin(e.Attribute("type").Value())
		method := reflect.ValueOf(gen).MethodByName(strings.Title(plugin))
		if method == reflect.ValueOf(nil) {
			err = gen.handleMIMETypePlugin(e, doc)
		} else {
			args := make([]reflect.Value, 2)
			args[0] = reflect.ValueOf(e)
			args[1] = reflect.ValueOf(doc)
			r := method.Call(args)
			rerr := r[0].Interface()
			if ierr, ok := rerr.(error); ok {
				err = ierr
			}
		}
		if err != nil {
			return
		}
	}
	return
}

type bufErr struct {
	buffer []byte
	err    error
}

func (gen *Generator) handleMIMETypePlugin(e xml.Node, doc *html.HtmlDocument) (err error) {
	src := e.Attribute("src").Value()
	typ := e.Attribute("type").Value()
	cmd := exec.Command(fmt.Sprintf("m%s%s", ZNG_PREFIX, gen.resolveMIMETypePlugin(typ)), src)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return
	}
	cmd.Stderr = os.Stderr
	c := make(chan bufErr)
	go func() {
		data, err := ioutil.ReadAll(stdout)
		c <- bufErr{data, err}
	}()
	if err = cmd.Start(); err != nil {
		return
	}
	be := <-c
	if err = cmd.Wait(); err != nil {
		return
	}
	if be.err != nil {
		return be.err
	}
	parent := e.Parent()
	child, err := doc.Coerce(be.buffer)
	if err != nil {
		return
	}
	parent.AddChild(child)
	e.Remove()
	return
}

func (gen *Generator) resolveMIMETypePlugin(typ string) string {
	return gen.Config.GetSection("mimetypes").GetString(typ)
}
<commit_msg>go fmt.<commit_after>/*
 * Copyright (c) 2013 Dario Castañé.
 * This file is part of Zingy.
 *
 * Zingy is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Zingy is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Zingy.  If not, see <http://www.gnu.org/licenses/>.
 */
package main

import (
	"bytes"
	"errors"
	"fmt"
	"github.com/moovweb/gokogiri"
	"github.com/moovweb/gokogiri/html"
	"github.com/moovweb/gokogiri/xml"
	markdown "github.com/russross/blackfriday"
	thtml "html/template"
	"io"
	"io/ioutil"
	yaml "launchpad.net/goyaml"
	"os"
	"os/exec"
	pathes "path"
	"path/filepath"
	"reflect"
	"strings"
	ttext "text/template"
)

var cmdGenerate = &Subcommand{
	UsageLine: "generate",
}

type Generator struct {
	Config ConfigSection
	Layout *thtml.Template
}

func (gen *Generator) GetDeployPath() string {
	return gen.Config.GetZString("deploy")
}

func (gen *Generator) BuildDeployPath(path string) string {
	return filepath.Join(gen.GetDeployPath(), path)
}

func (gen *Generator) Generate(path string, data *ZingyData) (err error) {
	writer, err := os.OpenFile(gen.BuildDeployPath(data.Path), os.O_CREATE|os.O_TRUNC|os.O_RDWR, os.FileMode(ZNG_DEFAULT_FILE_PERM))
	if err != nil {
		return
	}
	defer writer.Close()
	return gen.Layout.Execute(writer, data)
}

type ZingyData struct {
	Body   thtml.HTML
	Title  string
	Path   string
	Site   ZingySiteData
	Page   map[interface{}]interface{}
	config ConfigSection
}

type ZingySiteData struct {
	BaseURL string
	Image   string
}

func (zd *ZingyData) URL() string {
	return fmt.Sprintf("%s%s", zd.Site.BaseURL, zd.Path)
}

func (zd *ZingyData) Extra(path string) (value string, err error) {
	path = pathes.Clean(path)
	if pathes.IsAbs(path) {
		path = path[1:]
	}
	steps := strings.Split(path, "/")
	last := len(steps) - 1
	key, steps := steps[last], steps[:last]
	section := zd.config
	for _, step := range steps {
		section = section.GetSection(step)
		if section == nil {
			err = errors.New("not found")
			return
		}
	}
	value = section.GetString(key)
	return
}

func NewZingyData(path string, config ConfigSection) (data ZingyData) {
	if strings.HasSuffix(path, ".md") {
		path = strings.Replace(path, ".md", ".html", -1)
	}
	data.Path = fmt.Sprintf("/%s", path)
	data.config = config
	data.Site.BaseURL = config.GetSection("site").GetString("baseurl")
	data.Site.Image = config.GetSection("site").GetString("image")
	return
}

func init() {
	cmdGenerate.Run = func() {
		var (
			gen Generator
			err error
		)
		if gen.Config, err = NewConfig(); err != nil {
			panic(err)
		}
		if gen.Layout, err = thtml.ParseFiles(gen.Config.GetZString("layout")); err != nil {
			panic(err)
		}
		deployPath := gen.GetDeployPath()
		if _, err := os.Stat(deployPath); err == nil {
			if err = os.RemoveAll(deployPath); err != nil {
				panic(err)
			}
		}
		if err = os.Mkdir(deployPath, os.FileMode(ZNG_DEFAULT_DIR_PERM)); err != nil {
			panic(err)
		}
		walk := func(path string, info os.FileInfo, err error) error {
			return gen.walk(path, info, err)
		}
		if err := filepath.Walk(".", walk); err != nil {
			panic(err)
		}
	}
	cmdGenerate.Init()
}

func (gen *Generator) walk(path string, info os.FileInfo, err error) (ierr error) {
	if strings.HasPrefix(path, ".") {
		return nil
	}
	switch {
	case info.IsDir():
		ierr = os.Mkdir(gen.BuildDeployPath(path), os.FileMode(ZNG_DEFAULT_DIR_PERM))
	case strings.HasSuffix(path, ".md"):
		ierr = gen.renderMarkdown(path)
	case strings.HasSuffix(path, ".html"):
		ierr = gen.renderHTML(path)
	default:
		ierr = gen.copy(gen.BuildDeployPath(path), path)
	}
	return
}

func (gen *Generator) renderMarkdown(path string) (err error) {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}
	md := markdown.MarkdownCommon(input)
	return gen.render(path, md)
}

func (gen *Generator) renderHTML(path string) (err error) {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		return
	}
	return gen.render(path, input)
}

func (gen *Generator) render(path string, input []byte) (err error) {
	template, err := ttext.New("current").Parse(string(input))
	if err != nil {
		return
	}
	var processed bytes.Buffer
	data := NewZingyData(path, gen.Config)
	if err = template.Execute(&processed, &data); err != nil {
		return
	}
	doc, err := gokogiri.ParseHtml(processed.Bytes())
	if err != nil {
		return
	}
	defer doc.Free()
	if err = gen.handleEmbedTags(doc); err != nil {
		return
	}
	gen.cleanUnnecessaryPTags(doc)
	data.Page, err = gen.extractPageConfig(doc)
	if err != nil {
		fmt.Println(path, "=>", err)
		err = nil
	}
	data.Title = gen.getTitle(doc)
	body, err := doc.Search("//body")
	if err != nil {
		return
	}
	data.Body = thtml.HTML(body[0].InnerHtml())
	return gen.Generate(path, &data)
}

func (gen *Generator) cleanUnnecessaryPTags(doc *html.HtmlDocument) (err error) {
	ps, err := doc.Search("//p")
	if err != nil {
		return
	}
	for _, p := range ps {
		hasText := false
		child := p.FirstChild()
		for child != nil {
			typ := child.NodeType()
			if typ == xml.XML_TEXT_NODE {
				hasText = true
				break
			}
			child = child.NextSibling()
		}
		if !hasText {
			parent := p.Parent()
			child = p.FirstChild()
			for child != nil {
				parent.AddChild(child)
				child = child.NextSibling()
			}
			p.Remove()
		}
	}
	return
}

func (gen *Generator) getTitle(doc *html.HtmlDocument) (title string) {
	result, _ := doc.Search("//h1")
	if len(result) > 0 {
		title = result[0].FirstChild().Content()
	}
	return
}

func (gen *Generator) extractPageConfig(doc *html.HtmlDocument) (config map[interface{}]interface{}, err error) {
	result, _ := doc.Search("//comment()")
	if len(result) > 0 {
		err = yaml.Unmarshal([]byte(result[0].Content()), &config)
	}
	return
}

func (gen *Generator) copy(dstPath string, srcPath string) (err error) {
	src, err := os.Open(srcPath)
	if err != nil {
		return
	}
	defer src.Close()
	dst, err := os.OpenFile(dstPath, os.O_CREATE|os.O_TRUNC|os.O_RDWR, os.FileMode(ZNG_DEFAULT_FILE_PERM))
	if err != nil {
		return
	}
	defer dst.Close()
	_, err = io.Copy(dst, src)
	return
}

func (gen *Generator) Markdown(e xml.Node, doc *html.HtmlDocument) (err error) {
	src := e.Attribute("src").Value()
	mdInput, err := ioutil.ReadFile(src)
	if err != nil {
		return err
	}
	md := markdown.MarkdownCommon(mdInput)
	mdDoc, err := gokogiri.ParseHtml(md)
	if err != nil {
		return err
	}
	partial, err := mdDoc.Search("//body")
	if err != nil {
		return err
	}
	parent := e.Parent()
	child := partial[0].FirstChild()
	for child != nil {
		parent.AddChild(child)
		child = child.NextSibling()
	}
	e.Remove()
	return
}

func (gen *Generator) handleEmbedTags(doc *html.HtmlDocument) (err error) {
	result, err := doc.Search("//embed")
	if err != nil {
		return
	}
	for _, e := range result {
		plugin := gen.resolveMIMETypePlugin(e.Attribute("type").Value())
		method := reflect.ValueOf(gen).MethodByName(strings.Title(plugin))
		if method == reflect.ValueOf(nil) {
			err = gen.handleMIMETypePlugin(e, doc)
		} else {
			args := make([]reflect.Value, 2)
			args[0] = reflect.ValueOf(e)
			args[1] = reflect.ValueOf(doc)
			r := method.Call(args)
			rerr := r[0].Interface()
			if ierr, ok := rerr.(error); ok {
				err = ierr
			}
		}
		if err != nil {
			return
		}
	}
	return
}

type bufErr struct {
	buffer []byte
	err    error
}

func (gen *Generator) handleMIMETypePlugin(e xml.Node, doc *html.HtmlDocument) (err error) {
	src := e.Attribute("src").Value()
	typ := e.Attribute("type").Value()
	cmd := exec.Command(fmt.Sprintf("m%s%s", ZNG_PREFIX, gen.resolveMIMETypePlugin(typ)), src)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return
	}
	cmd.Stderr = os.Stderr
	c := make(chan bufErr)
	go func() {
		data, err := ioutil.ReadAll(stdout)
		c <- bufErr{data, err}
	}()
	if err = cmd.Start(); err != nil {
		return
	}
	be := <-c
	if err = cmd.Wait(); err != nil {
		return
	}
	if be.err != nil {
		return be.err
	}
	parent := e.Parent()
	child, err := doc.Coerce(be.buffer)
	if err != nil {
		return
	}
	parent.AddChild(child)
	e.Remove()
	return
}

func (gen *Generator) resolveMIMETypePlugin(typ string) string {
	return gen.Config.GetSection("mimetypes").GetString(typ)
}
<|endoftext|>


<commit_before>package main

import (
	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/elazarl/goproxy"
	"github.com/meatballhat/negroni-logrus"

	"flag"
	"fmt"
	"net/http"
	"os"
	"regexp"
)

const DefaultPort = ":8500"

// orPanic - wrapper for logging errors
func orPanic(err error) {
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Panic("Got error.")
	}
}

func main() {
	// getting proxy configuration
	verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
	record := flag.Bool("record", false, "should proxy record")
	destination := flag.String("destination", ".", "destination URI to catch")
	flag.Parse()

	// getting settings
	initSettings()

	// overriding default settings
	AppConfig.recordState = *record

	// overriding destination
	AppConfig.destination = *destination

	// getting default database
	port := os.Getenv("ProxyPort")
	if port == "" {
		port = DefaultPort
	} else {
		port = fmt.Sprintf(":%s", port)
	}

	// Output to stderr instead of stdout, could also be a file.
	log.SetOutput(os.Stderr)
	log.SetFormatter(&log.TextFormatter{})

	redisPool := getRedisPool()
	defer redisPool.Close()

	cache := Cache{pool: redisPool,
		prefix: AppConfig.cachePrefix}

	// getting connections
	d := DBClient{
		cache: cache,
		http:  &http.Client{},
	}

	// creating proxy
	proxy := goproxy.NewProxyHttpServer()

	proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*$"))).
		HandleConnect(goproxy.AlwaysMitm)

	// just helper handler to know where request hits proxy or no
	proxy.OnRequest().DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			log.WithFields(log.Fields{
				"destination": r.URL.Host,
			}).Info("Got request")

			return r, nil
		})

	// hijacking plain connections
	proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile(*destination))).DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {

			log.Info("connection found......")
			log.Info(fmt.Sprintf("Url path:  %s", r.URL.Path))

			return d.processRequest(r)
		})

	go d.startAdminInterface()

	proxy.Verbose = *verbose

	// proxy starting message
	log.WithFields(log.Fields{
		"RedisAddress": AppConfig.redisAddress,
		"Destination":  *destination,
		"ProxyPort":    port,
	}).Info("Proxy is starting...")

	log.Warn(http.ListenAndServe(port, proxy))
}

// processRequest - processes incoming requests and based on proxy state (record/playback)
// returns HTTP response.
func (d *DBClient) processRequest(req *http.Request) (*http.Request, *http.Response) {

	if AppConfig.recordState {
		log.Info("*** RECORD ***")
		newResponse, err := d.recordRequest(req)
		if err != nil {
			// something bad happened, passing through
			return req, nil
		} else {
			// discarding original requests and returns supplied response
			return req, newResponse
		}

	} else {
		log.Info("*** PLAYBACK ***")
		newResponse := d.getResponse(req)
		return req, newResponse
	}
}

func (d *DBClient) startAdminInterface() {
	// starting admin interface
	mux := getBoneRouter(*d)
	n := negroni.Classic()
	n.Use(negronilogrus.NewMiddleware())
	n.UseHandler(mux)

	// admin interface starting message
	log.WithFields(log.Fields{
		"RedisAddress": AppConfig.redisAddress,
		"AdminPort":    AppConfig.adminInterface,
	}).Info("Admin interface is starting...")

	n.Run(AppConfig.adminInterface)
}
<commit_msg>intercepting https<commit_after>package main

import (
	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/negroni"
	"github.com/elazarl/goproxy"
	"github.com/meatballhat/negroni-logrus"

	"bufio"
	"flag"
	"fmt"
	"net"
	"net/http"
	"os"
	"regexp"
)

const DefaultPort = ":8500"

// orPanic - wrapper for logging errors
func orPanic(err error) {
	if err != nil {
		log.WithFields(log.Fields{
			"error": err.Error(),
		}).Panic("Got error.")
	}
}

func main() {
	// getting proxy configuration
	verbose := flag.Bool("v", false, "should every proxy request be logged to stdout")
	record := flag.Bool("record", false, "should proxy record")
	destination := flag.String("destination", ".", "destination URI to catch")
	flag.Parse()

	// getting settings
	initSettings()

	// overriding default settings
	AppConfig.recordState = *record

	// overriding destination
	AppConfig.destination = *destination

	// getting default database
	port := os.Getenv("ProxyPort")
	if port == "" {
		port = DefaultPort
	} else {
		port = fmt.Sprintf(":%s", port)
	}

	// Output to stderr instead of stdout, could also be a file.
	log.SetOutput(os.Stderr)
	log.SetFormatter(&log.TextFormatter{})

	redisPool := getRedisPool()
	defer redisPool.Close()

	cache := Cache{pool: redisPool,
		prefix: AppConfig.cachePrefix}

	// getting connections
	d := DBClient{
		cache: cache,
		http:  &http.Client{},
	}

	// creating proxy
	proxy := goproxy.NewProxyHttpServer()

	proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*$"))).
		HandleConnect(goproxy.AlwaysMitm)

	// enable curl -p for all hosts on port 80
	proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile("^.*:80$"))).
		HijackConnect(func(req *http.Request, client net.Conn, ctx *goproxy.ProxyCtx) {
		defer func() {
			if e := recover(); e != nil {
				ctx.Logf("error connecting to remote: %v", e)
				client.Write([]byte("HTTP/1.1 500 Cannot reach destination\r\n\r\n"))
			}
			client.Close()
		}()
		clientBuf := bufio.NewReadWriter(bufio.NewReader(client), bufio.NewWriter(client))
		remote, err := net.Dial("tcp", req.URL.Host)
		orPanic(err)
		remoteBuf := bufio.NewReadWriter(bufio.NewReader(remote), bufio.NewWriter(remote))
		for {
			req, err := http.ReadRequest(clientBuf.Reader)
			orPanic(err)
			orPanic(req.Write(remoteBuf))
			orPanic(remoteBuf.Flush())
			resp, err := http.ReadResponse(remoteBuf.Reader, req)

			orPanic(err)
			orPanic(resp.Write(clientBuf.Writer))
			orPanic(clientBuf.Flush())
		}
	})

	// just helper handler to know where request hits proxy or no
	proxy.OnRequest().DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
			log.WithFields(log.Fields{
				"destination": r.URL.Host,
			}).Info("Got request")

			return r, nil
		})

	// hijacking plain connections
	proxy.OnRequest(goproxy.ReqHostMatches(regexp.MustCompile(*destination))).DoFunc(
		func(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {

			log.Info("connection found......")
			log.Info(fmt.Sprintf("Url path:  %s", r.URL.Path))

			return d.processRequest(r)
		})

	go d.startAdminInterface()

	proxy.Verbose = *verbose

	// proxy starting message
	log.WithFields(log.Fields{
		"RedisAddress": AppConfig.redisAddress,
		"Destination":  *destination,
		"ProxyPort":    port,
	}).Info("Proxy is starting...")

	log.Warn(http.ListenAndServe(port, proxy))
}

// processRequest - processes incoming requests and based on proxy state (record/playback)
// returns HTTP response.
func (d *DBClient) processRequest(req *http.Request) (*http.Request, *http.Response) {

	if AppConfig.recordState {
		log.Info("*** RECORD ***")
		newResponse, err := d.recordRequest(req)
		if err != nil {
			// something bad happened, passing through
			return req, nil
		} else {
			// discarding original requests and returns supplied response
			return req, newResponse
		}

	} else {
		log.Info("*** PLAYBACK ***")
		newResponse := d.getResponse(req)
		return req, newResponse
	}
}

func (d *DBClient) startAdminInterface() {
	// starting admin interface
	mux := getBoneRouter(*d)
	n := negroni.Classic()
	n.Use(negronilogrus.NewMiddleware())
	n.UseHandler(mux)

	// admin interface starting message
	log.WithFields(log.Fields{
		"RedisAddress": AppConfig.redisAddress,
		"AdminPort":    AppConfig.adminInterface,
	}).Info("Admin interface is starting...")

	n.Run(AppConfig.adminInterface)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 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 rules

import (
	"bytes"
	"errors"
	"sort"

	"github.com/m3db/m3metrics/filters"
	"github.com/m3db/m3metrics/generated/proto/schema"
	"github.com/m3db/m3metrics/policy"
)

var (
	emptyRollupTarget rollupTarget

	errNilRollupTargetSchema       = errors.New("nil rollup target schema")
	errNilRollupRuleSnapshotSchema = errors.New("nil rollup rule snapshot schema")
	errNilRollupRuleSchema         = errors.New("nil rollup rule schema")
)

// rollupTarget dictates how to roll up metrics. Metrics associated with a rollup
// target will be grouped and rolled up across the provided set of tags, named
// with the provided name, and aggregated and retained under the provided policies.
type rollupTarget struct {
	Name     []byte
	Tags     [][]byte
	Policies []policy.Policy
}

func newRollupTarget(target *schema.RollupTarget) (rollupTarget, error) {
	if target == nil {
		return emptyRollupTarget, errNilRollupTargetSchema
	}
	policies, err := policy.NewPoliciesFromSchema(target.Policies)
	if err != nil {
		return emptyRollupTarget, err
	}
	tags := make([]string, len(target.Tags))
	copy(tags, target.Tags)
	sort.Strings(tags)
	return rollupTarget{
		Name:     []byte(target.Name),
		Tags:     bytesArrayFromStringArray(tags),
		Policies: policies,
	}, nil
}

// sameTransform determines whether two targets have the same transformation.
func (t *rollupTarget) sameTransform(other rollupTarget) bool {
	if !bytes.Equal(t.Name, other.Name) {
		return false
	}
	if len(t.Tags) != len(other.Tags) {
		return false
	}
	for i := 0; i < len(t.Tags); i++ {
		if !bytes.Equal(t.Tags[i], other.Tags[i]) {
			return false
		}
	}
	return true
}

// clone clones a rollup target.
func (t *rollupTarget) clone() rollupTarget {
	name := make([]byte, len(t.Name))
	copy(name, t.Name)
	policies := make([]policy.Policy, len(t.Policies))
	copy(policies, t.Policies)
	return rollupTarget{
		Name:     name,
		Tags:     bytesArrayCopy(t.Tags),
		Policies: policies,
	}
}

// rollupRuleSnapshot defines a rule snapshot such that if a metric matches the
// provided filters, it is rolled up using the provided list of rollup targets.
type rollupRuleSnapshot struct {
	name       string
	tombstoned bool
	cutoverNs  int64
	filter     filters.Filter
	targets    []rollupTarget
}

func newRollupRuleSnapshot(
	r *schema.RollupRuleSnapshot,
	iterFn filters.NewSortedTagIteratorFn,
) (*rollupRuleSnapshot, error) {
	if r == nil {
		return nil, errNilRollupRuleSnapshotSchema
	}
	targets := make([]rollupTarget, 0, len(r.Targets))
	for _, t := range r.Targets {
		target, err := newRollupTarget(t)
		if err != nil {
			return nil, err
		}
		targets = append(targets, target)
	}
	filter, err := filters.NewTagsFilter(r.TagFilters, iterFn, filters.Conjunction)
	if err != nil {
		return nil, err
	}
	return &rollupRuleSnapshot{
		name:       r.Name,
		tombstoned: r.Tombstoned,
		cutoverNs:  r.CutoverTime,
		filter:     filter,
		targets:    targets,
	}, nil
}

// rollupRule stores rollup rule snapshots.
type rollupRule struct {
	uuid      string
	snapshots []*rollupRuleSnapshot
}

func newRollupRule(
	mc *schema.RollupRule,
	iterFn filters.NewSortedTagIteratorFn,
) (*rollupRule, error) {
	if mc == nil {
		return nil, errNilRollupRuleSchema
	}
	snapshots := make([]*rollupRuleSnapshot, 0, len(mc.Snapshots))
	for i := 0; i < len(mc.Snapshots); i++ {
		mr, err := newRollupRuleSnapshot(mc.Snapshots[i], iterFn)
		if err != nil {
			return nil, err
		}
		snapshots = append(snapshots, mr)
	}
	return &rollupRule{
		uuid:      mc.Uuid,
		snapshots: snapshots,
	}, nil
}

// ActiveSnapshot returns the latest rule snapshot whose cutover time is earlier
// than or equal to timeNs, or nil if not found.
func (rc *rollupRule) ActiveSnapshot(timeNs int64) *rollupRuleSnapshot {
	idx := rc.activeIndex(timeNs)
	if idx < 0 {
		return nil
	}
	return rc.snapshots[idx]
}

// ActiveRule returns the rule containing snapshots that's in effect at time timeNs
// and all future rules after time timeNs.
func (rc *rollupRule) ActiveRule(timeNs int64) *rollupRule {
	idx := rc.activeIndex(timeNs)
	if idx < 0 {
		return rc
	}
	return &rollupRule{uuid: rc.uuid, snapshots: rc.snapshots[idx:]}
}

func (rc *rollupRule) activeIndex(timeNs int64) int {
	idx := 0
	for idx < len(rc.snapshots) && rc.snapshots[idx].cutoverNs <= timeNs {
		idx++
	}
	idx--
	return idx
}

func bytesArrayFromStringArray(values []string) [][]byte {
	result := make([][]byte, len(values))
	for i, str := range values {
		result[i] = []byte(str)
	}
	return result
}

func bytesArrayCopy(values [][]byte) [][]byte {
	result := make([][]byte, len(values))
	for i, b := range values {
		result[i] = make([]byte, len(b))
		copy(result[i], b)
	}
	return result
}
<commit_msg>Search rollups backwards (#28)<commit_after>// Copyright (c) 2017 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 rules

import (
	"bytes"
	"errors"
	"sort"

	"github.com/m3db/m3metrics/filters"
	"github.com/m3db/m3metrics/generated/proto/schema"
	"github.com/m3db/m3metrics/policy"
)

var (
	emptyRollupTarget rollupTarget

	errNilRollupTargetSchema       = errors.New("nil rollup target schema")
	errNilRollupRuleSnapshotSchema = errors.New("nil rollup rule snapshot schema")
	errNilRollupRuleSchema         = errors.New("nil rollup rule schema")
)

// rollupTarget dictates how to roll up metrics. Metrics associated with a rollup
// target will be grouped and rolled up across the provided set of tags, named
// with the provided name, and aggregated and retained under the provided policies.
type rollupTarget struct {
	Name     []byte
	Tags     [][]byte
	Policies []policy.Policy
}

func newRollupTarget(target *schema.RollupTarget) (rollupTarget, error) {
	if target == nil {
		return emptyRollupTarget, errNilRollupTargetSchema
	}
	policies, err := policy.NewPoliciesFromSchema(target.Policies)
	if err != nil {
		return emptyRollupTarget, err
	}
	tags := make([]string, len(target.Tags))
	copy(tags, target.Tags)
	sort.Strings(tags)
	return rollupTarget{
		Name:     []byte(target.Name),
		Tags:     bytesArrayFromStringArray(tags),
		Policies: policies,
	}, nil
}

// sameTransform determines whether two targets have the same transformation.
func (t *rollupTarget) sameTransform(other rollupTarget) bool {
	if !bytes.Equal(t.Name, other.Name) {
		return false
	}
	if len(t.Tags) != len(other.Tags) {
		return false
	}
	for i := 0; i < len(t.Tags); i++ {
		if !bytes.Equal(t.Tags[i], other.Tags[i]) {
			return false
		}
	}
	return true
}

// clone clones a rollup target.
func (t *rollupTarget) clone() rollupTarget {
	name := make([]byte, len(t.Name))
	copy(name, t.Name)
	policies := make([]policy.Policy, len(t.Policies))
	copy(policies, t.Policies)
	return rollupTarget{
		Name:     name,
		Tags:     bytesArrayCopy(t.Tags),
		Policies: policies,
	}
}

// rollupRuleSnapshot defines a rule snapshot such that if a metric matches the
// provided filters, it is rolled up using the provided list of rollup targets.
type rollupRuleSnapshot struct {
	name       string
	tombstoned bool
	cutoverNs  int64
	filter     filters.Filter
	targets    []rollupTarget
}

func newRollupRuleSnapshot(
	r *schema.RollupRuleSnapshot,
	iterFn filters.NewSortedTagIteratorFn,
) (*rollupRuleSnapshot, error) {
	if r == nil {
		return nil, errNilRollupRuleSnapshotSchema
	}
	targets := make([]rollupTarget, 0, len(r.Targets))
	for _, t := range r.Targets {
		target, err := newRollupTarget(t)
		if err != nil {
			return nil, err
		}
		targets = append(targets, target)
	}
	filter, err := filters.NewTagsFilter(r.TagFilters, iterFn, filters.Conjunction)
	if err != nil {
		return nil, err
	}
	return &rollupRuleSnapshot{
		name:       r.Name,
		tombstoned: r.Tombstoned,
		cutoverNs:  r.CutoverTime,
		filter:     filter,
		targets:    targets,
	}, nil
}

// rollupRule stores rollup rule snapshots.
type rollupRule struct {
	uuid      string
	snapshots []*rollupRuleSnapshot
}

func newRollupRule(
	mc *schema.RollupRule,
	iterFn filters.NewSortedTagIteratorFn,
) (*rollupRule, error) {
	if mc == nil {
		return nil, errNilRollupRuleSchema
	}
	snapshots := make([]*rollupRuleSnapshot, 0, len(mc.Snapshots))
	for i := 0; i < len(mc.Snapshots); i++ {
		mr, err := newRollupRuleSnapshot(mc.Snapshots[i], iterFn)
		if err != nil {
			return nil, err
		}
		snapshots = append(snapshots, mr)
	}
	return &rollupRule{
		uuid:      mc.Uuid,
		snapshots: snapshots,
	}, nil
}

// ActiveSnapshot returns the latest rule snapshot whose cutover time is earlier
// than or equal to timeNs, or nil if not found.
func (rc *rollupRule) ActiveSnapshot(timeNs int64) *rollupRuleSnapshot {
	idx := rc.activeIndex(timeNs)
	if idx < 0 {
		return nil
	}
	return rc.snapshots[idx]
}

// ActiveRule returns the rule containing snapshots that's in effect at time timeNs
// and all future rules after time timeNs.
func (rc *rollupRule) ActiveRule(timeNs int64) *rollupRule {
	idx := rc.activeIndex(timeNs)
	if idx < 0 {
		return rc
	}
	return &rollupRule{uuid: rc.uuid, snapshots: rc.snapshots[idx:]}
}

func (rc *rollupRule) activeIndex(timeNs int64) int {
	idx := len(rc.snapshots) - 1
	for idx >= 0 && rc.snapshots[idx].cutoverNs > timeNs {
		idx--
	}
	return idx
}

func bytesArrayFromStringArray(values []string) [][]byte {
	result := make([][]byte, len(values))
	for i, str := range values {
		result[i] = []byte(str)
	}
	return result
}

func bytesArrayCopy(values [][]byte) [][]byte {
	result := make([][]byte, len(values))
	for i, b := range values {
		result[i] = make([]byte, len(b))
		copy(result[i], b)
	}
	return result
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/jriddick/geoffrey/bot"
	_ "github.com/jriddick/geoffrey/plugins"
	"github.com/natefinch/lumberjack"
	"github.com/spf13/viper"
)

func init() {
	// Output to stderr
	log.SetOutput(os.Stderr)

	// Set the log level to debug
	log.SetLevel(log.DebugLevel)

	// Set the configuration information
	viper.SetConfigName("config")
	viper.AddConfigPath(".")

	// Set the default values for configuration
	viper.SetDefault("logs.location", "logs")
	viper.SetDefault("logs.level", "INFO")
}

func main() {
	log.Infoln("[geoffrey] Running")

	// Load the configuration
	if err := viper.ReadInConfig(); err != nil {
		log.Fatalf("Could not read configuration: %s\n", err)
	}

	// Configure the logger level
	switch viper.GetString("logs.level") {
	case "DEBUG":
		log.SetLevel(log.DebugLevel)
	case "INFO":
		log.SetLevel(log.InfoLevel)
	case "WARN", "WARNING":
		log.SetLevel(log.WarnLevel)
	case "ERROR":
		log.SetLevel(log.ErrorLevel)
	case "FATAL":
		log.SetLevel(log.FatalLevel)
	case "PANIC":
		log.SetLevel(log.PanicLevel)
	default:
		log.Fatalf("[geoffrey] Tried to set log level to '%s'", viper.GetString("logs.level"))
	}

	// Configure the rotating file handler
	lumber := &lumberjack.Logger{
		Filename:   fmt.Sprintf("%s/geoffrey.log", viper.GetString("logs.location")),
		MaxSize:    viper.GetInt("logs.size"),
		MaxBackups: viper.GetInt("logs.backups"),
		MaxAge:     viper.GetInt("age"),
	}

	// Set the output to the rotating file
	log.SetOutput(lumber)

	// Set the formatting
	log.SetFormatter(&log.TextFormatter{
		DisableColors: true,
	})

	// Create the manager
	manager := bot.NewManager()

	// Get the bot configurations
	var bots []bot.Config

	// Unmarshal the bots
	if err := viper.UnmarshalKey("bots", &bots); err != nil {
		log.Fatalf("Could not read configuration: %s\n", err)
	}

	// Add all bots to the manager
	for _, config := range bots {
		if err := manager.Add(config.BotName, bot.NewBot(config)); err != nil {
			log.Fatalf("[%s] %v", config.BotName, err)
		} else {
			log.Infof("[geoffrey] Added bot '%s'", config.BotName)
		}
	}

	// Make sure we actaully have a bot registered
	if len(bots) < 1 {
		log.Fatalf("[geoffrey] You need a minimum of one configured bot")
	}

	log.Infof("[geoffrey] Started")

	// Listen and run
	if err := manager.Run(); err != nil {
		log.Fatalf("Error: %v", err)
	}
}
<commit_msg>Add rolling logger<commit_after>package main

import (
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/jriddick/geoffrey/bot"
	_ "github.com/jriddick/geoffrey/plugins"
	"github.com/spf13/viper"
)

func init() {
	// Output to stderr
	log.SetOutput(os.Stderr)

	// Set the log level to debug
	log.SetLevel(log.DebugLevel)

	// Set the configuration information
	viper.SetConfigName("config")
	viper.AddConfigPath(".")

	// Set the default values for configuration
	viper.SetDefault("logs.location", "logs")
	viper.SetDefault("logs.level", "INFO")
}

func main() {
	log.Infoln("[geoffrey] Running")

	// Load the configuration
	if err := viper.ReadInConfig(); err != nil {
		log.Fatalf("Could not read configuration: %s\n", err)
	}

	// Configure the logger level
	switch viper.GetString("logs.level") {
	case "DEBUG":
		log.SetLevel(log.DebugLevel)
	case "INFO":
		log.SetLevel(log.InfoLevel)
	case "WARN", "WARNING":
		log.SetLevel(log.WarnLevel)
	case "ERROR":
		log.SetLevel(log.ErrorLevel)
	case "FATAL":
		log.SetLevel(log.FatalLevel)
	case "PANIC":
		log.SetLevel(log.PanicLevel)
	default:
		log.Fatalf("[geoffrey] Tried to set log level to '%s'", viper.GetString("logs.level"))
	}

	// Create the manager
	manager := bot.NewManager()

	// Get the bot configurations
	var bots []bot.Config

	// Unmarshal the bots
	if err := viper.UnmarshalKey("bots", &bots); err != nil {
		log.Fatalf("Could not read configuration: %s\n", err)
	}

	// Add all bots to the manager
	for _, config := range bots {
		if err := manager.Add(config.BotName, bot.NewBot(config)); err != nil {
			log.Fatalf("[%s] %v", config.BotName, err)
		} else {
			log.Infof("[geoffrey] Added bot '%s'", config.BotName)
		}
	}

	// Make sure we actaully have a bot registered
	if len(bots) < 1 {
		log.Fatalf("[geoffrey] You need a minimum of one configured bot")
	}

	log.Infof("[geoffrey] Started")

	// Listen and run
	if err := manager.Run(); err != nil {
		log.Fatalf("Error: %v", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"
	"time"
)

type SiteMap []Sitemap
type Sitemap struct {
	Loc        string
	Date       time.Time
	ChangeFreq string
	Priority   float64
}

func (sm Sitemap) LastMod() string {
	if sm.Date.IsZero() {
		return ""
	}
	return sm.Date.Local().Format("2006-02-01")
}

func sitemapHandler(w http.ResponseWriter, r *http.Request) {
	var sm SiteMap
	articles := art.Enabled()
	sm = append(sm, Sitemap{
		Loc:        "http://" + r.Host,
		Priority:   1.0,
		Date:       articles[0].Date,
		ChangeFreq: "daily",
	})
	for _, a := range articles {
		sm = append(sm, Sitemap{
			Loc:        "http://" + r.Host + "/" + a.Slug,
			Priority:   0.8,
			Date:       a.Date,
			ChangeFreq: "monthly",
		})
	}
	for _, t := range art.TagCloud() {
		tagged := articles.Tag(t.Tag)
		sm = append(sm, Sitemap{
			Loc:        "http://" + r.Host + "/tag/" + t.Tag,
			Priority:   0.6 - float64(t.Wight)/10,
			Date:       tagged[0].Date,
			ChangeFreq: "weekly",
		})
	}
	err := tmpl.ExecuteTemplate(w, "sitemap.tmpl", sm)
	if err != nil {
		log.Println(err)
	}
}
<commit_msg>Make clear it's a slice<commit_after>package main

import (
	"log"
	"net/http"
	"time"
)

type SiteMap []Sitemap
type Sitemap struct {
	Loc        string
	Date       time.Time
	ChangeFreq string
	Priority   float64
}

func (sm Sitemap) LastMod() string {
	if sm.Date.IsZero() {
		return ""
	}
	return sm.Date.Local().Format("2006-02-01")
}

func sitemapHandler(w http.ResponseWriter, r *http.Request) {
	var sm []Sitemap
	articles := art.Enabled()
	sm = append(sm, Sitemap{
		Loc:        "http://" + r.Host,
		Priority:   1.0,
		Date:       articles[0].Date,
		ChangeFreq: "daily",
	})
	for _, a := range articles {
		sm = append(sm, Sitemap{
			Loc:        "http://" + r.Host + "/" + a.Slug,
			Priority:   0.8,
			Date:       a.Date,
			ChangeFreq: "monthly",
		})
	}
	for _, t := range art.TagCloud() {
		tagged := articles.Tag(t.Tag)
		sm = append(sm, Sitemap{
			Loc:        "http://" + r.Host + "/tag/" + t.Tag,
			Priority:   0.6 - float64(t.Wight)/10,
			Date:       tagged[0].Date,
			ChangeFreq: "weekly",
		})
	}
	err := tmpl.ExecuteTemplate(w, "sitemap.tmpl", sm)
	if err != nil {
		log.Println(err)
	}
}
<|endoftext|>


<commit_before>package hitGox

import (
	"bytes"
	"encoding/json"
	"github.com/valyala/fasthttp"
)

type AuthToken struct {
	AuthToken string `json:"authToken,omitempty"`
}

// GetToken get an authentication authToken rather than account information.
func GetToken(login string, pass string, app Application) (AuthToken, error) {
	args := fasthttp.AcquireArgs()
	args.Add("login", login)
	args.Add("pass", pass)
	args.Add("app", app.Name)
	statusCode, body, err := fasthttp.Post(nil, API+"/auth/token", args)
	if statusCode != 200 || err != nil {
		return AuthToken{}, err
	}
	var obj AuthToken
	if err = json.NewDecoder(bytes.NewReader(body)).Decode(&obj); err != nil {
		return AuthToken{}, err
	}
	return obj, nil
}
<commit_msg>✅ Approved getToken<commit_after>package hitGox

import (
	"bytes"
	"encoding/json"
	"errors"
	"github.com/valyala/fasthttp"
)

// AuthToken is about generated key for most actions by user.
type AuthToken struct {
	AuthToken string `json:"authToken"`
}

// GetToken can be used alternatively to just get an authentication token rather than account information.
func (app *Application) GetToken(login string, pass string) (*AuthToken, error) {
	switch {
	case app.Name == "":
		return nil, errors.New("no name of application, create new application first")
	case login == "":
		return nil, errors.New("login can not be empty")
	case pass == "":
		return nil, errors.New("pass can not be empty")
	}

	var args fasthttp.Args
	args.Add("login", login)
	args.Add("pass", pass)
	args.Add("app", app.Name)

	url := APIEndpoint + "/auth/token"
	_, resp, err := fasthttp.Post(nil, url, &args)
	if err != nil {
		return nil, err
	}

	var obj AuthToken
	if err = json.NewDecoder(bytes.NewReader(resp)).Decode(&obj); err != nil {
		return nil, err
	}

	return &obj, nil
}
<|endoftext|>


<commit_before>package getter

import (
	"net/url"
	"os"
)

// FileGetter is a Getter implementation that will download a module from
// a file scheme.
type FileGetter struct {
	getter

	// Copy, if set to true, will copy data instead of using a symlink
	Copy bool
}

func (g *FileGetter) ClientMode(u *url.URL) (ClientMode, error) {
	path := u.Path
	if u.RawPath != "" {
		path = u.RawPath
	}

	fi, err := os.Stat(path)
	if err != nil {
		return 0, err
	}

	// Check if the source is a directory.
	if fi.IsDir() {
		return ClientModeDir, nil
	}

	return ClientModeFile, nil
}
<commit_msg>Document FileGetter.Copy with new behaviour<commit_after>package getter

import (
	"net/url"
	"os"
)

// FileGetter is a Getter implementation that will download a module from
// a file scheme.
type FileGetter struct {
	getter

	// Copy, if set to true, will copy data instead of using a symlink. If
	// false, attempts to symlink to speed up the operation and to lower the
	// disk space usage. If the symlink fails, may attempt to copy on windows.
	Copy bool
}

func (g *FileGetter) ClientMode(u *url.URL) (ClientMode, error) {
	path := u.Path
	if u.RawPath != "" {
		path = u.RawPath
	}

	fi, err := os.Stat(path)
	if err != nil {
		return 0, err
	}

	// Check if the source is a directory.
	if fi.IsDir() {
		return ClientModeDir, nil
	}

	return ClientModeFile, nil
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package kvdbsync

import (
	"errors"
	"github.com/golang/protobuf/proto"
	"github.com/ligato/cn-infra/datasync"
	"github.com/ligato/cn-infra/datasync/resync"
	"github.com/ligato/cn-infra/datasync/syncbase"
	"github.com/ligato/cn-infra/db/keyval"
	"github.com/ligato/cn-infra/flavors/localdeps"
)

// Plugin dbsync implements Plugin interface
type Plugin struct {
	Deps    // inject
	adapter *watcher
}

// Deps is here to group injected dependencies of plugin
// to not mix with other plugin fields.
type Deps struct {
	localdeps.PluginInfraDeps                      // inject
	ResyncOrch                resync.Subscriber    // inject
	KvPlugin                  keyval.KvProtoPlugin // inject
}

// Init does nothing
func (plugin *Plugin) Init() error {
	return nil
}

// AfterInit uses provided connection to build new transport watcher
func (plugin *Plugin) AfterInit() error {
	if plugin.KvPlugin != nil && !plugin.KvPlugin.Disabled() {
		db := plugin.KvPlugin.NewBroker(plugin.ServiceLabel.GetAgentPrefix())
		dbW := plugin.KvPlugin.NewWatcher(plugin.ServiceLabel.GetAgentPrefix())

		plugin.adapter = &watcher{db, dbW, syncbase.NewWatcher()}
	}

	return nil
}

// Watch using ETCD or any other Key Val data store.
func (plugin *Plugin) Watch(resyncName string, changeChan chan datasync.ChangeEvent,
	resyncChan chan datasync.ResyncEvent, keyPrefixes ...string) (datasync.WatchRegistration, error) {

	if plugin.KvPlugin.Disabled() {
		return nil/*TODO*/, nil
	}

	if plugin.adapter == nil {
		return errors.New("Transport adapter is not ready yet")
	}

	reg, err := plugin.adapter.base.Watch(resyncName, changeChan, resyncChan, keyPrefixes...)
	if err != nil {
		return nil, err
	}

	resyncReg := plugin.ResyncOrch.Register(resyncName)
	_, err = watchAndResyncBrokerKeys(resyncReg, changeChan, resyncChan, plugin.adapter, keyPrefixes...)
	if err != nil {
		return nil, err
	}

	return reg, err
}

// Put to ETCD or any other data transport (from other Agent Plugins)
func (plugin *Plugin) Put(key string, data proto.Message, opts ...datasync.PutOption) error {
	if plugin.KvPlugin.Disabled() {
		return nil
	}

	if plugin.adapter != nil {
 		return plugin.adapter.db.Put(key, data, opts...)
 	}

	return errors.New("Transport adapter is not ready yet")
}

// Close resources
func (plugin *Plugin) Close() error {
	return nil
}

// String returns if set Deps.PluginName or "kvdbsync" otherwise
func (plugin *Plugin) String() string {
	if len(plugin.PluginName) == 0 {
		return "kvdbsync"
	}
	return string(plugin.PluginName)
}
<commit_msg>fix potential nil pointer in kvdbsync Watch()<commit_after>// Copyright (c) 2017 Cisco and/or its affiliates.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package kvdbsync

import (
	"errors"
	"github.com/golang/protobuf/proto"
	"github.com/ligato/cn-infra/datasync"
	"github.com/ligato/cn-infra/datasync/resync"
	"github.com/ligato/cn-infra/datasync/syncbase"
	"github.com/ligato/cn-infra/db/keyval"
	"github.com/ligato/cn-infra/flavors/localdeps"
)

// Plugin dbsync implements Plugin interface
type Plugin struct {
	Deps    // inject
	adapter *watcher
}

// Deps is here to group injected dependencies of plugin
// to not mix with other plugin fields.
type Deps struct {
	localdeps.PluginInfraDeps                      // inject
	ResyncOrch                resync.Subscriber    // inject
	KvPlugin                  keyval.KvProtoPlugin // inject
}

// Init does nothing
func (plugin *Plugin) Init() error {
	return nil
}

// AfterInit uses provided connection to build new transport watcher
func (plugin *Plugin) AfterInit() error {
	if plugin.KvPlugin != nil && !plugin.KvPlugin.Disabled() {
		db := plugin.KvPlugin.NewBroker(plugin.ServiceLabel.GetAgentPrefix())
		dbW := plugin.KvPlugin.NewWatcher(plugin.ServiceLabel.GetAgentPrefix())

		plugin.adapter = &watcher{db, dbW, syncbase.NewWatcher()}
	}

	return nil
}

// Watch using ETCD or any other Key Val data store.
func (plugin *Plugin) Watch(resyncName string, changeChan chan datasync.ChangeEvent,
	resyncChan chan datasync.ResyncEvent, keyPrefixes ...string) (datasync.WatchRegistration, error) {

	if plugin.KvPlugin.Disabled() {
		return nil/*TODO*/, nil
	}

	if plugin.adapter == nil {
		return nil, errors.New("Transport adapter is not ready yet")
	}

	reg, err := plugin.adapter.base.Watch(resyncName, changeChan, resyncChan, keyPrefixes...)
	if err != nil {
		return nil, err
	}

	resyncReg := plugin.ResyncOrch.Register(resyncName)
	_, err = watchAndResyncBrokerKeys(resyncReg, changeChan, resyncChan, plugin.adapter, keyPrefixes...)
	if err != nil {
		return nil, err
	}

	return reg, err
}

// Put to ETCD or any other data transport (from other Agent Plugins)
func (plugin *Plugin) Put(key string, data proto.Message, opts ...datasync.PutOption) error {
	if plugin.KvPlugin.Disabled() {
		return nil
	}

	if plugin.adapter != nil {
 		return plugin.adapter.db.Put(key, data, opts...)
 	}

	return errors.New("Transport adapter is not ready yet")
}

// Close resources
func (plugin *Plugin) Close() error {
	return nil
}

// String returns if set Deps.PluginName or "kvdbsync" otherwise
func (plugin *Plugin) String() string {
	if len(plugin.PluginName) == 0 {
		return "kvdbsync"
	}
	return string(plugin.PluginName)
}
<|endoftext|>


<commit_before>/*
 The MIT License (MIT)

Copyright (c) 2013 Tal Sliwowicz

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 main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/user"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

type HostGetter struct {
	DownloadLocation *string
	CacheLocation    *string
	User             *string
	Password         *string
	CacheFileName    *string
	HostPattern      *string
	HostPrefix       string
	CacheDuration    *time.Duration
}

type HostData struct {
	Name string
}
type Host struct {
	Host HostData
}

func (self *HostGetter) downloadHosts() ([]byte, error) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest("GET", *self.DownloadLocation, nil)
	if err != nil {
		log.Printf("could not create new http request for %s", self.DownloadLocation)
		return nil, err
	}
	req.SetBasicAuth(*self.User, *self.Password)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")
	res, err := client.Do(req)
	if err != nil {
		log.Printf("could not open http connection to download config from %s", *self.DownloadLocation)
		return nil, err
	}

	data, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()
	if err != nil {
		log.Printf("could not download config from %s", self.DownloadLocation)
		return nil, err
	}
	return data, nil
}

func (self *HostGetter) getHosts() (rt string, err error) {
	cacheLoc := filepath.Join(*self.CacheLocation, *self.CacheFileName)
	fi, err := os.Stat(cacheLoc)
	if err != nil {
		log.Printf("no file in cache, downloading %s (%v)", cacheLoc, err)
	} else if !time.Now().After(fi.ModTime().Add(*self.CacheDuration)) {
		log.Printf("found file in cache")
		var data []byte
		data, err = ioutil.ReadFile(cacheLoc)
		if err != nil {
			log.Printf("corrupt file in cache, downloading %s (%v)", cacheLoc, err)
		} else {
			rt = string(data)
			return
		}
	}

	rt, err = self.downloadParseHosts()
	if err == nil {
		log.Printf("downloaded and parsed - trying to save to cache")
		errd := os.MkdirAll(*self.CacheLocation, os.ModePerm)
		if errd != nil {
			log.Printf("could not create cache dir %s (%v)", *self.CacheLocation, errd)
			return
		}
		errf := ioutil.WriteFile(cacheLoc, []byte(rt), os.ModePerm)
		if errf != nil {
			log.Printf("downloaded and parsed ok, could not save to cache %v", errf)
		}
	} else {
		log.Printf("could not get hosts", err)
	}

	return
}

func (self *HostGetter) downloadParseHosts() (rt string, err error) {
	var data []byte
	var hosts []Host

	data, err = self.downloadHosts()
	if err != nil {
		log.Printf("failed to download")
		return
	}
	hosts, err = self.parse(data)
	if err != nil {
		log.Printf("could not parse")
		return
	}
	var buffer bytes.Buffer
	for _, host := range hosts {
		buffer.WriteString(host.Host.Name + "\n")
	}
	rt = buffer.String()
	return
}

func (self *HostGetter) parse(data []byte) (hosts []Host, err error) {
	err = json.Unmarshal(data, &hosts)
	if err != nil {
		log.Print("error:", err)
	}
	return
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	log.SetOutput(os.Stderr)

	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}

	getter := HostGetter{
		DownloadLocation: flag.String("url", "https://<forman-host>/hosts", "url to use"),
		CacheLocation:    flag.String("cachedir", filepath.Join(usr.HomeDir, ".gethosts"), "url to use"),
		CacheFileName:    flag.String("cachefile", "hostslist.txt", "url to use"),
		User:             flag.String("user", "", "user name for authentication"),
		Password:         flag.String("password", "", "password"),
		CacheDuration:    flag.Duration("cacheduration", time.Hour, "cache duration before trying to refresh")}

	flag.Parse() // Scan the arguments list

	if len(flag.Args()) > 0 {
		patt := flag.Arg(0)
		i := strings.Index(patt, "@")
		if i != -1 {
			getter.HostPrefix = patt[:i+1]
			patt = patt[i+1:]
		}
		getter.HostPattern = &patt
		log.Printf("requesting pattern %s, for prefix %s", patt, getter.HostPrefix)
	}

	hosts, err := getter.getHosts()
	if err != nil {
		log.Fatal("failed to download hosts")
	}

	if getter.HostPattern != nil {
		hostArr := strings.Split(hosts, "\n")

		for _, line := range hostArr {
			if strings.HasPrefix(line, *getter.HostPattern) {
				fmt.Fprintln(os.Stdout, getter.HostPrefix+line)
			}
		}
	} else {

		fmt.Fprintln(os.Stdout, hosts)
	}
}
<commit_msg>added a log message<commit_after>/*
 The MIT License (MIT)

Copyright (c) 2013 Tal Sliwowicz

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 main

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/user"
	"path/filepath"
	"runtime"
	"strings"
	"time"
)

type HostGetter struct {
	DownloadLocation *string
	CacheLocation    *string
	User             *string
	Password         *string
	CacheFileName    *string
	HostPattern      *string
	HostPrefix       string
	CacheDuration    *time.Duration
}

type HostData struct {
	Name string
}
type Host struct {
	Host HostData
}

func (self *HostGetter) downloadHosts() ([]byte, error) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client := &http.Client{Transport: tr}
	req, err := http.NewRequest("GET", *self.DownloadLocation, nil)
	if err != nil {
		log.Printf("could not create new http request for %s", self.DownloadLocation)
		return nil, err
	}
	req.SetBasicAuth(*self.User, *self.Password)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Accept", "application/json")
	res, err := client.Do(req)
	if err != nil {
		log.Printf("could not open http connection to download config from %s", *self.DownloadLocation)
		return nil, err
	}

	data, err := ioutil.ReadAll(res.Body)
	defer res.Body.Close()
	if err != nil {
		log.Printf("could not download config from %s", self.DownloadLocation)
		return nil, err
	}
	return data, nil
}

func (self *HostGetter) getHosts() (rt string, err error) {
	cacheLoc := filepath.Join(*self.CacheLocation, *self.CacheFileName)
	fi, err := os.Stat(cacheLoc)
	if err != nil {
		log.Printf("no file in cache, downloading %s (%v)", cacheLoc, err)
	} else if !time.Now().After(fi.ModTime().Add(*self.CacheDuration)) {
		log.Printf("found file in cache")
		var data []byte
		data, err = ioutil.ReadFile(cacheLoc)
		if err != nil {
			log.Printf("corrupt file in cache, downloading %s (%v)", cacheLoc, err)
		} else {
			rt = string(data)
			return
		}
	}

	rt, err = self.downloadParseHosts()
	if err == nil {
		log.Printf("downloaded and parsed - trying to save to cache")
		errd := os.MkdirAll(*self.CacheLocation, os.ModePerm)
		if errd != nil {
			log.Printf("could not create cache dir %s (%v)", *self.CacheLocation, errd)
			return
		}
		errf := ioutil.WriteFile(cacheLoc, []byte(rt), os.ModePerm)
		if errf != nil {
			log.Printf("downloaded and parsed ok, could not save to cache %v", errf)
		} else {
			log.Printf("saved hosts in cache")
		}
	} else {
		log.Printf("could not get hosts", err)
	}

	return
}

func (self *HostGetter) downloadParseHosts() (rt string, err error) {
	var data []byte
	var hosts []Host

	data, err = self.downloadHosts()
	if err != nil {
		log.Printf("failed to download")
		return
	}
	hosts, err = self.parse(data)
	if err != nil {
		log.Printf("could not parse")
		return
	}
	var buffer bytes.Buffer
	for _, host := range hosts {
		buffer.WriteString(host.Host.Name + "\n")
	}
	rt = buffer.String()
	return
}

func (self *HostGetter) parse(data []byte) (hosts []Host, err error) {
	err = json.Unmarshal(data, &hosts)
	if err != nil {
		log.Print("error:", err)
	}
	return
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	log.SetOutput(os.Stderr)

	usr, err := user.Current()
	if err != nil {
		log.Fatal(err)
	}

	getter := HostGetter{
		DownloadLocation: flag.String("url", "https://<forman-host>/hosts", "url to use"),
		CacheLocation:    flag.String("cachedir", filepath.Join(usr.HomeDir, ".gethosts"), "url to use"),
		CacheFileName:    flag.String("cachefile", "hostslist.txt", "url to use"),
		User:             flag.String("user", "", "user name for authentication"),
		Password:         flag.String("password", "", "password"),
		CacheDuration:    flag.Duration("cacheduration", time.Hour, "cache duration before trying to refresh")}

	flag.Parse() // Scan the arguments list

	if len(flag.Args()) > 0 {
		patt := flag.Arg(0)
		i := strings.Index(patt, "@")
		if i != -1 {
			getter.HostPrefix = patt[:i+1]
			patt = patt[i+1:]
		}
		getter.HostPattern = &patt
		log.Printf("requesting pattern %s, for prefix %s", patt, getter.HostPrefix)
	}

	hosts, err := getter.getHosts()
	if err != nil {
		log.Fatal("failed to download hosts")
	}

	if getter.HostPattern != nil {
		hostArr := strings.Split(hosts, "\n")

		for _, line := range hostArr {
			if strings.HasPrefix(line, *getter.HostPattern) {
				fmt.Fprintln(os.Stdout, getter.HostPrefix+line)
			}
		}
	} else {

		fmt.Fprintln(os.Stdout, hosts)
	}
}
<|endoftext|>


<commit_before>package schedule

import (
	"fmt"
	"io/ioutil"

	"github.com/headmade/backuper/backuper"
)

type Manager struct {
}

func New() (Manager, error) {
	return Manager{}, nil
}

func (m *Manager) UpdateBackup(period backuper.Period) error {
	return m.writeCrontab(periodToStr(&period), "backup")
}

func (m *Manager) UpdateCheck() error {
	return m.writeCrontab("* * * * *", "check")
}

func periodToStr(period *backuper.Period) string {
	str := "* * * * *"
	return str
}

func (m *Manager) writeCrontab(schedule string, cmd string) error {
	task := fmt.Sprintf("%s root /usr/local/bin/gobackuper %s >> /var/log/gobackuper_cron.log 2>&1\n\n", schedule, cmd)
	//return ioutil.WriteFile("/etc/cron.d/backuper_"+cmd, []byte(task), 0600)
	return ioutil.WriteFile("/tmp/gobackuper_check", []byte(task), 0600)
}
<commit_msg>Add crontab generation<commit_after>package schedule

import (
	"fmt"
//	"strconv"

	"github.com/headmade/backuper/backuper"
	"github.com/headmade/backuper/hmutil"
)

const (
	GOTRACEBACK = 1
	CRON_PATH = "PATH=/bin:/usr/bin:/usr/local/bin:$PATH"
)

var CRON_GOTRACEBACK = "" //"CRON_GOTRACEBACK=" + strconv.Itoa(GOTRACEBACK_LEVEL)

type Manager struct {
}

func New() (Manager, error) {
	return Manager{}, nil
}

func (m *Manager) UpdateBackup(period backuper.Period) error {
	return m.writeCrontab(periodToStr(&period), "backup")
}

func (m *Manager) UpdateCheck() error {
	return m.writeCrontab("* * * * *", "check")
}

func periodToStr(period *backuper.Period) string {
	str := "* * * * *"
	return str
}

func (m *Manager) writeCrontab(schedule string, cmd string) error {
	taskFormat := `crontab -l\
		| ( grep -v 'gobackuper %s' ; echo '%s %s %s gobackuper %s >> /var/log/gobackuper_cron.log 2>&1' )\
		| crontab`
	task := fmt.Sprintf(taskFormat, cmd, schedule, CRON_PATH, CRON_GOTRACEBACK, cmd)
	_, err := hmutil.System(task)
	return err
}
<|endoftext|>


<commit_before>package git

import (
	"bytes"
	"fmt"
	"sort"
	"strconv"
	"strings"

	"github.com/yosisa/go-git/lru"
)

var scratchbuf = new(bytes.Buffer)

type Tree struct {
	id      SHA1
	repo    *Repository
	Entries []*TreeEntry
	dirty   bool
}

func newTree(id SHA1, repo *Repository) *Tree {
	return &Tree{
		id:   id,
		repo: repo,
	}
}

func (t *Tree) SHA1() SHA1 {
	return t.id
}

func (t *Tree) Parse(data []byte) error {
	var mode, name, id, rest []byte
	var pos int
	for len(data) > 0 {
		if pos = bytes.IndexByte(data, ' '); pos == -1 {
			return ErrUnknownFormat
		}
		mode, rest = data[:pos], data[pos+1:]

		if pos = bytes.IndexByte(rest, 0); pos == -1 {
			return ErrUnknownFormat
		}
		name, id, rest = rest[:pos], rest[pos+1:pos+21], rest[pos+21:]

		last := len(mode) + len(name) + 22
		entry, err := newTreeEntry(mode, name, id, data[:last], t.repo)
		if err != nil {
			return err
		}
		t.Entries = append(t.Entries, entry)
		data = rest
	}
	return nil
}

func (t *Tree) Resolve() error {
	return t.repo.Resolve(t)
}

func (t *Tree) Resolved() bool {
	return t.Entries != nil
}

func (t *Tree) Find(path string) (*SparseObject, TreeEntryMode, error) {
	parts := splitPath(path)
	tree := t
	var i int
	for ; i < len(parts); i++ {
		if !tree.Resolved() {
			break
		}
		_, entry := tree.findEntry(parts[i])
		if entry == nil {
			return nil, 0, ErrObjectNotFound
		}
		if i == len(parts)-1 {
			return entry.Object, entry.Mode, nil
		}
		if entry.Object.obj == nil {
			tree = t.repo.NewTree()
			tree.id = entry.Object.SHA1
			continue
		}
		subtree, ok := entry.Object.obj.(*Tree)
		if !ok {
			return nil, 0, ErrObjectNotFound
		}
		tree = subtree
	}
	return tree.fastFind(parts[i:])
}

func (t *Tree) fastFind(parts []string) (*SparseObject, TreeEntryMode, error) {
	id := t.id
	mode := ModeTree
	for _, name := range parts {
		if mode != ModeTree {
			return nil, 0, ErrObjectNotFound
		}
		entry, err := t.repo.entry(id)
		if err != nil {
			return nil, 0, err
		}
		defer entry.Close()

		if entry.Type() != "tree" {
			return nil, 0, ErrObjectNotFound
		}
		data, err := entry.ReadAll()
		if err != nil {
			return nil, 0, err
		}
		id, mode, err = findTreeEntryBytes(data, name)
		if err != nil {
			return nil, 0, err
		}
	}
	return newSparseObject(id, t.repo), mode, nil
}

func findTreeEntryBytes(data []byte, name string) (id SHA1, mode TreeEntryMode, err error) {
	scratchbuf.Reset()
	scratchbuf.WriteString(name)
	scratchbuf.WriteByte(0)
	term := scratchbuf.Bytes()
	for len(data) > 0 {
		var i int
		if data[5] == ' ' {
			i = 5
		} else if data[6] == ' ' {
			i = 6
		} else {
			return id, 0, ErrUnknownFormat
		}
		if mode, err = parseMode(data[:i]); err != nil {
			return
		}
		data = data[i+1:]

		n := len(term)
		if len(data) < n {
			break
		}
		if data[n-1] == 0 && bytes.Equal(data[:n], term) {
			return SHA1FromBytes(data[n : n+20]), mode, nil
		}
		i = bytes.IndexByte(data, 0)
		if i < 0 {
			return id, 0, ErrUnknownFormat
		}
		data = data[i+21:]
	}
	return id, 0, ErrObjectNotFound
}

func (t *Tree) Add(path string, obj Object, mode TreeEntryMode) error {
	dir, name := splitDirBase(path)
	tree, err := t.getSubTree(dir, true)
	if err != nil {
		return err
	}
	tree.addEntry(name, obj, mode)
	return nil
}

func (t *Tree) addEntry(name string, obj Object, mode TreeEntryMode) {
	t.dirty = true
	newEntry := &TreeEntry{
		Mode:   mode,
		Name:   name,
		Object: &SparseObject{repo: t.repo, obj: obj},
	}
	if i, entry := t.findEntry(name); entry != nil {
		// Must not modify the entry directly because it's cached
		t.Entries[i] = newEntry
		return
	}
	t.Entries = append(t.Entries, newEntry)
}

func (t *Tree) Remove(path string) error {
	dir, name := splitDirBase(path)
	tree, err := t.getSubTree(dir, false)
	if err != nil {
		if err == ErrObjectNotFound {
			return nil
		}
		return err
	}
	tree.removeEntry(name)
	return nil
}

func (t *Tree) removeEntry(name string) {
	if i, entry := t.findEntry(name); entry != nil {
		copy(t.Entries[i:], t.Entries[i+1:])
		t.Entries = t.Entries[:len(t.Entries)-1]
		t.dirty = true
		return
	}
}

func (t *Tree) getSubTree(parts []string, create bool) (*Tree, error) {
	if err := t.Resolve(); err != nil {
		return nil, err
	}
	tree := t
	var i int
	for ; i < len(parts); i++ {
		_, entry := tree.findEntry(parts[i])
		if entry == nil {
			break
		}
		obj, err := entry.Object.Resolve()
		if err != nil {
			return nil, err
		}
		subtree, ok := obj.(*Tree)
		if !ok {
			break
		}
		tree = subtree
	}
	if i == len(parts) {
		return tree, nil
	}
	if !create {
		return nil, ErrObjectNotFound
	}
	return tree.makeSubTrees(parts[i:]), nil
}

func (t *Tree) makeSubTrees(parts []string) *Tree {
	tree := t
	for _, name := range parts {
		newTree := t.repo.NewTree()
		tree.addEntry(name, newTree, ModeTree)
		tree = newTree
	}
	return tree
}

func (t *Tree) findEntry(name string) (int, *TreeEntry) {
	for i, entry := range t.Entries {
		if entry.Name == name {
			return i, entry
		}
	}
	return 0, nil
}

func (t *Tree) Write() error {
	_, err := t.write()
	return err
}

// write walks subtrees to check and save dirty objects recursively. To save
// entire tree correctly, it's necessary to save objects from leaf to root. If
// something changed in subtrees, the parent tree also need to be saved.
func (t *Tree) write() (bool, error) {
	for _, entry := range t.Entries {
		// It's safe to ignore unresolved objects because it's stored in
		// the repository and not modified.
		if entry.Object.obj == nil {
			continue
		}
		if subtree, ok := entry.Object.obj.(*Tree); ok {
			if changed, err := subtree.write(); err != nil {
				return false, err
			} else if changed {
				t.dirty = true
			}
		} else if entry.SHA1().Empty() {
			if err := entry.Object.obj.Write(); err != nil {
				return false, err
			}
			t.dirty = true
		}
	}
	if !t.dirty {
		return false, nil
	}

	sort.Sort(ByName(t.Entries))
	b := new(bytes.Buffer)
	for _, entry := range t.Entries {
		if entry.Object.obj != nil {
			if subtree, ok := entry.Object.obj.(*Tree); ok && len(subtree.Entries) == 0 {
				continue // No need to write empty tree object
			}
		}
		fmt.Fprintf(b, "%s %s%c", entry.Mode, entry.Name, 0)
		b.Write(entry.SHA1().Bytes())
	}
	id, err := t.repo.writeObject("tree", bytes.NewReader(b.Bytes()))
	if err != nil {
		return false, err
	}
	t.id = id
	t.dirty = false
	return true, nil
}

var treeEntryCache = lru.New(1 << 16)

type TreeEntry struct {
	Mode   TreeEntryMode
	Name   string
	Object *SparseObject
}

func newTreeEntry(mode, name, id, row []byte, repo *Repository) (*TreeEntry, error) {
	key := string(row)
	if entry, ok := treeEntryCache.Get(key); ok {
		return entry.(*TreeEntry), nil
	}
	m, err := parseMode(mode)
	if err != nil {
		return nil, err
	}
	entry := &TreeEntry{
		Mode:   m,
		Name:   string(name),
		Object: newSparseObject(SHA1FromBytes(id), repo),
	}
	treeEntryCache.Add(key, entry)
	return entry, nil
}

func (t *TreeEntry) Size() int {
	return 8 + len(t.Name)
}

func (t *TreeEntry) canonicalName() string {
	if t.Mode&ModeTree != 0 {
		return t.Name + "/"
	}
	return t.Name
}

func (t *TreeEntry) SHA1() SHA1 {
	if t.Object.obj != nil {
		return t.Object.obj.SHA1()
	}
	return t.Object.SHA1
}

type TreeEntryMode uint32

const (
	ModeTree    TreeEntryMode = 0040000
	ModeFile                  = 0100644
	ModeFileEx                = 0100755
	ModeSymlink               = 0120000
)

func parseMode(bs []byte) (TreeEntryMode, error) {
	var mode TreeEntryMode
	for _, b := range bs {
		n := b - 0x30
		if n < 0 || n > 7 {
			return 0, fmt.Errorf("%d not in octal range", n)
		}
		mode = mode<<3 | TreeEntryMode(n)
	}
	return mode, nil
}

func (m TreeEntryMode) String() string {
	var s string
	for m > 0 {
		n := int(m & 0x7)
		s = strconv.Itoa(n) + s
		m = m >> 3
	}
	return s
}

func splitPath(path string) []string {
	return strings.Split(strings.Trim(path, "/"), "/")
}

func splitDirBase(path string) ([]string, string) {
	s := splitPath(path)
	return s[:len(s)-1], s[len(s)-1]
}

func (r *Repository) NewTree() *Tree {
	return &Tree{repo: r}
}

type ByName []*TreeEntry

func (z ByName) Len() int           { return len(z) }
func (z ByName) Swap(i, j int)      { z[i], z[j] = z[j], z[i] }
func (z ByName) Less(i, j int) bool { return z[i].canonicalName() < z[j].canonicalName() }
<commit_msg>Fix type of mode constants<commit_after>package git

import (
	"bytes"
	"fmt"
	"sort"
	"strconv"
	"strings"

	"github.com/yosisa/go-git/lru"
)

var scratchbuf = new(bytes.Buffer)

type Tree struct {
	id      SHA1
	repo    *Repository
	Entries []*TreeEntry
	dirty   bool
}

func newTree(id SHA1, repo *Repository) *Tree {
	return &Tree{
		id:   id,
		repo: repo,
	}
}

func (t *Tree) SHA1() SHA1 {
	return t.id
}

func (t *Tree) Parse(data []byte) error {
	var mode, name, id, rest []byte
	var pos int
	for len(data) > 0 {
		if pos = bytes.IndexByte(data, ' '); pos == -1 {
			return ErrUnknownFormat
		}
		mode, rest = data[:pos], data[pos+1:]

		if pos = bytes.IndexByte(rest, 0); pos == -1 {
			return ErrUnknownFormat
		}
		name, id, rest = rest[:pos], rest[pos+1:pos+21], rest[pos+21:]

		last := len(mode) + len(name) + 22
		entry, err := newTreeEntry(mode, name, id, data[:last], t.repo)
		if err != nil {
			return err
		}
		t.Entries = append(t.Entries, entry)
		data = rest
	}
	return nil
}

func (t *Tree) Resolve() error {
	return t.repo.Resolve(t)
}

func (t *Tree) Resolved() bool {
	return t.Entries != nil
}

func (t *Tree) Find(path string) (*SparseObject, TreeEntryMode, error) {
	parts := splitPath(path)
	tree := t
	var i int
	for ; i < len(parts); i++ {
		if !tree.Resolved() {
			break
		}
		_, entry := tree.findEntry(parts[i])
		if entry == nil {
			return nil, 0, ErrObjectNotFound
		}
		if i == len(parts)-1 {
			return entry.Object, entry.Mode, nil
		}
		if entry.Object.obj == nil {
			tree = t.repo.NewTree()
			tree.id = entry.Object.SHA1
			continue
		}
		subtree, ok := entry.Object.obj.(*Tree)
		if !ok {
			return nil, 0, ErrObjectNotFound
		}
		tree = subtree
	}
	return tree.fastFind(parts[i:])
}

func (t *Tree) fastFind(parts []string) (*SparseObject, TreeEntryMode, error) {
	id := t.id
	mode := ModeTree
	for _, name := range parts {
		if mode != ModeTree {
			return nil, 0, ErrObjectNotFound
		}
		entry, err := t.repo.entry(id)
		if err != nil {
			return nil, 0, err
		}
		defer entry.Close()

		if entry.Type() != "tree" {
			return nil, 0, ErrObjectNotFound
		}
		data, err := entry.ReadAll()
		if err != nil {
			return nil, 0, err
		}
		id, mode, err = findTreeEntryBytes(data, name)
		if err != nil {
			return nil, 0, err
		}
	}
	return newSparseObject(id, t.repo), mode, nil
}

func findTreeEntryBytes(data []byte, name string) (id SHA1, mode TreeEntryMode, err error) {
	scratchbuf.Reset()
	scratchbuf.WriteString(name)
	scratchbuf.WriteByte(0)
	term := scratchbuf.Bytes()
	for len(data) > 0 {
		var i int
		if data[5] == ' ' {
			i = 5
		} else if data[6] == ' ' {
			i = 6
		} else {
			return id, 0, ErrUnknownFormat
		}
		if mode, err = parseMode(data[:i]); err != nil {
			return
		}
		data = data[i+1:]

		n := len(term)
		if len(data) < n {
			break
		}
		if data[n-1] == 0 && bytes.Equal(data[:n], term) {
			return SHA1FromBytes(data[n : n+20]), mode, nil
		}
		i = bytes.IndexByte(data, 0)
		if i < 0 {
			return id, 0, ErrUnknownFormat
		}
		data = data[i+21:]
	}
	return id, 0, ErrObjectNotFound
}

func (t *Tree) Add(path string, obj Object, mode TreeEntryMode) error {
	dir, name := splitDirBase(path)
	tree, err := t.getSubTree(dir, true)
	if err != nil {
		return err
	}
	tree.addEntry(name, obj, mode)
	return nil
}

func (t *Tree) addEntry(name string, obj Object, mode TreeEntryMode) {
	t.dirty = true
	newEntry := &TreeEntry{
		Mode:   mode,
		Name:   name,
		Object: &SparseObject{repo: t.repo, obj: obj},
	}
	if i, entry := t.findEntry(name); entry != nil {
		// Must not modify the entry directly because it's cached
		t.Entries[i] = newEntry
		return
	}
	t.Entries = append(t.Entries, newEntry)
}

func (t *Tree) Remove(path string) error {
	dir, name := splitDirBase(path)
	tree, err := t.getSubTree(dir, false)
	if err != nil {
		if err == ErrObjectNotFound {
			return nil
		}
		return err
	}
	tree.removeEntry(name)
	return nil
}

func (t *Tree) removeEntry(name string) {
	if i, entry := t.findEntry(name); entry != nil {
		copy(t.Entries[i:], t.Entries[i+1:])
		t.Entries = t.Entries[:len(t.Entries)-1]
		t.dirty = true
		return
	}
}

func (t *Tree) getSubTree(parts []string, create bool) (*Tree, error) {
	if err := t.Resolve(); err != nil {
		return nil, err
	}
	tree := t
	var i int
	for ; i < len(parts); i++ {
		_, entry := tree.findEntry(parts[i])
		if entry == nil {
			break
		}
		obj, err := entry.Object.Resolve()
		if err != nil {
			return nil, err
		}
		subtree, ok := obj.(*Tree)
		if !ok {
			break
		}
		tree = subtree
	}
	if i == len(parts) {
		return tree, nil
	}
	if !create {
		return nil, ErrObjectNotFound
	}
	return tree.makeSubTrees(parts[i:]), nil
}

func (t *Tree) makeSubTrees(parts []string) *Tree {
	tree := t
	for _, name := range parts {
		newTree := t.repo.NewTree()
		tree.addEntry(name, newTree, ModeTree)
		tree = newTree
	}
	return tree
}

func (t *Tree) findEntry(name string) (int, *TreeEntry) {
	for i, entry := range t.Entries {
		if entry.Name == name {
			return i, entry
		}
	}
	return 0, nil
}

func (t *Tree) Write() error {
	_, err := t.write()
	return err
}

// write walks subtrees to check and save dirty objects recursively. To save
// entire tree correctly, it's necessary to save objects from leaf to root. If
// something changed in subtrees, the parent tree also need to be saved.
func (t *Tree) write() (bool, error) {
	for _, entry := range t.Entries {
		// It's safe to ignore unresolved objects because it's stored in
		// the repository and not modified.
		if entry.Object.obj == nil {
			continue
		}
		if subtree, ok := entry.Object.obj.(*Tree); ok {
			if changed, err := subtree.write(); err != nil {
				return false, err
			} else if changed {
				t.dirty = true
			}
		} else if entry.SHA1().Empty() {
			if err := entry.Object.obj.Write(); err != nil {
				return false, err
			}
			t.dirty = true
		}
	}
	if !t.dirty {
		return false, nil
	}

	sort.Sort(ByName(t.Entries))
	b := new(bytes.Buffer)
	for _, entry := range t.Entries {
		if entry.Object.obj != nil {
			if subtree, ok := entry.Object.obj.(*Tree); ok && len(subtree.Entries) == 0 {
				continue // No need to write empty tree object
			}
		}
		fmt.Fprintf(b, "%s %s%c", entry.Mode, entry.Name, 0)
		b.Write(entry.SHA1().Bytes())
	}
	id, err := t.repo.writeObject("tree", bytes.NewReader(b.Bytes()))
	if err != nil {
		return false, err
	}
	t.id = id
	t.dirty = false
	return true, nil
}

var treeEntryCache = lru.New(1 << 16)

type TreeEntry struct {
	Mode   TreeEntryMode
	Name   string
	Object *SparseObject
}

func newTreeEntry(mode, name, id, row []byte, repo *Repository) (*TreeEntry, error) {
	key := string(row)
	if entry, ok := treeEntryCache.Get(key); ok {
		return entry.(*TreeEntry), nil
	}
	m, err := parseMode(mode)
	if err != nil {
		return nil, err
	}
	entry := &TreeEntry{
		Mode:   m,
		Name:   string(name),
		Object: newSparseObject(SHA1FromBytes(id), repo),
	}
	treeEntryCache.Add(key, entry)
	return entry, nil
}

func (t *TreeEntry) Size() int {
	return 8 + len(t.Name)
}

func (t *TreeEntry) canonicalName() string {
	if t.Mode&ModeTree != 0 {
		return t.Name + "/"
	}
	return t.Name
}

func (t *TreeEntry) SHA1() SHA1 {
	if t.Object.obj != nil {
		return t.Object.obj.SHA1()
	}
	return t.Object.SHA1
}

type TreeEntryMode uint32

const (
	ModeTree    TreeEntryMode = 0040000
	ModeFile    TreeEntryMode = 0100644
	ModeFileEx  TreeEntryMode = 0100755
	ModeSymlink TreeEntryMode = 0120000
)

func parseMode(bs []byte) (TreeEntryMode, error) {
	var mode TreeEntryMode
	for _, b := range bs {
		n := b - 0x30
		if n < 0 || n > 7 {
			return 0, fmt.Errorf("%d not in octal range", n)
		}
		mode = mode<<3 | TreeEntryMode(n)
	}
	return mode, nil
}

func (m TreeEntryMode) String() string {
	var s string
	for m > 0 {
		n := int(m & 0x7)
		s = strconv.Itoa(n) + s
		m = m >> 3
	}
	return s
}

func splitPath(path string) []string {
	return strings.Split(strings.Trim(path, "/"), "/")
}

func splitDirBase(path string) ([]string, string) {
	s := splitPath(path)
	return s[:len(s)-1], s[len(s)-1]
}

func (r *Repository) NewTree() *Tree {
	return &Tree{repo: r}
}

type ByName []*TreeEntry

func (z ByName) Len() int           { return len(z) }
func (z ByName) Swap(i, j int)      { z[i], z[j] = z[j], z[i] }
func (z ByName) Less(i, j int) bool { return z[i].canonicalName() < z[j].canonicalName() }
<|endoftext|>


<commit_before>package gogit

import (
	"testing"
)

func TestBranches(t *testing.T) {
	git := Git{"/Users/tuzki/htdocs/go/src/gogit"}
	branches, err := git.Branches()
	if err != nil {
		t.Fatal(err)
	}
	if len(branches) < 1 {
		t.Fatal("there is no branches")
	}
}
<commit_msg>test remote branches<commit_after>package gogit

import (
	"testing"
)

var path string

func init() {
	path = "/Users/tuzki/htdocs/go/src/gogit"
}

func TestBranches(t *testing.T) {
	git := Git{path}
	branches, err := git.Branches()
	if err != nil {
		t.Fatal(err)
	}
	if len(branches) < 1 {
		t.Fatal("there is no branches")
	}
}

func TestRemoteBranches(t *testing.T) {
	git := Git{path}
	remoteBranches, err := git.RemoteBranches("origin")
	if err != nil {
		t.Fatal(err)
	}
	if len(remoteBranches) < 1 {
		t.Fatal("there is no remote branches")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/flynn/go-discoverd"
)

func main() {
	flag.Parse()
	name := flag.Arg(0)
	port := flag.Arg(1)
	host := flag.Arg(2)

	exit := make(chan os.Signal, 1)
	signal.Notify(exit, os.Interrupt, syscall.SIGTERM)
	var cleanup func()
	go func() {
		<-exit
		log.Println("Shutting down...")
		if cleanup != nil {
			cleanup()
		}
		os.Exit(0)
	}()

	client, err := discoverd.NewClient()
	if err != nil {
		log.Fatal("Error making client: ", err.Error())
	}
	if host != "" {
		client.RegisterWithHost(name, host, port, nil)
		cleanup = func() { client.UnregisterWithHost(name, host, port) }
	} else {
		client.Register(name, port, nil)
		cleanup = func() { client.Unregister(name, port) }
	}
	log.Printf("Registered %s on port %s.\n", name, port)

	set := client.Services(name)
	for {
		log.Println(strings.Join(set.OnlineAddrs(), ", "))
		time.Sleep(1 * time.Second)
	}
}
<commit_msg>discoverd/client: Refactor/update example<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"github.com/flynn/go-discoverd"
)

func main() {
	flag.Parse()
	name := flag.Arg(0)
	addr := flag.Arg(1)

	client, err := discoverd.NewClient()
	if err != nil {
		log.Fatal("Error making client:", err)
	}
	if err = client.Register(name, addr); err != nil {
		log.Fatal("Error registering:", err)
	}
	log.Printf("Registered %s at %s.\n", name, addr)

	exit := make(chan os.Signal, 1)
	signal.Notify(exit, os.Interrupt, syscall.SIGTERM)
	go func() {
		<-exit
		log.Println("Shutting down...")
		client.Unregister(name, addr)
		os.Exit(0)
	}()

	set, err := client.ServiceSet(name)
	if err != nil {
		log.Fatal("Error getting ServiceSet:", err)
	}
	for _ = range time.Tick(time.Second) {
		log.Println(strings.Join(set.Addrs(), ", "))
	}
}
<|endoftext|>


<commit_before>// Demonstrates how to tie together Goji (https://goji.io) and nosurf.
package main

import (
	"fmt"
	"html/template"
	"net/http"

	"github.com/zenazn/goji"
	"github.com/zenazn/goji/web"

	"github.com/justinas/nosurf"
)

var templateString = `
<!doctype html>

{{ if .name }}

Your name: {{ .name }}

{{ end }}
<form action="/signup/submit" method="POST">
<input type="text" name="name">

<input type="hidden" name="csrf_token" value="{{ .csrf_token }}">
<input type="submit" value="Send">
</form>

`

var templ = template.Must(template.New("t1").Parse(templateString))

type M map[string]interface{}

func IndexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Our index page")
}

func ShowSignupForm(c web.C, w http.ResponseWriter, r *http.Request) {
	templ.Execute(w, M{
		"csrf_token": nosurf.Token(r), // Pass the CSRF token to the template
	})
}

func SubmitSignupForm(c web.C, w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	fmt.Fprintf(w, "Successfully submitted, %s!", r.FormValue("name"))
}

func main() {
	goji.Get("/", IndexHandler) // Doesn't need CSRF protection (no POST/PUT/DELETE actions).

	signup := web.New()
	goji.Handle("/signup/*", signup)
	// But our signup forms do, so we add nosurf to their middleware stack (only).
	signup.Use(nosurf.NewPure)
	signup.Get("/signup/new", ShowSignupForm)
	signup.Post("/signup/submit", SubmitSignupForm)

	goji.Serve()
}
<commit_msg>Fleshed out Goji example to show how to apply a custom nosurf instance.<commit_after>// Demonstrates how to tie together Goji (https://goji.io) and nosurf.
package main

import (
	"fmt"
	"html/template"
	"net/http"
	"time"

	"github.com/zenazn/goji"
	"github.com/zenazn/goji/web"

	"github.com/justinas/nosurf"
)

var templateString = `
<!doctype html>

{{ if .name }}

Your name: {{ .name }}

{{ end }}
<form action="/signup/submit" method="POST">
<input type="text" name="name">

<input type="hidden" name="csrf_token" value="{{ .csrf_token }}">
<input type="submit" value="Send">
</form>

`

var templ = template.Must(template.New("t1").Parse(templateString))

type M map[string]interface{}

func IndexHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Our index page")
}

func ShowSignupForm(c web.C, w http.ResponseWriter, r *http.Request) {
	templ.Execute(w, M{
		"csrf_token": nosurf.Token(r), // Pass the CSRF token to the template
	})
}

func SubmitSignupForm(c web.C, w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}

	fmt.Fprintf(w, "Successfully submitted, %s!", r.FormValue("name"))
}

func main() {
	goji.Get("/", IndexHandler) // Doesn't need CSRF protection (no POST/PUT/DELETE actions).

	signup := web.New()
	goji.Handle("/signup/*", signup)
	// But our signup forms do, so we add nosurf to their middleware stack (only).
	signup.Use(nosurf.NewPure)
	signup.Get("/signup/new", ShowSignupForm)
	signup.Post("/signup/submit", SubmitSignupForm)

	admin := web.New()
	// A more advanced example: we enforce secure cookies (HTTPS only),
	// set a domain and keep the expiry time low.
	a := nosurf.New(admin)
	a.SetBaseCookie(http.Cookie{
		Name:     "csrf_token",
		Domain:   "localhost",
		Path:     "/admin",
		MaxAge:   time.Now().Add(time.Hour * 4),
		HttpOnly: true,
		Secure:   true,
	})

	// Our /admin/* routes now have CSRF protection.
	goji.Handle("/admin/*", a)

	goji.Serve()
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"fmt"
	"net/http"
)

type EchoGreeterServer struct {
}

func (s *EchoGreeterServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) {
	return &HelloReply{
		Message: fmt.Sprintf("Hello, %s!", req.Name),
	}, nil
}

func main() {
	srv := &EchoGreeterServer{}

	cnv := NewGreeterHTTPConverter(srv)

	http.Handle("sayhello", cnv.SayHello(nil))

	http.ListenAndServe(":8080", nil)
}
<commit_msg>Add comments to main.go<commit_after>package main

import (
	"context"
	"fmt"
	"net/http"
)

// EchoGreeterServer has implemented the GreeterServer interface that created from the service in proto file.
type EchoGreeterServer struct {
}

// SayHello implements the GreeterServer interface method.
// SayHello returns a greeting to the name sent.
func (s *EchoGreeterServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) {
	return &HelloReply{
		Message: fmt.Sprintf("Hello, %s!", req.Name),
	}, nil
}

func main() {
	// Create the GreeterServer.
	srv := &EchoGreeterServer{}

	// Create the GreeterHTTPConverter generated by protoc-gen-gohttp.
	// This converter converts the GreeterServer interface that created from the service in proto to http.HandlerFunc.
	conv := NewGreeterHTTPConverter(srv)

	// Register SayHello HandlerFunc to the server.
	// If you do not need a callback, pass nil as argument.
	http.Handle("/sayhello", conv.SayHello(nil))
	// If you need an auto-generated Path, use the SayHelloWithPath method.
	// In this case, the string 'greeter/server' is returned.
	http.Handle(conv.SayHelloWithPath(nil))

	http.ListenAndServe(":8080", nil)
}
<|endoftext|>