<commit_before>// Copyright (c) 2015 The golex Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lex

import (
	"bytes"
	"fmt"
	"go/token"
	"io"
	"os"
)

// BOM handling modes which can be set by the BOMMode Option. Default is BOMIgnoreFirst.
const (
	BOMError       = iota // BOM is an error anywhere.
	BOMIgnoreFirst        // Skip BOM if at beginning, report as error if anywhere else.
	BOMPassAll            // No special handling of BOM.
	BOMPassFirst          // No special handling of BOM if at beginning, report as error if anywhere else.
)

const (
	NonASCII = 0x80 // DefaultRuneClass returns NonASCII for non ASCII runes.
	RuneEOF  = -1
)

// DefaultRuneClass returns the character class of r. If r is an ASCII code
// then its class equals the ASCII code. Any other rune is of class NonASCII.
//
// DefaultRuneClass is the default implementation Lexer will use to convert
// runes (21 bit entities) to scanner classes (8 bit entities).
//
// Non ASCII aware lexical analyzers will typically use their own
// categorization function. To assign such custom function use the RuneClass
// option.
func DefaultRuneClass(r rune) int {
	if r >= 0 && r < 0x80 {
		return int(r)
	}

	return NonASCII
}

// Char represents a rune and its position.
type Char struct {
	Rune rune
	pos  int32
}

// NewChar returns a new Char value.
func NewChar(pos token.Pos, r rune) Char { return Char{pos: int32(pos), Rune: r} }

// IsValid reports whether c is not a zero Char.
func (c Char) IsValid() bool { return c.Pos().IsValid() }

// Pos returns the token.Pos associated with c.
func (c Char) Pos() token.Pos { return token.Pos(c.pos) }

// Lexer suports golex[0] generated lexical analyzers.
type Lexer struct {
	File      *token.File             // The *token.File passed to New.
	First     Char                    // First remembers the lookahead char when Rule0 was invoked.
	Last      Char                    // Last remembers the last Char returned by Next.
	Prev      Char                    // Prev remembers the Char previous to Last.
	bomMode   int                     // See the BOM* constants.
	bytesBuf  bytes.Buffer            // Used by TokenBytes.
	classf    func(rune) int          //
	errorf    func(token.Pos, string) //
	lookahead Char                    // Lookahead if non zero.
	mark      int                     // Longest match marker.
	off       int                     // Used for File.AddLine.
	src       io.RuneReader           // Lexer input.
	tokenBuf  []Char                  // Lexeme collector.
	ungetBuf  []Char                  // Unget buffer.
}

// New returns a new *Lexer. The result can be amended using opts.
func New(file *token.File, src io.RuneReader, opts ...Option) (*Lexer, error) {
	r := &Lexer{
		File:    file,
		bomMode: BOMIgnoreFirst,
		classf:  DefaultRuneClass,
		src:     src,
	}
	r.errorf = r.defaultErrorf
	for _, o := range opts {
		if err := o(r); err != nil {
			return nil, err
		}
	}
	return r, nil
}

// Abort handles the situation when the scanner does not successfully recognize
// any token or when an attempt to find the longest match "overruns" from an
// accepting state only to never reach an accepting state again. In the first
// case the scanner was never in an accepting state since last call to Rule0
// and then (true, previousLookahead rune) is returned, effectively consuming a
// single Char token, avoiding scanner stall.  Otherwise there was at least one
// accepting scanner state marked using Mark. In this case Abort rollbacks the
// lexer state to the marked state and returns (false, 0). The scanner must
// then execute a prescribed goto statement. For example:
//
//	%yyc c
//	%yyn c = l.Next()
//	%yym l.Mark()
//
//	%{
//	package foo
//
//	import (...)
//
//	type lexer struct {
//		*lex.Lexer
//		...
//	}
//
//	func newLexer(...) *lexer {
//		return &lexer{
//			lex.NewLexer(...),
//			...
//		}
//	}
//
//	func (l *lexer) scan() int {
//	        c := l.Enter()
//	%}
//
//	... more lex defintions
//
//	%%
//
//	        c = l.Rule0()
//
//	... lex rules
//
//	%%
//
//		if c, ok := l.Abort(); ok {
//			return c
//		}
//
//		goto yyAction
//	}
func (l *Lexer) Abort() (int, bool) {
	if l.mark >= 0 {
		if len(l.tokenBuf) > l.mark {
			l.Unget(l.lookahead)
			for i := len(l.tokenBuf) - 1; i >= l.mark; i-- {
				l.Unget(l.tokenBuf[i])
			}
			l.Next()
		}
		l.tokenBuf = l.tokenBuf[:l.mark]
		return 0, false
	}

	switch n := len(l.tokenBuf); n {
	case 0: // [] z
		c := l.lookahead
		l.Next()
		return int(c.Rune), true
	case 1: // [a] z
		return int(l.tokenBuf[0].Rune), true
	default: // [a, b, ...], z
		c := l.tokenBuf[0]   // a
		l.Unget(l.lookahead) // z
		for i := n - 1; i > 1; i-- {
			l.Unget(l.tokenBuf[i]) // ...
		}
		l.lookahead = l.tokenBuf[1] // b
		l.tokenBuf = l.tokenBuf[:1]
		return int(c.Rune), true
	}
}

func (l *Lexer) class() int { return l.classf(l.lookahead.Rune) }

func (l *Lexer) defaultErrorf(pos token.Pos, msg string) {
	l.Error(fmt.Sprintf("%v: %v", l.File.Position(pos), msg))
}

// Enter ensures the lexer has a valid lookahead Char and returns its class.
// Typical usage in an .l file:
//
//	%yyn c = l.Next()
func (l *Lexer) Enter() int {
	if !l.lookahead.IsValid() {
		l.Next()
	}
	return l.class()
}

// Error Implements yyLexer[2] by printing the msg to stderr.
func (l *Lexer) Error(msg string) {
	fmt.Fprintf(os.Stderr, "%s\n", msg)
}

// Mark records the current state of scanner as accepting. It implements the
// golex macro %yym.
func (l *Lexer) Mark() { l.mark = len(l.tokenBuf) }

func (l *Lexer) next() int {
	const bom = '\ufeff'

	if c := l.lookahead; c.IsValid() {
		l.tokenBuf = append(l.tokenBuf, c)
	}
	if n := len(l.ungetBuf); n != 0 {
		l.lookahead = l.ungetBuf[n-1]
		l.ungetBuf = l.ungetBuf[:n-1]
		return l.class()
	}

	if l.src == nil {
		return RuneEOF
	}

	var r rune
	var sz int
	var err error
	var pos token.Pos
again:
	r, sz, err = l.src.ReadRune()
	pos = l.File.Pos(l.off)
	if err != nil {
		l.src = nil
		r = RuneEOF
		if err != io.EOF {
			l.errorf(pos, err.Error())
		}
	}

	if r == bom {
		switch l.bomMode {
		default:
			fallthrough
		case BOMIgnoreFirst:
			if l.off != 0 {
				l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
			}
			l.off += sz
			goto again
		case BOMPassAll:
			// nop
		case BOMPassFirst:
			if l.off != 0 {
				l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
				l.off += sz
				goto again
			}
		case BOMError:
			switch {
			case l.off == 0:
				l.errorf(pos, "unicode (UTF-8) BOM at beginnig of file")
			default:
				l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
			}
			l.off += sz
			goto again
		}
	}

	l.lookahead = NewChar(pos, r)
	l.off += sz
	if r == '\n' {
		l.File.AddLine(l.off)
	}
	return l.class()
}

// Next advances the scanner for one rune and returns the respective character
// class of the new lookahead.
func (l *Lexer) Next() int {
	l.Prev = l.Last
	r := l.next()
	l.Last = l.lookahead
	return r
}

// Offset returns the number of bytes that was read from the lexer's source so far.
func (l *Lexer) Offset() int { return l.off }

// Rule0 initializesthe scanner state before the attempt to recognize a token
// starts. The token collecting buffer is cleared.  Rule0 records the current
// lookahead in l.First and returns its class.
func (l *Lexer) Rule0() int {
	l.First = l.lookahead
	l.mark = -1
	if len(l.tokenBuf) > 1<<18 { //DONE constant tuned
		l.tokenBuf = nil
	} else {
		l.tokenBuf = l.tokenBuf[:0]
	}
	return l.class()
}

// Token returns the currently collected token chars. The result is R/O.
func (l *Lexer) Token() []Char { return l.tokenBuf }

// TokenBytes returns the UTF-8 encoding of Token. If builder is not nil then
// it's called instead to build the encoded token byte value into the buffer
// passed to it.
//
// The Result is R/O.
func (l *Lexer) TokenBytes(builder func(*bytes.Buffer)) []byte {
	if len(l.bytesBuf.Bytes()) < 1<<18 { //DONE constant tuned
		l.bytesBuf.Reset()
	} else {
		l.bytesBuf = bytes.Buffer{}
	}
	switch {
	case builder != nil:
		builder(&l.bytesBuf)
	default:
		for _, c := range l.Token() {
			l.bytesBuf.WriteRune(c.Rune)
		}
	}
	return l.bytesBuf.Bytes()
}

// Unget unreads all chars in c.
func (l *Lexer) Unget(c ...Char) {
	for _, c := range c {
		l.ungetBuf = append(l.ungetBuf, c)
	}
}

// Option is a function which can be passed as an optional argument to New.
type Option func(*Lexer) error

// BOMMode option selects how the lexer handles BOMs. See the BOM* constants for details.
func BOMMode(mode int) Option {
	return func(l *Lexer) error {
		l.bomMode = mode
		return nil
	}
}

// ErrorFunc option sets a function called when an, for example I/O error, occurs.
func ErrorFunc(f func(token.Pos, string)) Option {
	return func(l *Lexer) error {
		l.errorf = f
		return nil
	}
}

// RuneClass option sets the function used to convert runes to character
// classes.
func RuneClass(f func(rune) int) Option {
	return func(l *Lexer) error {
		l.classf = f
		return nil
	}
}
<commit_msg>lex: Bug fixes.<commit_after>// Copyright (c) 2015 The golex Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lex

import (
	"bytes"
	"fmt"
	"go/token"
	"io"
	"os"
)

// BOM handling modes which can be set by the BOMMode Option. Default is BOMIgnoreFirst.
const (
	BOMError       = iota // BOM is an error anywhere.
	BOMIgnoreFirst        // Skip BOM if at beginning, report as error if anywhere else.
	BOMPassAll            // No special handling of BOM.
	BOMPassFirst          // No special handling of BOM if at beginning, report as error if anywhere else.
)

const (
	NonASCII = 0x80 // DefaultRuneClass returns NonASCII for non ASCII runes.
	RuneEOF  = -1
)

// DefaultRuneClass returns the character class of r. If r is an ASCII code
// then its class equals the ASCII code. Any other rune is of class NonASCII.
//
// DefaultRuneClass is the default implementation Lexer will use to convert
// runes (21 bit entities) to scanner classes (8 bit entities).
//
// Non ASCII aware lexical analyzers will typically use their own
// categorization function. To assign such custom function use the RuneClass
// option.
func DefaultRuneClass(r rune) int {
	if r >= 0 && r < 0x80 {
		return int(r)
	}

	return NonASCII
}

// Char represents a rune and its position.
type Char struct {
	Rune rune
	pos  int32
}

// NewChar returns a new Char value.
func NewChar(pos token.Pos, r rune) Char { return Char{pos: int32(pos), Rune: r} }

// IsValid reports whether c is not a zero Char.
func (c Char) IsValid() bool { return c.Pos().IsValid() }

// Pos returns the token.Pos associated with c.
func (c Char) Pos() token.Pos { return token.Pos(c.pos) }

// Lexer suports golex[0] generated lexical analyzers.
type Lexer struct {
	File      *token.File             // The *token.File passed to New.
	First     Char                    // First remembers the lookahead char when Rule0 was invoked.
	Last      Char                    // Last remembers the last Char returned by Next.
	Prev      Char                    // Prev remembers the Char previous to Last.
	bomMode   int                     // See the BOM* constants.
	bytesBuf  bytes.Buffer            // Used by TokenBytes.
	classf    func(rune) int          //
	errorf    func(token.Pos, string) //
	lookahead Char                    // Lookahead if non zero.
	mark      int                     // Longest match marker.
	off       int                     // Used for File.AddLine.
	src       io.RuneReader           // Lexer input.
	tokenBuf  []Char                  // Lexeme collector.
	ungetBuf  []Char                  // Unget buffer.
}

// New returns a new *Lexer. The result can be amended using opts.
func New(file *token.File, src io.RuneReader, opts ...Option) (*Lexer, error) {
	r := &Lexer{
		File:    file,
		bomMode: BOMIgnoreFirst,
		classf:  DefaultRuneClass,
		src:     src,
	}
	r.errorf = r.defaultErrorf
	for _, o := range opts {
		if err := o(r); err != nil {
			return nil, err
		}
	}
	return r, nil
}

// Abort handles the situation when the scanner does not successfully recognize
// any token or when an attempt to find the longest match "overruns" from an
// accepting state only to never reach an accepting state again. In the first
// case the scanner was never in an accepting state since last call to Rule0
// and then (true, previousLookahead rune) is returned, effectively consuming a
// single Char token, avoiding scanner stall.  Otherwise there was at least one
// accepting scanner state marked using Mark. In this case Abort rollbacks the
// lexer state to the marked state and returns (false, 0). The scanner must
// then execute a prescribed goto statement. For example:
//
//	%yyc c
//	%yyn c = l.Next()
//	%yym l.Mark()
//
//	%{
//	package foo
//
//	import (...)
//
//	type lexer struct {
//		*lex.Lexer
//		...
//	}
//
//	func newLexer(...) *lexer {
//		return &lexer{
//			lex.NewLexer(...),
//			...
//		}
//	}
//
//	func (l *lexer) scan() int {
//	        c := l.Enter()
//	%}
//
//	... more lex defintions
//
//	%%
//
//	        c = l.Rule0()
//
//	... lex rules
//
//	%%
//
//		if c, ok := l.Abort(); ok {
//			return c
//		}
//
//		goto yyAction
//	}
func (l *Lexer) Abort() (int, bool) {
	if l.mark >= 0 {
		if len(l.tokenBuf) > l.mark {
			l.Unget(l.lookahead)
			for i := len(l.tokenBuf) - 1; i >= l.mark; i-- {
				l.Unget(l.tokenBuf[i])
			}
			l.Next()
		}
		l.tokenBuf = l.tokenBuf[:l.mark]
		return 0, false
	}

	switch n := len(l.tokenBuf); n {
	case 0: // [] z
		c := l.lookahead
		l.Next()
		return int(c.Rune), true
	case 1: // [a] z
		return int(l.tokenBuf[0].Rune), true
	default: // [a, b, ...], z
		c := l.tokenBuf[0]   // a
		l.Unget(l.lookahead) // z
		for i := n - 1; i > 1; i-- {
			l.Unget(l.tokenBuf[i]) // ...
		}
		l.lookahead = l.tokenBuf[1] // b
		l.tokenBuf = l.tokenBuf[:1]
		return int(c.Rune), true
	}
}

func (l *Lexer) class() int { return l.classf(l.lookahead.Rune) }

func (l *Lexer) defaultErrorf(pos token.Pos, msg string) {
	l.Error(fmt.Sprintf("%v: %v", l.File.Position(pos), msg))
}

// Enter ensures the lexer has a valid lookahead Char and returns its class.
// Typical usage in an .l file:
//
//	%yyn c = l.Next()
func (l *Lexer) Enter() int {
	if !l.lookahead.IsValid() {
		l.Next()
	}
	return l.class()
}

// Error Implements yyLexer[2] by printing the msg to stderr.
func (l *Lexer) Error(msg string) {
	fmt.Fprintf(os.Stderr, "%s\n", msg)
}

// Mark records the current state of scanner as accepting. It implements the
// golex macro %yym.
func (l *Lexer) Mark() { l.mark = len(l.tokenBuf) }

func (l *Lexer) next() int {
	const bom = '\ufeff'

	if c := l.lookahead; c.IsValid() {
		l.tokenBuf = append(l.tokenBuf, c)
	}
	if n := len(l.ungetBuf); n != 0 {
		l.lookahead = l.ungetBuf[n-1]
		l.ungetBuf = l.ungetBuf[:n-1]
		return l.class()
	}

	if l.src == nil {
		return RuneEOF
	}

	var r rune
	var sz int
	var err error
	var pos token.Pos
again:
	r, sz, err = l.src.ReadRune()
	off0 := l.off
	pos = l.File.Pos(l.off)
	l.off += sz
	if err != nil {
		l.src = nil
		r = RuneEOF
		if err != io.EOF {
			l.errorf(pos, err.Error())
		}
	}

	if r == bom {
		switch l.bomMode {
		default:
			fallthrough
		case BOMIgnoreFirst:
			if off0 != 0 {
				l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
			}
			goto again
		case BOMPassAll:
			// nop
		case BOMPassFirst:
			if off0 != 0 {
				l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
				goto again
			}
		case BOMError:
			switch {
			case off0 == 0:
				l.errorf(pos, "unicode (UTF-8) BOM at beginnig of file")
			default:
				l.errorf(pos, "unicode (UTF-8) BOM in middle of file")
			}
			goto again
		}
	}

	l.lookahead = NewChar(pos, r)
	if r == '\n' {
		l.File.AddLine(l.off)
	}
	return l.class()
}

// Next advances the scanner for one rune and returns the respective character
// class of the new lookahead.
func (l *Lexer) Next() int {
	l.Prev = l.Last
	r := l.next()
	l.Last = l.lookahead
	return r
}

// Offset returns the current reading offset of the lexer's source.
func (l *Lexer) Offset() int { return l.off }

// Rule0 initializes the scanner state before the attempt to recognize a token
// starts. The token collecting buffer is cleared.  Rule0 records the current
// lookahead in l.First and returns its class.
func (l *Lexer) Rule0() int {
	l.First = l.lookahead
	l.mark = -1
	if len(l.tokenBuf) > 1<<18 { //DONE constant tuned
		l.tokenBuf = nil
	} else {
		l.tokenBuf = l.tokenBuf[:0]
	}
	return l.class()
}

// Token returns the currently collected token chars. The result is R/O.
func (l *Lexer) Token() []Char { return l.tokenBuf }

// TokenBytes returns the UTF-8 encoding of Token. If builder is not nil then
// it's called instead to build the encoded token byte value into the buffer
// passed to it.
//
// The Result is R/O.
func (l *Lexer) TokenBytes(builder func(*bytes.Buffer)) []byte {
	if len(l.bytesBuf.Bytes()) < 1<<18 { //DONE constant tuned
		l.bytesBuf.Reset()
	} else {
		l.bytesBuf = bytes.Buffer{}
	}
	switch {
	case builder != nil:
		builder(&l.bytesBuf)
	default:
		for _, c := range l.Token() {
			l.bytesBuf.WriteRune(c.Rune)
		}
	}
	return l.bytesBuf.Bytes()
}

// Unget unreads all chars in c.
func (l *Lexer) Unget(c ...Char) {
	for _, c := range c {
		l.ungetBuf = append(l.ungetBuf, c)
	}
}

// Option is a function which can be passed as an optional argument to New.
type Option func(*Lexer) error

// BOMMode option selects how the lexer handles BOMs. See the BOM* constants for details.
func BOMMode(mode int) Option {
	return func(l *Lexer) error {
		l.bomMode = mode
		return nil
	}
}

// ErrorFunc option sets a function called when an, for example I/O error, occurs.
func ErrorFunc(f func(token.Pos, string)) Option {
	return func(l *Lexer) error {
		l.errorf = f
		return nil
	}
}

// RuneClass option sets the function used to convert runes to character
// classes.
func RuneClass(f func(rune) int) Option {
	return func(l *Lexer) error {
		l.classf = f
		return nil
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"
	"text/template"
	"time"

	"github.com/PuerkitoBio/goquery"
	"golang.org/x/oauth2"
)

const issueTemplate = `
{{range .}}
- [ ] {{.}}
{{end}}
`

var reGithubRepo = regexp.MustCompile("https://github.com/[a-zA-Z0-9-._]+/[a-zA-Z0-9-._]+$")
var githubGETREPO = "https://api.github.com/repos%s"
var githubGETCOMMITS = "https://api.github.com/repos%s/commits"
var githubPOSTISSUES = "https://api.github.com/repos/avelino/awesome-go/issues"
var awesomeGoGETISSUES = "http://api.github.com/repos/avelino/awesome-go/issues" //only returns open issues
var numberOfYears time.Duration = 1

const issueTitle = "Investigate repositories with more than 1 year without update"
const deadLinkMessage = " this repository might no longer exist! (status code >= 400 returned)"
const movedPermanently = " status code 301 received"
const status302 = " status code 302 received"
const archived = " repository has been archived"

var delay time.Duration = 1

//LIMIT specifies the max number of repositories that are added in a single run of the script
var LIMIT = 10
var ctr = 0

type tokenSource struct {
	AccessToken string
}
type issue struct {
	Title string `json:"title"`
	Body  string `json:"body"`
}
type repo struct {
	Archived bool `json:"archived"`
}

func (t *tokenSource) Token() (*oauth2.Token, error) {
	token := &oauth2.Token{
		AccessToken: t.AccessToken,
	}
	return token, nil
}
func getRepositoriesFromBody(body string) []string {
	links := strings.Split(body, "- ")
	for idx, link := range links {
		str := strings.ReplaceAll(link, "\r", "")
		str = strings.ReplaceAll(str, "[ ]", "")
		str = strings.ReplaceAll(str, "[x]", "")
		str = strings.ReplaceAll(str, " ", "")
		str = strings.ReplaceAll(str, "\n", "")
		str = strings.ReplaceAll(str, deadLinkMessage, "")
		str = strings.ReplaceAll(str, movedPermanently, "")
		str = strings.ReplaceAll(str, status302, "")
		str = strings.ReplaceAll(str, archived, "")
		links[idx] = str
	}
	return links
}
func generateIssueBody(repositories []string) (string, error) {
	var writer bytes.Buffer
	t := template.New("issue")
	temp, err := t.Parse(issueTemplate)
	if err != nil {
		log.Print("Failed to generate template")
		return "", err
	}
	err = temp.Execute(&writer, repositories)
	if err != nil {
		log.Print("Failed to generate template")
		return "", err
	}
	issueBody := writer.String()
	return issueBody, nil
}
func createIssue(staleRepos []string, client *http.Client) {
	if len(staleRepos) == 0 {
		log.Print("NO STALE REPOSITORIES")
		return
	}
	body, err := generateIssueBody(staleRepos)
	if err != nil {
		log.Print("Failed at CreateIssue")
		return
	}
	newIssue := &issue{
		Title: issueTitle,
		Body:  body,
	}
	buf := new(bytes.Buffer)
	json.NewEncoder(buf).Encode(newIssue)
	req, err := http.NewRequest("POST", githubPOSTISSUES, buf)
	if err != nil {
		log.Print("Failed at CreateIssue")
		return
	}
	client.Do(req)
}
func getAllFlaggedRepositories(client *http.Client, flaggedRepositories *map[string]bool) error {
	req, err := http.NewRequest("GET", awesomeGoGETISSUES, nil)
	if err != nil {
		log.Print("Failed to get all issues")
		return err
	}
	res, err := client.Do(req)
	if err != nil {
		log.Print("Failed to get all issues")
		return err
	}
	target := []issue{}
	defer res.Body.Close()
	json.NewDecoder(res.Body).Decode(&target)
	for _, i := range target {
		if i.Title == issueTitle {
			repos := getRepositoriesFromBody(i.Body)
			for _, repo := range repos {
				(*flaggedRepositories)[repo] = true
			}
		}
	}
	return nil
}
func containsOpenIssue(link string, openIssues map[string]bool) bool {
	_, ok := openIssues[link]
	if ok {
		return true
	}
	return false
}
func testRepoState(toRun bool, href string, client *http.Client, staleRepos *[]string) bool {
	if toRun {
		ownerRepo := strings.ReplaceAll(href, "https://github.com", "")
		apiCall := fmt.Sprintf(githubGETREPO, ownerRepo)
		req, err := http.NewRequest("GET", apiCall, nil)
		var repoResp repo
		isRepoAdded := false
		if err != nil {
			log.Printf("Failed at repository %s\n", href)
			return false
		}
		resp, err := client.Do(req)
		if err != nil {
			log.Printf("Failed at repository %s\n", href)
			return false
		}
		defer resp.Body.Close()
		json.NewDecoder(resp.Body).Decode(&repoResp)
		if resp.StatusCode == 301 {
			*staleRepos = append(*staleRepos, href+movedPermanently)
			log.Printf("%s returned 301", href)
			isRepoAdded = true
		}
		if resp.StatusCode == 302 && !isRepoAdded {
			*staleRepos = append(*staleRepos, href+status302)
			log.Printf("%s returned 302", href)
			isRepoAdded = true
		}
		if resp.StatusCode >= 400 && !isRepoAdded {
			*staleRepos = append(*staleRepos, href+deadLinkMessage)
			log.Printf("%s might not exist!", href)
			isRepoAdded = true
		}
		if repoResp.Archived && !isRepoAdded {
			*staleRepos = append(*staleRepos, href+archived)
			log.Printf("%s is archived!", href)
			isRepoAdded = true
		}
		return isRepoAdded
	}
	return false
}
func testCommitAge(toRun bool, href string, client *http.Client, staleRepos *[]string) bool {
	if toRun {
		var respObj []map[string]interface{}
		now := time.Now()
		since := now.Add(-1 * 365 * 24 * numberOfYears * time.Hour)
		sinceQuery := since.Format(time.RFC3339)
		ownerRepo := strings.ReplaceAll(href, "https://github.com", "")
		apiCall := fmt.Sprintf(githubGETCOMMITS, ownerRepo)
		req, err := http.NewRequest("GET", apiCall, nil)
		isRepoAdded := false
		if err != nil {
			log.Printf("Failed at repository %s\n", href)
			return false
		}
		q := req.URL.Query()
		q.Add("since", sinceQuery)
		req.URL.RawQuery = q.Encode()
		resp, err := client.Do(req)
		if err != nil {
			log.Printf("Failed at repository %s\n", href)
			return false
		}
		defer resp.Body.Close()
		json.NewDecoder(resp.Body).Decode(&respObj)
		isAged := len(respObj) == 0
		if isAged {
			log.Printf("%s has not had a commit in a while", href)
			*staleRepos = append(*staleRepos, href)
			isRepoAdded = true
		}
		return isRepoAdded
	}
	return false
}
func testStaleRepository() {
	query := startQuery()
	var staleRepos []string
	addressedRepositories := make(map[string]bool)
	oauth := os.Getenv("OAUTH_TOKEN")
	client := &http.Client{}
	if oauth == "" {
		log.Print("No oauth token found. Using unauthenticated client ...")
	} else {
		tokenSource := &tokenSource{
			AccessToken: oauth,
		}
		client = oauth2.NewClient(oauth2.NoContext, tokenSource)
	}
	err := getAllFlaggedRepositories(client, &addressedRepositories)

	if err != nil {
		log.Println("Failed to get existing issues. Exiting...")
		return
	}
	query.Find("body li > a:first-child").EachWithBreak(func(_ int, s *goquery.Selection) bool {
		href, ok := s.Attr("href")
		if !ok {
			log.Println("expected to have href")
			return true
		}
		if ctr >= LIMIT && LIMIT != -1 {
			log.Print("Max number of issues created")
			return false
		}
		issueExists := containsOpenIssue(href, addressedRepositories)
		if issueExists {
			log.Printf("issue already exists for %s\n", href)
		} else {
			isGithubRepo := reGithubRepo.MatchString(href)
			if isGithubRepo {
				isRepoAdded := testRepoState(true, href, client, &staleRepos)
				isRepoAdded = testCommitAge(!isRepoAdded, href, client, &staleRepos)
				if isRepoAdded {
					ctr++
				}
			} else {
				log.Printf("%s non-github repo not currently handled", href)
			}
		}
		return true
	})
	createIssue(staleRepos, client)
}

func main() {
	testStaleRepository()
}
<commit_msg>set date now on investigate issue title (#3455)<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"
	"text/template"
	"time"

	"github.com/PuerkitoBio/goquery"
	"golang.org/x/oauth2"
)

const issueTemplate = `
{{range .}}
- [ ] {{.}}
{{end}}
`

var reGithubRepo = regexp.MustCompile("https://github.com/[a-zA-Z0-9-._]+/[a-zA-Z0-9-._]+$")
var githubGETREPO = "https://api.github.com/repos%s"
var githubGETCOMMITS = "https://api.github.com/repos%s/commits"
var githubPOSTISSUES = "https://api.github.com/repos/avelino/awesome-go/issues"
var awesomeGoGETISSUES = "http://api.github.com/repos/avelino/awesome-go/issues" //only returns open issues
var numberOfYears time.Duration = 1
var timeNow = time.Now()
var issueTitle = fmt.Sprintf("Investigate repositories with more than 1 year without update - %s", timeNow.Format("2006-01-02"))

const deadLinkMessage = " this repository might no longer exist! (status code >= 400 returned)"
const movedPermanently = " status code 301 received"
const status302 = " status code 302 received"
const archived = " repository has been archived"

var delay time.Duration = 1

//LIMIT specifies the max number of repositories that are added in a single run of the script
var LIMIT = 10
var ctr = 0

type tokenSource struct {
	AccessToken string
}
type issue struct {
	Title string `json:"title"`
	Body  string `json:"body"`
}
type repo struct {
	Archived bool `json:"archived"`
}

func (t *tokenSource) Token() (*oauth2.Token, error) {
	token := &oauth2.Token{
		AccessToken: t.AccessToken,
	}
	return token, nil
}
func getRepositoriesFromBody(body string) []string {
	links := strings.Split(body, "- ")
	for idx, link := range links {
		str := strings.ReplaceAll(link, "\r", "")
		str = strings.ReplaceAll(str, "[ ]", "")
		str = strings.ReplaceAll(str, "[x]", "")
		str = strings.ReplaceAll(str, " ", "")
		str = strings.ReplaceAll(str, "\n", "")
		str = strings.ReplaceAll(str, deadLinkMessage, "")
		str = strings.ReplaceAll(str, movedPermanently, "")
		str = strings.ReplaceAll(str, status302, "")
		str = strings.ReplaceAll(str, archived, "")
		links[idx] = str
	}
	return links
}
func generateIssueBody(repositories []string) (string, error) {
	var writer bytes.Buffer
	t := template.New("issue")
	temp, err := t.Parse(issueTemplate)
	if err != nil {
		log.Print("Failed to generate template")
		return "", err
	}
	err = temp.Execute(&writer, repositories)
	if err != nil {
		log.Print("Failed to generate template")
		return "", err
	}
	issueBody := writer.String()
	return issueBody, nil
}
func createIssue(staleRepos []string, client *http.Client) {
	if len(staleRepos) == 0 {
		log.Print("NO STALE REPOSITORIES")
		return
	}
	body, err := generateIssueBody(staleRepos)
	if err != nil {
		log.Print("Failed at CreateIssue")
		return
	}
	newIssue := &issue{
		Title: issueTitle,
		Body:  body,
	}
	buf := new(bytes.Buffer)
	json.NewEncoder(buf).Encode(newIssue)
	req, err := http.NewRequest("POST", githubPOSTISSUES, buf)
	if err != nil {
		log.Print("Failed at CreateIssue")
		return
	}
	client.Do(req)
}
func getAllFlaggedRepositories(client *http.Client, flaggedRepositories *map[string]bool) error {
	req, err := http.NewRequest("GET", awesomeGoGETISSUES, nil)
	if err != nil {
		log.Print("Failed to get all issues")
		return err
	}
	res, err := client.Do(req)
	if err != nil {
		log.Print("Failed to get all issues")
		return err
	}
	target := []issue{}
	defer res.Body.Close()
	json.NewDecoder(res.Body).Decode(&target)
	for _, i := range target {
		if i.Title == issueTitle {
			repos := getRepositoriesFromBody(i.Body)
			for _, repo := range repos {
				(*flaggedRepositories)[repo] = true
			}
		}
	}
	return nil
}
func containsOpenIssue(link string, openIssues map[string]bool) bool {
	_, ok := openIssues[link]
	if ok {
		return true
	}
	return false
}
func testRepoState(toRun bool, href string, client *http.Client, staleRepos *[]string) bool {
	if toRun {
		ownerRepo := strings.ReplaceAll(href, "https://github.com", "")
		apiCall := fmt.Sprintf(githubGETREPO, ownerRepo)
		req, err := http.NewRequest("GET", apiCall, nil)
		var repoResp repo
		isRepoAdded := false
		if err != nil {
			log.Printf("Failed at repository %s\n", href)
			return false
		}
		resp, err := client.Do(req)
		if err != nil {
			log.Printf("Failed at repository %s\n", href)
			return false
		}
		defer resp.Body.Close()
		json.NewDecoder(resp.Body).Decode(&repoResp)
		if resp.StatusCode == 301 {
			*staleRepos = append(*staleRepos, href+movedPermanently)
			log.Printf("%s returned 301", href)
			isRepoAdded = true
		}
		if resp.StatusCode == 302 && !isRepoAdded {
			*staleRepos = append(*staleRepos, href+status302)
			log.Printf("%s returned 302", href)
			isRepoAdded = true
		}
		if resp.StatusCode >= 400 && !isRepoAdded {
			*staleRepos = append(*staleRepos, href+deadLinkMessage)
			log.Printf("%s might not exist!", href)
			isRepoAdded = true
		}
		if repoResp.Archived && !isRepoAdded {
			*staleRepos = append(*staleRepos, href+archived)
			log.Printf("%s is archived!", href)
			isRepoAdded = true
		}
		return isRepoAdded
	}
	return false
}
func testCommitAge(toRun bool, href string, client *http.Client, staleRepos *[]string) bool {
	if toRun {
		var respObj []map[string]interface{}
		since := timeNow.Add(-1 * 365 * 24 * numberOfYears * time.Hour)
		sinceQuery := since.Format(time.RFC3339)
		ownerRepo := strings.ReplaceAll(href, "https://github.com", "")
		apiCall := fmt.Sprintf(githubGETCOMMITS, ownerRepo)
		req, err := http.NewRequest("GET", apiCall, nil)
		isRepoAdded := false
		if err != nil {
			log.Printf("Failed at repository %s\n", href)
			return false
		}
		q := req.URL.Query()
		q.Add("since", sinceQuery)
		req.URL.RawQuery = q.Encode()
		resp, err := client.Do(req)
		if err != nil {
			log.Printf("Failed at repository %s\n", href)
			return false
		}
		defer resp.Body.Close()
		json.NewDecoder(resp.Body).Decode(&respObj)
		isAged := len(respObj) == 0
		if isAged {
			log.Printf("%s has not had a commit in a while", href)
			*staleRepos = append(*staleRepos, href)
			isRepoAdded = true
		}
		return isRepoAdded
	}
	return false
}
func testStaleRepository() {
	query := startQuery()
	var staleRepos []string
	addressedRepositories := make(map[string]bool)
	oauth := os.Getenv("OAUTH_TOKEN")
	client := &http.Client{}
	if oauth == "" {
		log.Print("No oauth token found. Using unauthenticated client ...")
	} else {
		tokenSource := &tokenSource{
			AccessToken: oauth,
		}
		client = oauth2.NewClient(oauth2.NoContext, tokenSource)
	}
	err := getAllFlaggedRepositories(client, &addressedRepositories)

	if err != nil {
		log.Println("Failed to get existing issues. Exiting...")
		return
	}
	query.Find("body li > a:first-child").EachWithBreak(func(_ int, s *goquery.Selection) bool {
		href, ok := s.Attr("href")
		if !ok {
			log.Println("expected to have href")
			return true
		}
		if ctr >= LIMIT && LIMIT != -1 {
			log.Print("Max number of issues created")
			return false
		}
		issueExists := containsOpenIssue(href, addressedRepositories)
		if issueExists {
			log.Printf("issue already exists for %s\n", href)
		} else {
			isGithubRepo := reGithubRepo.MatchString(href)
			if isGithubRepo {
				isRepoAdded := testRepoState(true, href, client, &staleRepos)
				isRepoAdded = testCommitAge(!isRepoAdded, href, client, &staleRepos)
				if isRepoAdded {
					ctr++
				}
			} else {
				log.Printf("%s non-github repo not currently handled", href)
			}
		}
		return true
	})
	createIssue(staleRepos, client)
}

func main() {
	testStaleRepository()
}
<|endoftext|>


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

package py

// #include "utils.h"
// static inline void incref(PyObject *obj) { Py_INCREF(obj); }
// static inline void decref(PyObject *obj) { Py_DECREF(obj); }
// static inline void xdecref(PyObject *obj) { Py_XDECREF(obj); }
import "C"

import (
	"fmt"
	"os"
	"unsafe"
)

type Error struct {
	kind *C.PyObject
	tb   *C.PyObject
	val  *C.PyObject
}

func (e *Error) String() string {
	ts := ""
	en := C.excName(e.kind)
	if en.c == nil {
		tpyS := C.PyObject_Str(e.kind)
		defer C.decref(tpyS)
		ts = C.GoString(C.PyString_AsString(tpyS))
	} else {
		if en.m != nil {
			ts = C.GoString(en.m) + "."
		}
		ts += C.GoString(en.c)
	}

	pyS := C.PyObject_Str(e.val)
	defer C.decref(pyS)
	s := C.GoString(C.PyString_AsString(pyS))

	return fmt.Sprintf("%s: %s", ts, s)
}

func exceptionRaised() bool {
	return C.PyErr_Occurred() != nil
}

func exception() os.Error {
	if C.PyErr_Occurred() == nil {
		return nil
	}

	var t, v, tb *C.PyObject

	defer C.xdecref(v)

	C.PyErr_Fetch(&t, &v, &tb)

	return &Error{t, tb, v}
}

func raise(err os.Error) {
	var val *C.PyObject
	var exc = C.PyExc_Exception

	e, ok := err.(*Error)
	if ok {
		exc = e.kind
		val = e.val
	} else {
		v, _ := NewString(err.String())
		val = c(v)
	}

	C.PyErr_SetObject(exc, val)
}

func Err_Format(f string, args ...interface{}) {
	s := C.CString(fmt.Sprintf(f, args))
	defer C.free(unsafe.Pointer(s))
	C.PyErr_SetString(C.PyExc_Exception, s)
}

func TypeError(format string, args ...interface{}) os.Error {
	msg := fmt.Sprintf(format, args...)
	val, _ := NewString(msg)
	C.incref(C.PyExc_TypeError)
	return &Error{C.PyExc_TypeError, nil, c(val)}
}

func KeyError(format string, args ...interface{}) os.Error {
	msg := fmt.Sprintf(format, args...)
	val, _ := NewString(msg)
	C.incref(C.PyExc_KeyError)
	return &Error{C.PyExc_TypeError, nil, c(val)}
}

func AttributeError(format string, args ...interface{}) os.Error {
	msg := fmt.Sprintf(format, args...)
	val, _ := NewString(msg)
	C.incref(C.PyExc_AttributeError)
	return &Error{C.PyExc_TypeError, nil, c(val)}
}

func NotImplemented(format string, args ...interface{}) os.Error {
	msg := fmt.Sprintf(format, args...)
	val, _ := NewString(msg)
	C.incref(C.PyExc_NotImplementedError)
	return &Error{C.PyExc_TypeError, nil, c(val)}
}

func int2Err(i C.int) os.Error {
	if i < 0 {
		return exception()
	}
	return nil
}

func int2BoolErr(i C.int) (bool, os.Error) {
	if i < 0 {
		return false, exception()
	}
	return i > 0, nil
}

func ssize_t2Int64Err(s C.Py_ssize_t) (int64, os.Error) {
	if s < 0 {
		return 0, exception()
	}
	return int64(s), nil
}

func obj2ObjErr(obj *C.PyObject) (Object, os.Error) {
	if obj == nil {
		return nil, exception()
	}
	return newObject(obj), nil
}
<commit_msg>Fix silly copy/paste error<commit_after>// Copyright 2011 Julian Phillips.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package py

// #include "utils.h"
// static inline void incref(PyObject *obj) { Py_INCREF(obj); }
// static inline void decref(PyObject *obj) { Py_DECREF(obj); }
// static inline void xdecref(PyObject *obj) { Py_XDECREF(obj); }
import "C"

import (
	"fmt"
	"os"
	"unsafe"
)

type Error struct {
	kind *C.PyObject
	tb   *C.PyObject
	val  *C.PyObject
}

func (e *Error) String() string {
	ts := ""
	en := C.excName(e.kind)
	if en.c == nil {
		tpyS := C.PyObject_Str(e.kind)
		defer C.decref(tpyS)
		ts = C.GoString(C.PyString_AsString(tpyS))
	} else {
		if en.m != nil {
			ts = C.GoString(en.m) + "."
		}
		ts += C.GoString(en.c)
	}

	pyS := C.PyObject_Str(e.val)
	defer C.decref(pyS)
	s := C.GoString(C.PyString_AsString(pyS))

	return fmt.Sprintf("%s: %s", ts, s)
}

func exceptionRaised() bool {
	return C.PyErr_Occurred() != nil
}

func exception() os.Error {
	if C.PyErr_Occurred() == nil {
		return nil
	}

	var t, v, tb *C.PyObject

	defer C.xdecref(v)

	C.PyErr_Fetch(&t, &v, &tb)

	return &Error{t, tb, v}
}

func raise(err os.Error) {
	var val *C.PyObject
	var exc = C.PyExc_Exception

	e, ok := err.(*Error)
	if ok {
		exc = e.kind
		val = e.val
	} else {
		v, _ := NewString(err.String())
		val = c(v)
	}

	C.PyErr_SetObject(exc, val)
}

func Err_Format(f string, args ...interface{}) {
	s := C.CString(fmt.Sprintf(f, args))
	defer C.free(unsafe.Pointer(s))
	C.PyErr_SetString(C.PyExc_Exception, s)
}

func TypeError(format string, args ...interface{}) os.Error {
	msg := fmt.Sprintf(format, args...)
	val, _ := NewString(msg)
	C.incref(C.PyExc_TypeError)
	return &Error{C.PyExc_TypeError, nil, c(val)}
}

func KeyError(format string, args ...interface{}) os.Error {
	msg := fmt.Sprintf(format, args...)
	val, _ := NewString(msg)
	C.incref(C.PyExc_KeyError)
	return &Error{C.PyExc_KeyError, nil, c(val)}
}

func AttributeError(format string, args ...interface{}) os.Error {
	msg := fmt.Sprintf(format, args...)
	val, _ := NewString(msg)
	C.incref(C.PyExc_AttributeError)
	return &Error{C.PyExc_AttributeError, nil, c(val)}
}

func NotImplemented(format string, args ...interface{}) os.Error {
	msg := fmt.Sprintf(format, args...)
	val, _ := NewString(msg)
	C.incref(C.PyExc_NotImplementedError)
	return &Error{C.PyExc_NotImplementedError, nil, c(val)}
}

func int2Err(i C.int) os.Error {
	if i < 0 {
		return exception()
	}
	return nil
}

func int2BoolErr(i C.int) (bool, os.Error) {
	if i < 0 {
		return false, exception()
	}
	return i > 0, nil
}

func ssize_t2Int64Err(s C.Py_ssize_t) (int64, os.Error) {
	if s < 0 {
		return 0, exception()
	}
	return int64(s), nil
}

func obj2ObjErr(obj *C.PyObject) (Object, os.Error) {
	if obj == nil {
		return nil, exception()
	}
	return newObject(obj), nil
}
<|endoftext|>


<commit_before>// Copyright 2017 Istio Authors
//
// 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 util

import (
	"bytes"
	"log"
	"net"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/golang/protobuf/ptypes"

	"istio.io/istio/pilot/pkg/bootstrap"
	envoy "istio.io/istio/pilot/pkg/proxy/envoy/v1"
	"istio.io/istio/pilot/pkg/serviceregistry"
)

var (
	// MockTestServer is used for the unit tests. Will be started once, terminated at the
	// end of the suite.
	MockTestServer *bootstrap.Server

	// MockPilotURL is the URL for the pilot http endpoint
	MockPilotURL string

	// MockPilotGrpcAddr is the address to be used for grpc connections.
	MockPilotGrpcAddr string

	// MockPilotSecureAddr is the address to be used for secure grpc connections.
	MockPilotSecureAddr string

	// MockPilotSecurePort is the secure port
	MockPilotSecurePort int

	// MockPilotHTTPPort is the dynamic port for pilot http
	MockPilotHTTPPort int

	// MockPilotGrpcPort is the dynamic port for pilot grpc
	MockPilotGrpcPort int

	fsRoot string
	stop   chan struct{}
)

var (
	// IstioTop has the top of the istio tree, matches the env variable from make.
	IstioTop = os.Getenv("TOP")

	// IstioSrc is the location if istio source ($TOP/src/istio.io/istio
	IstioSrc = os.Getenv("ISTIO_GO")

	// IstioBin is the location of the binary output directory
	IstioBin = os.Getenv("ISTIO_BIN")

	// IstioOut is the location of the output directory ($TOP/out)
	IstioOut = os.Getenv("ISTIO_OUT")

	// EnvoyOutWriter captures envoy output
	// Redirect out and err from envoy to buffer - coverage tests get confused if we write to out.
	// TODO: use files
	EnvoyOutWriter bytes.Buffer

	// EnvoyErrWriter captures envoy errors
	EnvoyErrWriter bytes.Buffer
)

func init() {
	if IstioTop == "" {
		// Assume it is run inside istio.io/istio
		current, _ := os.Getwd()
		idx := strings.Index(current, "/src/istio.io/istio")
		if idx > 0 {
			IstioTop = current[0:idx]
		} else {
			IstioTop = current // launching from GOTOP (for example in goland)
		}
	}
	if IstioSrc == "" {
		IstioSrc = IstioTop + "/src/istio.io/istio"
	}
	if IstioOut == "" {
		IstioOut = IstioTop + "/out"
	}
	if IstioBin == "" {
		IstioBin = IstioTop + "/out/" + runtime.GOOS + "_" + runtime.GOARCH + "/release"
	}
}

// EnsureTestServer will ensure a pilot server is running in process and initializes
// the MockPilotUrl and MockPilotGrpcAddr to allow connections to the test pilot.
func EnsureTestServer() *bootstrap.Server {
	if MockTestServer == nil {
		err := setup()
		if err != nil {
			log.Fatal("Failed to start in-process server", err)
		}
	}
	return MockTestServer
}

func setup() error {
	// TODO: point to test data directory
	// Setting FileDir (--configDir) disables k8s client initialization, including for registries,
	// and uses a 100ms scan. Must be used with the mock registry (or one of the others)
	// This limits the options -
	stop = make(chan struct{})

	// When debugging a test or running locally it helps having a static port for /debug
	// "0" is used on shared environment (it's not actually clear if such thing exists since
	// we run the tests in isolated VMs)
	pilotHTTP := os.Getenv("PILOT_HTTP")
	if len(pilotHTTP) == 0 {
		pilotHTTP = "0"
	}
	httpAddr := ":" + pilotHTTP

	_, meshConfig, _ := bootstrap.GetMeshConfig(nil, "not used", "not used")
	meshConfig.AccessLogFile = "/tmp/envoy-access.log" // TODO take value from TestSetup.AccessLogPath, needs refactoring to avoid import cycle
	//TODO: start mixer first, get its address
	meshConfig.MixerCheckServer = "istio-mixer.istio-system:9091"
	meshConfig.MixerReportServer = "istio-mixer.istio-system:9091"
	meshConfig.RdsRefreshDelay = ptypes.DurationProto(10 * time.Millisecond)

	// Create a test pilot discovery service configured to watch the tempDir.
	args := bootstrap.PilotArgs{
		Namespace: "testing",
		DiscoveryOptions: envoy.DiscoveryServiceOptions{
			HTTPAddr:        httpAddr,
			GrpcAddr:        ":0",
			SecureGrpcAddr:  ":0",
			EnableCaching:   true,
			EnableProfiling: true,
		},
		MeshConfig: meshConfig,
		Config: bootstrap.ConfigArgs{
			KubeConfig: IstioSrc + "/.circleci/config",
		},
		Service: bootstrap.ServiceArgs{
			// Using the Mock service registry, which provides the hello and world services.
			Registries: []string{
				string(serviceregistry.MockRegistry)},
		},
	}
	// Static testdata, should include all configs we want to test.
	args.Config.FileDir = IstioSrc + "/tests/testdata/config"

	bootstrap.PilotCertDir = IstioSrc + "/tests/testdata/certs/pilot"

	// Create and setup the controller.
	s, err := bootstrap.NewServer(args)
	if err != nil {
		return err
	}

	MockTestServer = s

	// Start the server.
	_, err = s.Start(stop)
	if err != nil {
		return err
	}

	// Extract the port from the network address.
	_, port, err := net.SplitHostPort(s.HTTPListeningAddr.String())
	if err != nil {
		return err
	}
	MockPilotURL = "http://localhost:" + port
	MockPilotHTTPPort, _ = strconv.Atoi(port)

	_, port, err = net.SplitHostPort(s.GRPCListeningAddr.String())
	if err != nil {
		return err
	}
	MockPilotGrpcAddr = "localhost:" + port
	MockPilotGrpcPort, _ = strconv.Atoi(port)

	_, port, err = net.SplitHostPort(s.SecureGRPCListeningAddr.String())
	if err != nil {
		return err
	}
	MockPilotSecureAddr = "localhost:" + port
	MockPilotSecurePort, _ = strconv.Atoi(port)

	// Wait a bit for the server to come up.
	// TODO(nmittler): Change to polling health endpoint once https://github.com/istio/istio/pull/2002 lands.
	time.Sleep(time.Second)

	return nil
}

// Teardown will cleanup the temp dir and remove the test data.
func Teardown() {
	close(stop)

	// Remove the temp dir.
	_ = os.RemoveAll(fsRoot)
}
<commit_msg>Revert "Fix xds_test on MacOS by configuring ... (#5779)" (#6256)<commit_after>// Copyright 2017 Istio Authors
//
// 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 util

import (
	"bytes"
	"log"
	"net"
	"os"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/golang/protobuf/ptypes"

	"istio.io/istio/pilot/pkg/bootstrap"
	envoy "istio.io/istio/pilot/pkg/proxy/envoy/v1"
	"istio.io/istio/pilot/pkg/serviceregistry"
)

var (
	// MockTestServer is used for the unit tests. Will be started once, terminated at the
	// end of the suite.
	MockTestServer *bootstrap.Server

	// MockPilotURL is the URL for the pilot http endpoint
	MockPilotURL string

	// MockPilotGrpcAddr is the address to be used for grpc connections.
	MockPilotGrpcAddr string

	// MockPilotSecureAddr is the address to be used for secure grpc connections.
	MockPilotSecureAddr string

	// MockPilotSecurePort is the secure port
	MockPilotSecurePort int

	// MockPilotHTTPPort is the dynamic port for pilot http
	MockPilotHTTPPort int

	// MockPilotGrpcPort is the dynamic port for pilot grpc
	MockPilotGrpcPort int

	fsRoot string
	stop   chan struct{}
)

var (
	// IstioTop has the top of the istio tree, matches the env variable from make.
	IstioTop = os.Getenv("TOP")

	// IstioSrc is the location if istio source ($TOP/src/istio.io/istio
	IstioSrc = os.Getenv("ISTIO_GO")

	// IstioBin is the location of the binary output directory
	IstioBin = os.Getenv("ISTIO_BIN")

	// IstioOut is the location of the output directory ($TOP/out)
	IstioOut = os.Getenv("ISTIO_OUT")

	// EnvoyOutWriter captures envoy output
	// Redirect out and err from envoy to buffer - coverage tests get confused if we write to out.
	// TODO: use files
	EnvoyOutWriter bytes.Buffer

	// EnvoyErrWriter captures envoy errors
	EnvoyErrWriter bytes.Buffer
)

func init() {
	if IstioTop == "" {
		// Assume it is run inside istio.io/istio
		current, _ := os.Getwd()
		idx := strings.Index(current, "/src/istio.io/istio")
		if idx > 0 {
			IstioTop = current[0:idx]
		} else {
			IstioTop = current // launching from GOTOP (for example in goland)
		}
	}
	if IstioSrc == "" {
		IstioSrc = IstioTop + "/src/istio.io/istio"
	}
	if IstioOut == "" {
		IstioOut = IstioTop + "/out"
	}
	if IstioBin == "" {
		IstioBin = IstioTop + "/out/" + runtime.GOOS + "_" + runtime.GOARCH + "/release"
	}
}

// EnsureTestServer will ensure a pilot server is running in process and initializes
// the MockPilotUrl and MockPilotGrpcAddr to allow connections to the test pilot.
func EnsureTestServer() *bootstrap.Server {
	if MockTestServer == nil {
		err := setup()
		if err != nil {
			log.Fatal("Failed to start in-process server", err)
		}
	}
	return MockTestServer
}

func setup() error {
	// TODO: point to test data directory
	// Setting FileDir (--configDir) disables k8s client initialization, including for registries,
	// and uses a 100ms scan. Must be used with the mock registry (or one of the others)
	// This limits the options -
	stop = make(chan struct{})

	// When debugging a test or running locally it helps having a static port for /debug
	// "0" is used on shared environment (it's not actually clear if such thing exists since
	// we run the tests in isolated VMs)
	pilotHTTP := os.Getenv("PILOT_HTTP")
	if len(pilotHTTP) == 0 {
		pilotHTTP = "0"
	}
	httpAddr := ":" + pilotHTTP

	// Create a test pilot discovery service configured to watch the tempDir.
	args := bootstrap.PilotArgs{
		Namespace: "testing",
		DiscoveryOptions: envoy.DiscoveryServiceOptions{
			HTTPAddr:        httpAddr,
			GrpcAddr:        ":0",
			SecureGrpcAddr:  ":0",
			EnableCaching:   true,
			EnableProfiling: true,
		},
		//TODO: start mixer first, get its address
		Mesh: bootstrap.MeshArgs{
			MixerAddress:    "istio-mixer.istio-system:9091",
			RdsRefreshDelay: ptypes.DurationProto(10 * time.Millisecond),
		},
		Config: bootstrap.ConfigArgs{
			KubeConfig: IstioSrc + "/.circleci/config",
		},
		Service: bootstrap.ServiceArgs{
			// Using the Mock service registry, which provides the hello and world services.
			Registries: []string{
				string(serviceregistry.MockRegistry)},
		},
	}
	// Static testdata, should include all configs we want to test.
	args.Config.FileDir = IstioSrc + "/tests/testdata/config"

	bootstrap.PilotCertDir = IstioSrc + "/tests/testdata/certs/pilot"

	// Create and setup the controller.
	s, err := bootstrap.NewServer(args)
	if err != nil {
		return err
	}

	MockTestServer = s

	// Start the server.
	_, err = s.Start(stop)
	if err != nil {
		return err
	}

	// Extract the port from the network address.
	_, port, err := net.SplitHostPort(s.HTTPListeningAddr.String())
	if err != nil {
		return err
	}
	MockPilotURL = "http://localhost:" + port
	MockPilotHTTPPort, _ = strconv.Atoi(port)

	_, port, err = net.SplitHostPort(s.GRPCListeningAddr.String())
	if err != nil {
		return err
	}
	MockPilotGrpcAddr = "localhost:" + port
	MockPilotGrpcPort, _ = strconv.Atoi(port)

	_, port, err = net.SplitHostPort(s.SecureGRPCListeningAddr.String())
	if err != nil {
		return err
	}
	MockPilotSecureAddr = "localhost:" + port
	MockPilotSecurePort, _ = strconv.Atoi(port)

	// Wait a bit for the server to come up.
	// TODO(nmittler): Change to polling health endpoint once https://github.com/istio/istio/pull/2002 lands.
	time.Sleep(time.Second)

	return nil
}

// Teardown will cleanup the temp dir and remove the test data.
func Teardown() {
	close(stop)

	// Remove the temp dir.
	_ = os.RemoveAll(fsRoot)
}
<|endoftext|>


<commit_before>/*
 * This file is part of the kubevirt project
 *
 * 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.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package tests_test

import (
	expect "github.com/google/goexpect"
	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"

	"kubevirt.io/kubevirt/tests/framework/checks"

	v1 "kubevirt.io/api/core/v1"

	"kubevirt.io/kubevirt/tests"
	"kubevirt.io/kubevirt/tests/console"
	"kubevirt.io/kubevirt/tests/libvmi"
)

var _ = Describe("[rfe_id:151][crit:high][vendor:cnv-qe@redhat.com][level:component][sig-compute]IgnitionData", func() {

	BeforeEach(func() {
		if !checks.HasFeature("ExperimentalIgnitionSupport") {
			Skip("ExperimentalIgnitionSupport feature gate is not enabled in kubevirt-config")
		}
	})

	Describe("[rfe_id:151][crit:medium][vendor:cnv-qe@redhat.com][level:component]A new VirtualMachineInstance", func() {
		Context("with IgnitionData annotation", func() {
			Context("with injected data", func() {
				It("[test_id:1616]should have injected data under firmware directory", func() {
					ignitionData := "ignition injected"
					vmi := tests.RunVMIAndExpectLaunch(
						libvmi.NewFedora(libvmi.WithAnnotation(v1.IgnitionAnnotation, ignitionData)),
						240)

					Expect(console.SafeExpectBatch(vmi, []expect.Batcher{
						&expect.BSnd{S: "\n"},
						&expect.BExp{R: "login:"},
						&expect.BSnd{S: "fedora\n"},
						&expect.BExp{R: "Password:"},
						&expect.BSnd{S: "fedora" + "\n"},
						&expect.BExp{R: console.PromptExpression},
						&expect.BSnd{S: "ls /sys/firmware/qemu_fw_cfg/by_name/opt/com.coreos/config\n"},
						&expect.BExp{R: "raw"},
					}, 300)).To(Succeed())
				})
			})
		})

	})
})
<commit_msg>vmi_ignition_test: reuse console.LoginToFedora<commit_after>/*
 * This file is part of the kubevirt project
 *
 * 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.
 *
 * Copyright 2017 Red Hat, Inc.
 *
 */

package tests_test

import (
	expect "github.com/google/goexpect"
	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"

	"kubevirt.io/kubevirt/tests/framework/checks"

	v1 "kubevirt.io/api/core/v1"

	"kubevirt.io/kubevirt/tests"
	"kubevirt.io/kubevirt/tests/console"
	"kubevirt.io/kubevirt/tests/libvmi"
)

var _ = Describe("[rfe_id:151][crit:high][vendor:cnv-qe@redhat.com][level:component][sig-compute]IgnitionData", func() {

	BeforeEach(func() {
		if !checks.HasFeature("ExperimentalIgnitionSupport") {
			Skip("ExperimentalIgnitionSupport feature gate is not enabled in kubevirt-config")
		}
	})

	Describe("[rfe_id:151][crit:medium][vendor:cnv-qe@redhat.com][level:component]A new VirtualMachineInstance", func() {
		Context("with IgnitionData annotation", func() {
			Context("with injected data", func() {
				It("[test_id:1616]should have injected data under firmware directory", func() {
					ignitionData := "ignition injected"
					vmi := tests.RunVMIAndExpectLaunch(
						libvmi.NewFedora(libvmi.WithAnnotation(v1.IgnitionAnnotation, ignitionData)),
						240)

					Expect(console.LoginToFedora(vmi)).To(Succeed())
					Expect(console.SafeExpectBatch(vmi, []expect.Batcher{
						&expect.BSnd{S: "ls /sys/firmware/qemu_fw_cfg/by_name/opt/com.coreos/config\n"},
						&expect.BExp{R: "raw"},
					}, 300)).To(Succeed())
				})
			})
		})

	})
})
<|endoftext|>


<commit_before>package libvirt

import (
	"github.com/alexzorin/libvirt-go"
	"github.com/mistifyio/mistify-agent/rpc"
	"github.com/mistifyio/mistify-agent/client"
	"syscall"
	"net/http"
	"runtime"
	"fmt"
)

type (
	Libvirt struct {
		uri         string
		connections chan *libvirt.VirConnection
		max         int
	}

	Domain struct {
		*libvirt.VirDomain
		State int
	}
)

func NewLibvirt(uri string, max int) (*Libvirt, error) {
	lv := &Libvirt{
		uri:         uri,
		max:         max,
		connections: make(chan *libvirt.VirConnection, max),
	}

	for i := 0; i < max; i++ {
		v, err := libvirt.NewVirConnection(uri)
		if err != nil {
			return nil, err
		}
		lv.connections <- &v
	}

	return lv, nil
}

func (lv *Libvirt) RunHTTP(port uint) error {
	server, err := rpc.NewServer(int(port))
	if err != nil {
		return err
	}

	server.RegisterService(lv)
	return server.ListenAndServe()
}

func newDomain(vDom *libvirt.VirDomain) (*Domain, error) {
	domain := &Domain{
		VirDomain: vDom,
	}
	runtime.SetFinalizer(domain, func(domain *Domain) {
		domain.Free()
	})

	state, err := vDom.GetState()
	if err != nil {
		return nil, err
	}

	domain.State = state[0]
	return domain, nil
}

func (d *Domain) Free() {
	if d.VirDomain != nil {
		d.VirDomain.Free()
		d.VirDomain = nil
	}
}

func (lv *Libvirt) getConnection() *libvirt.VirConnection {
	conn := <-lv.connections
	defer func() {
		lv.connections <- conn
	}()

	return conn
}

func (lv *Libvirt) LookupDomainByName(name string) (*Domain, error) {
	conn := lv.getConnection()

	vDom, err := conn.LookupDomainByName(name)
	if err != nil {
		return nil, err
	}

	return newDomain(&vDom)
}

func (lv *Libvirt) NewDomain(guest *client.Guest) (*Domain, error) {
	conn := lv.getConnection()

	vDom, err := conn.DomainDefineXML(fmt.Sprintf(`<domain type="test"><name>%s</name><memory unit="MiB">%d</memory><os><type>hvm</type></os></domain>`, guest.Id, guest.Memory))
	if err != nil {
		return nil, err
	}

	return newDomain(&vDom)
}

func (lv *Libvirt) DomainWrapper(fn func(*Domain) error) func(*http.Request, *rpc.GuestRequest, *rpc.GuestResponse) error {
	return func(r *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
		if request.Guest == nil || request.Guest.Id == "" {
			return syscall.EINVAL
		}

		domain, err := lv.LookupDomainByName(request.Guest.Id)
		if err != nil {
			return err
		}

		err = fn(domain)
		if err != nil {
			return err
		}

		*response = rpc.GuestResponse{
			Guest: request.Guest,
		}
		return nil
	}
}

func (lv *Libvirt) Create(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	domain, err := lv.NewDomain(request.Guest)
	if err != nil {
		return err
	}

	err = domain.Create()
	if err != nil {
		return err
	}

	*response = rpc.GuestResponse{
		Guest: request.Guest,
	}

	return nil
}

func (lv *Libvirt) Reboot(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.DomainWrapper(func(domain *Domain) error {
		return domain.Reboot(0)
	})(http, request, response)
}

func (lv *Libvirt) Run(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.DomainWrapper(func(domain *Domain) error {

		switch domain.State {

		case libvirt.VIR_DOMAIN_RUNNING:
			// nothing to do

		case libvirt.VIR_DOMAIN_SHUTDOWN, libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_BLOCKED, libvirt.VIR_DOMAIN_NOSTATE:
			return domain.Create()

		case libvirt.VIR_DOMAIN_PAUSED, libvirt.VIR_DOMAIN_PMSUSPENDED:
			return domain.Resume()
		}

		return nil
	})(http, request, response)
}

func (lv *Libvirt) Shutdown(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.DomainWrapper(func(domain *Domain) error {

		switch domain.State {
		case libvirt.VIR_DOMAIN_SHUTDOWN, libvirt.VIR_DOMAIN_SHUTOFF:
			// nothing to do

		default:
			return domain.Shutdown()
		}

		return nil
	})(http, request, response)

}
<commit_msg>MIST-138: add stubs for remaining functions<commit_after>package libvirt

import (
	"github.com/alexzorin/libvirt-go"
	"github.com/mistifyio/mistify-agent/rpc"
	"github.com/mistifyio/mistify-agent/client"
	"syscall"
	"net/http"
	"runtime"
	"fmt"
)

type (
	Libvirt struct {
		uri         string
		connections chan *libvirt.VirConnection
		max         int
	}

	Domain struct {
		*libvirt.VirDomain
		State int
	}
)

func NewLibvirt(uri string, max int) (*Libvirt, error) {
	lv := &Libvirt{
		uri:         uri,
		max:         max,
		connections: make(chan *libvirt.VirConnection, max),
	}

	for i := 0; i < max; i++ {
		v, err := libvirt.NewVirConnection(uri)
		if err != nil {
			return nil, err
		}
		lv.connections <- &v
	}

	return lv, nil
}

func (lv *Libvirt) RunHTTP(port uint) error {
	server, err := rpc.NewServer(int(port))
	if err != nil {
		return err
	}

	server.RegisterService(lv)
	return server.ListenAndServe()
}

func newDomain(vDom *libvirt.VirDomain) (*Domain, error) {
	domain := &Domain{
		VirDomain: vDom,
	}
	runtime.SetFinalizer(domain, func(domain *Domain) {
		domain.Free()
	})

	state, err := vDom.GetState()
	if err != nil {
		return nil, err
	}

	domain.State = state[0]
	return domain, nil
}

func (d *Domain) Free() {
	if d.VirDomain != nil {
		d.VirDomain.Free()
		d.VirDomain = nil
	}
}

func (lv *Libvirt) getConnection() *libvirt.VirConnection {
	conn := <-lv.connections
	defer func() {
		lv.connections <- conn
	}()

	return conn
}

func (lv *Libvirt) LookupDomainByName(name string) (*Domain, error) {
	conn := lv.getConnection()

	vDom, err := conn.LookupDomainByName(name)
	if err != nil {
		return nil, err
	}

	return newDomain(&vDom)
}

func (lv *Libvirt) NewDomain(guest *client.Guest) (*Domain, error) {
	conn := lv.getConnection()

	vDom, err := conn.DomainDefineXML(fmt.Sprintf(`<domain type="test"><name>%s</name><memory unit="MiB">%d</memory><os><type>hvm</type></os></domain>`, guest.Id, guest.Memory))
	if err != nil {
		return nil, err
	}

	return newDomain(&vDom)
}

func (lv *Libvirt) DomainWrapper(fn func(*Domain) error) func(*http.Request, *rpc.GuestRequest, *rpc.GuestResponse) error {
	return func(r *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
		if request.Guest == nil || request.Guest.Id == "" {
			return syscall.EINVAL
		}

		domain, err := lv.LookupDomainByName(request.Guest.Id)
		if err != nil {
			return err
		}

		err = fn(domain)
		if err != nil {
			return err
		}

		*response = rpc.GuestResponse{
			Guest: request.Guest,
		}
		return nil
	}
}

// Guest Actions

func (lv *Libvirt) Restart(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.Reboot(http, request, response)
}

func (lv *Libvirt) Poweroff(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.Shutdown(http, request, response)
}

func (lv *Libvirt) Delete(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.DomainWrapper(func(domain *Domain) error {
		return domain.Destroy()
	})(http, request, response)
}

func (lv *Libvirt) Create(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	domain, err := lv.NewDomain(request.Guest)
	if err != nil {
		return err
	}

	err = domain.Create()
	if err != nil {
		return err
	}

	*response = rpc.GuestResponse{
		Guest: request.Guest,
	}

	return nil
}

func (lv *Libvirt) Run(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.DomainWrapper(func(domain *Domain) error {

		switch domain.State {

		case libvirt.VIR_DOMAIN_RUNNING:
			// nothing to do

		case libvirt.VIR_DOMAIN_SHUTDOWN, libvirt.VIR_DOMAIN_SHUTOFF, libvirt.VIR_DOMAIN_BLOCKED, libvirt.VIR_DOMAIN_NOSTATE:
			return domain.Create()

		case libvirt.VIR_DOMAIN_PAUSED, libvirt.VIR_DOMAIN_PMSUSPENDED:
			return domain.Resume()
		}

		return nil
	})(http, request, response)
}

func (lv *Libvirt) Reboot(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.DomainWrapper(func(domain *Domain) error {
		return domain.Reboot(0)
	})(http, request, response)
}

func (lv *Libvirt) Shutdown(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
	return lv.DomainWrapper(func(domain *Domain) error {

		switch domain.State {
		case libvirt.VIR_DOMAIN_SHUTDOWN, libvirt.VIR_DOMAIN_SHUTOFF:
			// nothing to do

		default:
			return domain.Shutdown()
		}

		return nil
	})(http, request, response)
}

/*
func (lv *Libvirt) CpuMetrics(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
}

func (lv *Libvirt) DiskMetrics(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
}

func (lv *Libvirt) NicMetrics(http *http.Request, request *rpc.GuestRequest, response *rpc.GuestResponse) error {
}
*/
<|endoftext|>


<commit_before>package stor

import (
	"github.com/zero-os/0-Disk/config"
	"github.com/zero-os/0-Disk/log"
)

// ConfigFromConfigSource creates tlog stor client config from config.Source
func ConfigFromConfigSource(source config.Source, vdiskID, privKey string, dataShards, parityShards int) (conf Config, err error) {
	// read vdisk config
	vdiskConf, err := config.ReadVdiskTlogConfig(source, vdiskID)
	if err != nil {
		log.Errorf("failed to read vdisk tlog config for vdisk `%v`: %v", vdiskID, err)
		return
	}

	// read zerostor config of this vdisk
	zsc, err := config.ReadZeroStoreClusterConfig(source, vdiskConf.ZeroStorClusterID)
	if err != nil {
		log.Errorf("failed to read ZeroStorCluster config for vdisk `%v`: %v", vdiskID, err)
		return
	}

	// creates stor config
	serverAddrs := func() (addrs []string) {
		for _, s := range zsc.Servers {
			addrs = append(addrs, s.Address)
		}
		return
	}()

	metaServerAddrs := func() (addrs []string) {
		for _, s := range zsc.MetadataServers {
			addrs = append(addrs, s.Address)
		}
		return
	}()

	return Config{
		VdiskID:         vdiskID,
		Organization:    zsc.IYO.Org,
		Namespace:       zsc.IYO.Namespace,
		IyoClientID:     zsc.IYO.ClientID,
		IyoSecret:       zsc.IYO.Secret,
		ZeroStorShards:  serverAddrs,
		MetaShards:      metaServerAddrs,
		DataShardsNum:   dataShards,
		ParityShardsNum: parityShards,
		EncryptPrivKey:  privKey,
	}, nil
}
<commit_msg>tlog : validate data+parity against given servers.<commit_after>package stor

import (
	"fmt"

	"github.com/zero-os/0-Disk/config"
	"github.com/zero-os/0-Disk/log"
)

// ConfigFromConfigSource creates tlog stor client config from config.Source
func ConfigFromConfigSource(source config.Source, vdiskID, privKey string, dataShards, parityShards int) (conf Config, err error) {
	// read vdisk config
	vdiskConf, err := config.ReadVdiskTlogConfig(source, vdiskID)
	if err != nil {
		log.Errorf("failed to read vdisk tlog config for vdisk `%v`: %v", vdiskID, err)
		return
	}

	// read zerostor config of this vdisk
	zsc, err := config.ReadZeroStoreClusterConfig(source, vdiskConf.ZeroStorClusterID)
	if err != nil {
		log.Errorf("failed to read ZeroStorCluster config for vdisk `%v`: %v", vdiskID, err)
		return
	}

	minServerNum := dataShards + parityShards
	serverNum := len(zsc.Servers)
	if minServerNum > len(zsc.Servers) {
		err = fmt.Errorf("number of zerostor servers (%v) is less than data + parity (%v)",
			serverNum, minServerNum)
		return
	}

	// creates stor config
	serverAddrs := func() (addrs []string) {
		for _, s := range zsc.Servers {
			addrs = append(addrs, s.Address)
		}
		return
	}()

	metaServerAddrs := func() (addrs []string) {
		for _, s := range zsc.MetadataServers {
			addrs = append(addrs, s.Address)
		}
		return
	}()

	return Config{
		VdiskID:         vdiskID,
		Organization:    zsc.IYO.Org,
		Namespace:       zsc.IYO.Namespace,
		IyoClientID:     zsc.IYO.ClientID,
		IyoSecret:       zsc.IYO.Secret,
		ZeroStorShards:  serverAddrs,
		MetaShards:      metaServerAddrs,
		DataShardsNum:   dataShards,
		ParityShardsNum: parityShards,
		EncryptPrivKey:  privKey,
	}, nil
}
<|endoftext|>


<commit_before>// log package supplies more advanced features than go orign log package.
//
// It supports log different level: trace, debug, info, warn, error, fatal.
//
// It also supports different log handlers which you can log to stdout, file, socket, etc...
//
// Use
//
//  import "github.com/siddontang/go/log"
//
//  //log with different level
//  log.Info("hello world")
//  log.Error("hello world")
//
//  //create a logger with specified handler
//  h := NewStreamHandler(os.Stdout)
//  l := log.NewDefault(h)
//  l.Info("hello world")
//
package log
<commit_msg>update document<commit_after>// log package supplies more advanced features than go orign log package.
//
// It supports log different level: trace, debug, info, warn, error, fatal.
//
// It also supports different log handlers which you can log to stdout, file, socket, etc...
//
// Use
//
//  import "github.com/siddontang/go/log"
//
//  //log with different level
//  log.Info("hello world")
//  log.Error("hello world")
//
//  //create a logger with specified handler
//  h := NewStreamHandler(os.Stdout)
//  l := log.NewDefault(h)
//  l.Info("hello world")
//  l.Infof("%s %d", "hello", 123)
//
package log
<|endoftext|>


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

package log

import (
	"log"
	"os"

	"github.com/getsentry/raven-go"
)

func init() {
	if sentryDSN := os.Getenv("SENTRY_DSN"); sentryDSN != "" {
		raven.SetDSN(sentryDSN)
	}
}

var lg *Logger

// Logger represents a logger
type Logger struct {
	lg *log.Logger
}

// Print writes an info in the log
func (l *Logger) Print(v ...interface{}) {
	l.lg.Print(v)
}

// Printf writes an info with format in the log
func (l *Logger) Printf(format string, v ...interface{}) {
	l.lg.Printf(format, v...)
}

// Error writes an error in the log
func (l *Logger) Error(err error) {
	raven.CaptureError(err, nil)
	l.Print(err)
}

// New returns a new Logger
func New() *Logger {
	return &Logger{lg: log.New(os.Stdout, "[autoscale] ", 0)}
}

// Log returns the Logger
func Log() *Logger {
	if lg == nil {
		lg = New()
	}
	return lg
}
<commit_msg>log: fix syntax<commit_after>// Copyright 2016 tsuru-autoscale authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package log

import (
	"log"
	"os"

	"github.com/getsentry/raven-go"
)

func init() {
	if sentryDSN := os.Getenv("SENTRY_DSN"); sentryDSN != "" {
		raven.SetDSN(sentryDSN)
	}
}

var lg *Logger

// Logger represents a logger
type Logger struct {
	lg *log.Logger
}

// Print writes an info in the log
func (l *Logger) Print(v ...interface{}) {
	l.lg.Print(v...)
}

// Printf writes an info with format in the log
func (l *Logger) Printf(format string, v ...interface{}) {
	l.lg.Printf(format, v...)
}

// Error writes an error in the log
func (l *Logger) Error(err error) {
	raven.CaptureError(err, nil)
	l.Print(err)
}

// New returns a new Logger
func New() *Logger {
	return &Logger{lg: log.New(os.Stdout, "[autoscale] ", 0)}
}

// Log returns the Logger
func Log() *Logger {
	if lg == nil {
		lg = New()
	}
	return lg
}
<|endoftext|>


<commit_before>/*
Copyright 2013 Google Inc.

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 lru implements an LRU cache.
package lru

import "container/list"

// Cache is an LRU cache. It is not safe for concurrent access.
type Cache struct {
	// MaxEntries is the maximum number of cache entries before
	// an item is evicted. Zero means no limit.
	MaxEntries int

	// OnEvicted optionally specificies a callback function to be
	// executed when an entry is purged from the cache.
	OnEvicted func(key Key, value interface{})

	ll    *list.List
	cache map[interface{}]*list.Element
}

// A Key may be any value that is comparable. See http://golang.org/ref/spec#Comparison_operators
type Key interface{}

type entry struct {
	key   Key
	value interface{}
}

// New creates a new Cache.
// If maxEntries is zero, the cache has no limit and it's assumed
// that eviction is done by the caller.
func New(maxEntries int) *Cache {
	return &Cache{
		MaxEntries: maxEntries,
		ll:         list.New(),
		cache:      make(map[interface{}]*list.Element),
	}
}

// Add adds a value to the cache.
func (c *Cache) Add(key Key, value interface{}) {
	if c.cache == nil {
		c.cache = make(map[interface{}]*list.Element)
		c.ll = list.New()
	}
	if ee, ok := c.cache[key]; ok {
		c.ll.MoveToFront(ee)
		ee.Value.(*entry).value = value
		return
	}
	ele := c.ll.PushFront(&entry{key, value})
	c.cache[key] = ele
	if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
		c.RemoveOldest()
	}
}

// Get looks up a key's value from the cache.
func (c *Cache) Get(key Key) (value interface{}, ok bool) {
	if c.cache == nil {
		return
	}
	if ele, hit := c.cache[key]; hit {
		c.ll.MoveToFront(ele)
		return ele.Value.(*entry).value, true
	}
	return
}

// Remove removes the provided key from the cache.
func (c *Cache) Remove(key Key) {
	if c.cache == nil {
		return
	}
	if ele, hit := c.cache[key]; hit {
		c.removeElement(ele)
	}
}

// RemoveOldest removes the oldest item from the cache.
func (c *Cache) RemoveOldest() {
	if c.cache == nil {
		return
	}
	ele := c.ll.Back()
	if ele != nil {
		c.removeElement(ele)
	}
}

func (c *Cache) removeElement(e *list.Element) {
	c.ll.Remove(e)
	kv := e.Value.(*entry)
	delete(c.cache, kv.key)
	if c.OnEvicted != nil {
		c.OnEvicted(kv.key, kv.value)
	}
}

// Len returns the number of items in the cache.
func (c *Cache) Len() int {
	if c.cache == nil {
		return 0
	}
	return c.ll.Len()
}

// clear purges all stored items from the cache.
func (c *Cache) clear() {
	if c.OnEvicted != nil {
		for _, e := range c.cache {
			kv := e.Value.(*entry)
			c.OnEvicted(kv.key, kv.value)
		}
	}
	c.ll = nil
	c.cache = nil
}
<commit_msg>Unexport lru.Cache.Remove<commit_after>/*
Copyright 2013 Google Inc.

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 lru implements an LRU cache.
package lru

import "container/list"

// Cache is an LRU cache. It is not safe for concurrent access.
type Cache struct {
	// MaxEntries is the maximum number of cache entries before
	// an item is evicted. Zero means no limit.
	MaxEntries int

	// OnEvicted optionally specificies a callback function to be
	// executed when an entry is purged from the cache.
	OnEvicted func(key Key, value interface{})

	ll    *list.List
	cache map[interface{}]*list.Element
}

// A Key may be any value that is comparable. See http://golang.org/ref/spec#Comparison_operators
type Key interface{}

type entry struct {
	key   Key
	value interface{}
}

// New creates a new Cache.
// If maxEntries is zero, the cache has no limit and it's assumed
// that eviction is done by the caller.
func New(maxEntries int) *Cache {
	return &Cache{
		MaxEntries: maxEntries,
		ll:         list.New(),
		cache:      make(map[interface{}]*list.Element),
	}
}

// Add adds a value to the cache.
func (c *Cache) Add(key Key, value interface{}) {
	if c.cache == nil {
		c.cache = make(map[interface{}]*list.Element)
		c.ll = list.New()
	}
	if ee, ok := c.cache[key]; ok {
		c.ll.MoveToFront(ee)
		ee.Value.(*entry).value = value
		return
	}
	ele := c.ll.PushFront(&entry{key, value})
	c.cache[key] = ele
	if c.MaxEntries != 0 && c.ll.Len() > c.MaxEntries {
		c.RemoveOldest()
	}
}

// Get looks up a key's value from the cache.
func (c *Cache) Get(key Key) (value interface{}, ok bool) {
	if c.cache == nil {
		return
	}
	if ele, hit := c.cache[key]; hit {
		c.ll.MoveToFront(ele)
		return ele.Value.(*entry).value, true
	}
	return
}

// remove removes the provided key from the cache.
func (c *Cache) remove(key Key) {
	if c.cache == nil {
		return
	}
	if ele, hit := c.cache[key]; hit {
		c.removeElement(ele)
	}
}

// RemoveOldest removes the oldest item from the cache.
func (c *Cache) RemoveOldest() {
	if c.cache == nil {
		return
	}
	ele := c.ll.Back()
	if ele != nil {
		c.removeElement(ele)
	}
}

func (c *Cache) removeElement(e *list.Element) {
	c.ll.Remove(e)
	kv := e.Value.(*entry)
	delete(c.cache, kv.key)
	if c.OnEvicted != nil {
		c.OnEvicted(kv.key, kv.value)
	}
}

// Len returns the number of items in the cache.
func (c *Cache) Len() int {
	if c.cache == nil {
		return 0
	}
	return c.ll.Len()
}

// clear purges all stored items from the cache.
func (c *Cache) clear() {
	if c.OnEvicted != nil {
		for _, e := range c.cache {
			kv := e.Value.(*entry)
			c.OnEvicted(kv.key, kv.value)
		}
	}
	c.ll = nil
	c.cache = nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Unknwon
//
// 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 macaron is a high productive and modular design web framework in Go.
package macaron

import (
	"io"
	"log"
	"net/http"
	"os"
	"reflect"
	"strings"

	"github.com/Unknwon/com"
	"gopkg.in/ini.v0"

	"github.com/Unknwon/macaron/inject"
)

const _VERSION = "0.4.9.1229"

func Version() string {
	return _VERSION
}

// Handler can be any callable function.
// Macaron attempts to inject services into the handler's argument list,
// and panics if an argument could not be fullfilled via dependency injection.
type Handler interface{}

// validateHandler makes sure a handler is a callable function,
// and panics if it is not.
func validateHandler(h Handler) {
	if reflect.TypeOf(h).Kind() != reflect.Func {
		panic("Macaron handler must be a callable function")
	}
}

// validateHandlers makes sure handlers are callable functions,
// and panics if any of them is not.
func validateHandlers(handlers []Handler) {
	for _, h := range handlers {
		validateHandler(h)
	}
}

// Macaron represents the top level web application.
// inject.Injector methods can be invoked to map services on a global level.
type Macaron struct {
	inject.Injector
	befores  []BeforeHandler
	handlers []Handler
	action   Handler

	urlPrefix string // For suburl support.
	*Router

	logger *log.Logger
}

// NewWithLogger creates a bare bones Macaron instance.
// Use this method if you want to have full control over the middleware that is used.
// You can specify logger output writer with this function.
func NewWithLogger(out io.Writer) *Macaron {
	m := &Macaron{
		Injector: inject.New(),
		action:   func() {},
		Router:   NewRouter(),
		logger:   log.New(out, "[Macaron] ", 0),
	}
	m.Router.m = m
	m.Map(m.logger)
	m.Map(defaultReturnHandler())
	m.notFound = func(resp http.ResponseWriter, req *http.Request) {
		c := m.createContext(resp, req)
		c.handlers = append(c.handlers, http.NotFound)
		c.run()
	}
	return m
}

// New creates a bare bones Macaron instance.
// Use this method if you want to have full control over the middleware that is used.
func New() *Macaron {
	return NewWithLogger(os.Stdout)
}

// Classic creates a classic Macaron with some basic default middleware:
// mocaron.Logger, mocaron.Recovery and mocaron.Static.
func Classic() *Macaron {
	m := New()
	m.Use(Logger())
	m.Use(Recovery())
	m.Use(Static("public"))
	return m
}

// Handlers sets the entire middleware stack with the given Handlers.
// This will clear any current middleware handlers,
// and panics if any of the handlers is not a callable function
func (m *Macaron) Handlers(handlers ...Handler) {
	m.handlers = make([]Handler, 0)
	for _, handler := range handlers {
		m.Use(handler)
	}
}

// Action sets the handler that will be called after all the middleware has been invoked.
// This is set to macaron.Router in a macaron.Classic().
func (m *Macaron) Action(handler Handler) {
	validateHandler(handler)
	m.action = handler
}

// BeforeHandler represents a handler executes at beginning of every request.
// Macaron stops future process when it returns true.
type BeforeHandler func(rw http.ResponseWriter, req *http.Request) bool

func (m *Macaron) Before(handler BeforeHandler) {
	m.befores = append(m.befores, handler)
}

// Use adds a middleware Handler to the stack,
// and panics if the handler is not a callable func.
// Middleware Handlers are invoked in the order that they are added.
func (m *Macaron) Use(handler Handler) {
	validateHandler(handler)
	m.handlers = append(m.handlers, handler)
}

func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Context {
	c := &Context{
		Injector: inject.New(),
		handlers: m.handlers,
		action:   m.action,
		index:    0,
		Router:   m.Router,
		Req:      Request{req},
		Resp:     NewResponseWriter(rw),
		Data:     make(map[string]interface{}),
	}
	c.SetParent(m)
	c.Map(c)
	c.MapTo(c.Resp, (*http.ResponseWriter)(nil))
	c.Map(req)
	return c
}

// ServeHTTP is the HTTP Entry point for a Macaron instance.
// Useful if you want to control your own HTTP server.
// Be aware that none of middleware will run without registering any router.
func (m *Macaron) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	req.URL.Path = strings.TrimPrefix(req.URL.Path, m.urlPrefix)
	for _, h := range m.befores {
		if h(rw, req) {
			return
		}
	}
	m.Router.ServeHTTP(rw, req)
}

func GetDefaultListenInfo() (string, int) {
	host := os.Getenv("HOST")
	if len(host) == 0 {
		host = "0.0.0.0"
	}
	port := com.StrTo(os.Getenv("PORT")).MustInt()
	if port == 0 {
		port = 4000
	}
	return host, port
}

// Run the http server. Listening on os.GetEnv("PORT") or 4000 by default.
func (m *Macaron) Run(args ...interface{}) {
	host, port := GetDefaultListenInfo()
	if len(args) == 1 {
		switch arg := args[0].(type) {
		case string:
			host = arg
		case int:
			port = arg
		}
	} else if len(args) >= 2 {
		if arg, ok := args[0].(string); ok {
			host = arg
		}
		if arg, ok := args[1].(int); ok {
			port = arg
		}
	}

	addr := host + ":" + com.ToStr(port)
	logger := m.Injector.GetVal(reflect.TypeOf(m.logger)).Interface().(*log.Logger)
	logger.Printf("listening on %s (%s)\n", addr, Env)
	logger.Fatalln(http.ListenAndServe(addr, m))
}

// SetURLPrefix sets URL prefix of router layer, so that it support suburl.
func (m *Macaron) SetURLPrefix(prefix string) {
	m.urlPrefix = prefix
}

// ____   ____            .__      ___.   .__
// \   \ /   /____ _______|__|____ \_ |__ |  |   ____   ______
//  \   Y   /\__  \\_  __ \  \__  \ | __ \|  | _/ __ \ /  ___/
//   \     /  / __ \|  | \/  |/ __ \| \_\ \  |_\  ___/ \___ \
//    \___/  (____  /__|  |__(____  /___  /____/\___  >____  >
//                \/              \/    \/          \/     \/

const (
	DEV  = "development"
	PROD = "production"
	TEST = "test"
)

var (
	// Env is the environment that Macaron is executing in.
	// The MACARON_ENV is read on initialization to set this variable.
	Env = DEV

	// Path of work directory.
	Root string

	// Flash applies to current request.
	FlashNow bool

	// Configuration convention object.
	cfg *ini.File
)

func setENV(e string) {
	if len(e) > 0 {
		Env = e
	}
}

func init() {
	setENV(os.Getenv("MACARON_ENV"))

	var err error
	Root, err = os.Getwd()
	if err != nil {
		panic("error getting work directory: " + err.Error())
	}
}

// SetConfig sets data sources for configuration.
func SetConfig(source interface{}, others ...interface{}) (err error) {
	cfg, err = ini.Load(source, others...)
	return err
}

// Config returns configuration convention object.
// It returns an empty object if there is no one available.
func Config() *ini.File {
	if cfg == nil {
		return &ini.File{}
	}
	return cfg
}
<commit_msg>update dep version<commit_after>// Copyright 2014 Unknwon
//
// 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 macaron is a high productive and modular design web framework in Go.
package macaron

import (
	"io"
	"log"
	"net/http"
	"os"
	"reflect"
	"strings"

	"github.com/Unknwon/com"
	"gopkg.in/ini.v1"

	"github.com/Unknwon/macaron/inject"
)

const _VERSION = "0.4.9.1229"

func Version() string {
	return _VERSION
}

// Handler can be any callable function.
// Macaron attempts to inject services into the handler's argument list,
// and panics if an argument could not be fullfilled via dependency injection.
type Handler interface{}

// validateHandler makes sure a handler is a callable function,
// and panics if it is not.
func validateHandler(h Handler) {
	if reflect.TypeOf(h).Kind() != reflect.Func {
		panic("Macaron handler must be a callable function")
	}
}

// validateHandlers makes sure handlers are callable functions,
// and panics if any of them is not.
func validateHandlers(handlers []Handler) {
	for _, h := range handlers {
		validateHandler(h)
	}
}

// Macaron represents the top level web application.
// inject.Injector methods can be invoked to map services on a global level.
type Macaron struct {
	inject.Injector
	befores  []BeforeHandler
	handlers []Handler
	action   Handler

	urlPrefix string // For suburl support.
	*Router

	logger *log.Logger
}

// NewWithLogger creates a bare bones Macaron instance.
// Use this method if you want to have full control over the middleware that is used.
// You can specify logger output writer with this function.
func NewWithLogger(out io.Writer) *Macaron {
	m := &Macaron{
		Injector: inject.New(),
		action:   func() {},
		Router:   NewRouter(),
		logger:   log.New(out, "[Macaron] ", 0),
	}
	m.Router.m = m
	m.Map(m.logger)
	m.Map(defaultReturnHandler())
	m.notFound = func(resp http.ResponseWriter, req *http.Request) {
		c := m.createContext(resp, req)
		c.handlers = append(c.handlers, http.NotFound)
		c.run()
	}
	return m
}

// New creates a bare bones Macaron instance.
// Use this method if you want to have full control over the middleware that is used.
func New() *Macaron {
	return NewWithLogger(os.Stdout)
}

// Classic creates a classic Macaron with some basic default middleware:
// mocaron.Logger, mocaron.Recovery and mocaron.Static.
func Classic() *Macaron {
	m := New()
	m.Use(Logger())
	m.Use(Recovery())
	m.Use(Static("public"))
	return m
}

// Handlers sets the entire middleware stack with the given Handlers.
// This will clear any current middleware handlers,
// and panics if any of the handlers is not a callable function
func (m *Macaron) Handlers(handlers ...Handler) {
	m.handlers = make([]Handler, 0)
	for _, handler := range handlers {
		m.Use(handler)
	}
}

// Action sets the handler that will be called after all the middleware has been invoked.
// This is set to macaron.Router in a macaron.Classic().
func (m *Macaron) Action(handler Handler) {
	validateHandler(handler)
	m.action = handler
}

// BeforeHandler represents a handler executes at beginning of every request.
// Macaron stops future process when it returns true.
type BeforeHandler func(rw http.ResponseWriter, req *http.Request) bool

func (m *Macaron) Before(handler BeforeHandler) {
	m.befores = append(m.befores, handler)
}

// Use adds a middleware Handler to the stack,
// and panics if the handler is not a callable func.
// Middleware Handlers are invoked in the order that they are added.
func (m *Macaron) Use(handler Handler) {
	validateHandler(handler)
	m.handlers = append(m.handlers, handler)
}

func (m *Macaron) createContext(rw http.ResponseWriter, req *http.Request) *Context {
	c := &Context{
		Injector: inject.New(),
		handlers: m.handlers,
		action:   m.action,
		index:    0,
		Router:   m.Router,
		Req:      Request{req},
		Resp:     NewResponseWriter(rw),
		Data:     make(map[string]interface{}),
	}
	c.SetParent(m)
	c.Map(c)
	c.MapTo(c.Resp, (*http.ResponseWriter)(nil))
	c.Map(req)
	return c
}

// ServeHTTP is the HTTP Entry point for a Macaron instance.
// Useful if you want to control your own HTTP server.
// Be aware that none of middleware will run without registering any router.
func (m *Macaron) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	req.URL.Path = strings.TrimPrefix(req.URL.Path, m.urlPrefix)
	for _, h := range m.befores {
		if h(rw, req) {
			return
		}
	}
	m.Router.ServeHTTP(rw, req)
}

func GetDefaultListenInfo() (string, int) {
	host := os.Getenv("HOST")
	if len(host) == 0 {
		host = "0.0.0.0"
	}
	port := com.StrTo(os.Getenv("PORT")).MustInt()
	if port == 0 {
		port = 4000
	}
	return host, port
}

// Run the http server. Listening on os.GetEnv("PORT") or 4000 by default.
func (m *Macaron) Run(args ...interface{}) {
	host, port := GetDefaultListenInfo()
	if len(args) == 1 {
		switch arg := args[0].(type) {
		case string:
			host = arg
		case int:
			port = arg
		}
	} else if len(args) >= 2 {
		if arg, ok := args[0].(string); ok {
			host = arg
		}
		if arg, ok := args[1].(int); ok {
			port = arg
		}
	}

	addr := host + ":" + com.ToStr(port)
	logger := m.Injector.GetVal(reflect.TypeOf(m.logger)).Interface().(*log.Logger)
	logger.Printf("listening on %s (%s)\n", addr, Env)
	logger.Fatalln(http.ListenAndServe(addr, m))
}

// SetURLPrefix sets URL prefix of router layer, so that it support suburl.
func (m *Macaron) SetURLPrefix(prefix string) {
	m.urlPrefix = prefix
}

// ____   ____            .__      ___.   .__
// \   \ /   /____ _______|__|____ \_ |__ |  |   ____   ______
//  \   Y   /\__  \\_  __ \  \__  \ | __ \|  | _/ __ \ /  ___/
//   \     /  / __ \|  | \/  |/ __ \| \_\ \  |_\  ___/ \___ \
//    \___/  (____  /__|  |__(____  /___  /____/\___  >____  >
//                \/              \/    \/          \/     \/

const (
	DEV  = "development"
	PROD = "production"
	TEST = "test"
)

var (
	// Env is the environment that Macaron is executing in.
	// The MACARON_ENV is read on initialization to set this variable.
	Env = DEV

	// Path of work directory.
	Root string

	// Flash applies to current request.
	FlashNow bool

	// Configuration convention object.
	cfg *ini.File
)

func setENV(e string) {
	if len(e) > 0 {
		Env = e
	}
}

func init() {
	setENV(os.Getenv("MACARON_ENV"))

	var err error
	Root, err = os.Getwd()
	if err != nil {
		panic("error getting work directory: " + err.Error())
	}
}

// SetConfig sets data sources for configuration.
func SetConfig(source interface{}, others ...interface{}) (err error) {
	cfg, err = ini.Load(source, others...)
	return err
}

// Config returns configuration convention object.
// It returns an empty object if there is no one available.
func Config() *ini.File {
	if cfg == nil {
		return &ini.File{}
	}
	return cfg
}
<|endoftext|>