<commit_before>package ionic

import (
	"encoding/json"
	"fmt"
	"net/http"
	"testing"

	. "github.com/franela/goblin"
	"github.com/gomicro/bogus"
	"github.com/ion-channel/ionic/products"
	. "github.com/onsi/gomega"
)

func TestProducts(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("Products", func() {
		var server *bogus.Bogus
		var h, p string
		var client *IonClient
		g.BeforeEach(func() {
			server = bogus.New()
			h, p = server.HostPort()
			client, _ = New(fmt.Sprintf("http://%v:%v", h, p))
		})
		g.AfterEach(func() {
			server.Close()
		})

		g.It("should get a product", func() {
			server.AddPath("/v1/vulnerability/getProducts").
				SetMethods("GET").
				SetPayload([]byte(SampleValidProduct)).
				SetStatus(http.StatusOK)

			product, err := client.GetProducts("cpe:/a:oracle:jdk:1.6.0:update_71", "someapikey")
			Expect(err).To(BeNil())
			Expect(product[0].Sources[0].Name).To(Equal("NVD"))
			Expect(product[0].ID).To(Equal(84647))
			Expect(product[0].Name).To(Equal("jdk"))
		})

		g.It("should get a raw product", func() {
			server.AddPath("/v1/vulnerability/getProducts").
				SetMethods("GET").
				SetPayload([]byte(SampleValidProduct)).
				SetStatus(http.StatusOK)

			raw, err := client.GetRawProducts("cpe:/a:oracle:jdk:1.6.0:update_71", "fookey")
			Expect(err).To(BeNil())
			Expect(raw).To(Equal(json.RawMessage(SampleValidRawProduct)))
		})

		g.It("should search for a product", func() {
			server.AddPath("/v1/product/search").
				SetMethods("GET").
				SetPayload([]byte(sampleBunsenSearchResponse)).
				SetStatus(http.StatusOK)
			products, err := client.GetProductSearch("less", "mahVersion", "mahVendor", "someapikey")
			Expect(err).To(BeNil())
			hitRecords := server.HitRecords()
			Expect(hitRecords).To(HaveLen(1))
			hitRecord := hitRecords[0]
			Expect(hitRecord.Header.Get("Authorization")).To(Equal("Bearer someapikey"))
			Expect(hitRecord.Query.Get("product_identifier")).To(Equal("less"))
			Expect(hitRecord.Query.Get("version")).To(Equal("mahVersion"))
			Expect(hitRecord.Query.Get("vendor")).To(Equal("mahVendor"))
			Expect(products).To(HaveLen(5))
			Expect(products[0].ID).To(Equal(39862))
		})
		g.It("should omit version and vendor from product search when it is not given", func() {
			server.AddPath("/v1/product/search").
				SetMethods("GET").
				SetPayload([]byte(sampleBunsenSearchResponse)).
				SetStatus(http.StatusOK)
			products, err := client.GetProductSearch("less", "", "", "someapikey")
			Expect(err).To(BeNil())
			hitRecords := server.HitRecords()
			Expect(hitRecords).To(HaveLen(1))
			hitRecord := hitRecords[0]
			Expect(hitRecord.Header.Get("Authorization")).To(Equal("Bearer someapikey"))
			Expect(hitRecord.Query.Get("product_identifier")).To(Equal("less"))
			Expect(hitRecord.Query.Get("version")).To(Equal(""))
			Expect(hitRecord.Query.Get("vendor")).To(Equal(""))
			Expect(products).To(HaveLen(5))
			Expect(products[0].ID).To(Equal(39862))
		})
		g.It("should marshal and unmarshal products with scores", func() {
			searchResultJSON := `{"product":{"name":"django","language":"","source":null,"created_at":"2017-02-13T20:02:35.667Z","title":"Django Project Django 1.0-alpha-1","up":"alpha1","updated_at":"2017-02-13T20:02:35.667Z","edition":"","part":"/a","references":[],"version":"1.0","org":"djangoproject","external_id":"cpe:/a:djangoproject:django:1.0:alpha1","id":30955,"aliases":null},"github":{"committer_count":2,"uri":"https://github.com/monsooncommerce/gstats"},"mean_score":0.534,"scores":[{"term":"django","score":0.393},{"term":"1.0","score":0.842}]}`
			var searchResult products.ProductSearchResult
			err := json.Unmarshal([]byte(searchResultJSON), &searchResult)
			Expect(err).NotTo(HaveOccurred())
			Expect(searchResult.Product.Up).To(Equal("alpha1"))
			Expect(searchResult.Scores).To(HaveLen(2))
			Expect(searchResult.Scores[0].Term).To(Equal("django"))
			Expect(searchResult.Scores[1].Term).To(Equal("1.0"))
			Expect(fmt.Sprintf("%.3f", searchResult.Scores[0].Score)).To(Equal("0.393"))
			Expect(fmt.Sprintf("%.3f", searchResult.Scores[1].Score)).To(Equal("0.842"))
			Expect(fmt.Sprintf("%.3f", searchResult.MeanScore)).To(Equal("0.534"))
		})
	})
}

const (
	SampleValidProduct         = `{"data":[{"id":84647,"name":"jdk","org":"oracle","version":"1.6.0","up":"update_71","edition":"","aliases":null,"created_at":"2017-02-13T20:02:42.600Z","updated_at":"2017-02-13T20:02:42.600Z","title":"Oracle JDK 1.6.0 Update 71","references":[{"April 2014 CPU":"http://www.oracle.com/technetwork/topics/security/cpuapr2014-1972952.html"}],"part":"/a","language":"","external_id":"cpe:/a:oracle:jdk:1.6.0:update_71","source":[{"id":1,"name":"NVD","description":"National Vulnerability Database","created_at":"2017-02-09T20:18:35.385Z","updated_at":"2017-02-13T20:12:05.342Z","attribution":"Copyright © 1999–2017, The MITRE Corporation. CVE and the CVE logo are registered trademarks and CVE-Compatible is a trademark of The MITRE Corporation.","license":"Submissions: For all materials you submit to the Common Vulnerabilities and Exposures (CVE®)","copyright_url":"http://cve.mitre.org/about/termsofuse.html"}]}]}`
	SampleValidRawProduct      = `[{"id":84647,"name":"jdk","org":"oracle","version":"1.6.0","up":"update_71","edition":"","aliases":null,"created_at":"2017-02-13T20:02:42.600Z","updated_at":"2017-02-13T20:02:42.600Z","title":"Oracle JDK 1.6.0 Update 71","references":[{"April 2014 CPU":"http://www.oracle.com/technetwork/topics/security/cpuapr2014-1972952.html"}],"part":"/a","language":"","external_id":"cpe:/a:oracle:jdk:1.6.0:update_71","source":[{"id":1,"name":"NVD","description":"National Vulnerability Database","created_at":"2017-02-09T20:18:35.385Z","updated_at":"2017-02-13T20:12:05.342Z","attribution":"Copyright © 1999–2017, The MITRE Corporation. CVE and the CVE logo are registered trademarks and CVE-Compatible is a trademark of The MITRE Corporation.","license":"Submissions: For all materials you submit to the Common Vulnerabilities and Exposures (CVE®)","copyright_url":"http://cve.mitre.org/about/termsofuse.html"}]}]`
	sampleBunsenSearchResponse = `{"data":[{"id":39862,"name":"less","org":"gnu","version":"-","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less","references":[],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:-"},{"id":39863,"name":"less","org":"gnu","version":"358","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less 358","references":[],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:358"},{"id":39864,"name":"less","org":"gnu","version":"381","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less 381","references":[],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:381"},{"id":39865,"name":"less","org":"gnu","version":"382","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less 382","references":[],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:382"},{"id":39866,"name":"less","org":"gnu","version":"471","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less 471","references":[{"Vendor Website":"http://www.gnu.org/software/less/"}],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:471"}],"meta":{"copyright":"Copyright 2018 Selection Pressure LLC www.selectpress.net","authors":["Ion Channel Dev Team"],"version":"v1","last_update":"2018-05-03T16:27:42.409Z","total_count":5,"limit":10,"offset":0},"links":{"self":"https://api.ionchannel.io/v1/product/search?user_query=less"}}`
)
<commit_msg>responding to code review, making test do what it says it does<commit_after>package ionic

import (
	"encoding/json"
	"fmt"
	"net/http"
	"testing"

	. "github.com/franela/goblin"
	"github.com/gomicro/bogus"
	"github.com/ion-channel/ionic/products"
	. "github.com/onsi/gomega"
)

func TestProducts(t *testing.T) {
	g := Goblin(t)
	RegisterFailHandler(func(m string, _ ...int) { g.Fail(m) })

	g.Describe("Products", func() {
		var server *bogus.Bogus
		var h, p string
		var client *IonClient
		g.BeforeEach(func() {
			server = bogus.New()
			h, p = server.HostPort()
			client, _ = New(fmt.Sprintf("http://%v:%v", h, p))
		})
		g.AfterEach(func() {
			server.Close()
		})

		g.It("should get a product", func() {
			server.AddPath("/v1/vulnerability/getProducts").
				SetMethods("GET").
				SetPayload([]byte(SampleValidProduct)).
				SetStatus(http.StatusOK)

			product, err := client.GetProducts("cpe:/a:oracle:jdk:1.6.0:update_71", "someapikey")
			Expect(err).To(BeNil())
			Expect(product[0].Sources[0].Name).To(Equal("NVD"))
			Expect(product[0].ID).To(Equal(84647))
			Expect(product[0].Name).To(Equal("jdk"))
		})

		g.It("should get a raw product", func() {
			server.AddPath("/v1/vulnerability/getProducts").
				SetMethods("GET").
				SetPayload([]byte(SampleValidProduct)).
				SetStatus(http.StatusOK)

			raw, err := client.GetRawProducts("cpe:/a:oracle:jdk:1.6.0:update_71", "fookey")
			Expect(err).To(BeNil())
			Expect(raw).To(Equal(json.RawMessage(SampleValidRawProduct)))
		})

		g.It("should search for a product", func() {
			server.AddPath("/v1/product/search").
				SetMethods("GET").
				SetPayload([]byte(sampleBunsenSearchResponse)).
				SetStatus(http.StatusOK)
			products, err := client.GetProductSearch("less", "mahVersion", "mahVendor", "someapikey")
			Expect(err).To(BeNil())
			hitRecords := server.HitRecords()
			Expect(hitRecords).To(HaveLen(1))
			hitRecord := hitRecords[0]
			Expect(hitRecord.Header.Get("Authorization")).To(Equal("Bearer someapikey"))
			Expect(hitRecord.Query.Get("product_identifier")).To(Equal("less"))
			Expect(hitRecord.Query.Get("version")).To(Equal("mahVersion"))
			Expect(hitRecord.Query.Get("vendor")).To(Equal("mahVendor"))
			Expect(products).To(HaveLen(5))
			Expect(products[0].ID).To(Equal(39862))
		})
		g.It("should omit version and vendor from product search when it is not given", func() {
			server.AddPath("/v1/product/search").
				SetMethods("GET").
				SetPayload([]byte(sampleBunsenSearchResponse)).
				SetStatus(http.StatusOK)
			products, err := client.GetProductSearch("less", "", "", "someapikey")
			Expect(err).To(BeNil())
			hitRecords := server.HitRecords()
			Expect(hitRecords).To(HaveLen(1))
			hitRecord := hitRecords[0]
			Expect(hitRecord.Header.Get("Authorization")).To(Equal("Bearer someapikey"))
			Expect(hitRecord.Query.Get("product_identifier")).To(Equal("less"))
			Expect(hitRecord.Query.Get("version")).To(Equal(""))
			Expect(hitRecord.Query.Get("vendor")).To(Equal(""))
			Expect(products).To(HaveLen(5))
			Expect(products[0].ID).To(Equal(39862))
		})
		g.It("should unmarshal search results with scores", func() {
			searchResultJSON := `{"product":{"name":"django","language":"","source":null,"created_at":"2017-02-13T20:02:35.667Z","title":"Django Project Django 1.0-alpha-1","up":"alpha1","updated_at":"2017-02-13T20:02:35.667Z","edition":"","part":"/a","references":[],"version":"1.0","org":"djangoproject","external_id":"cpe:/a:djangoproject:django:1.0:alpha1","id":30955,"aliases":null},"github":{"committer_count":2,"uri":"https://github.com/monsooncommerce/gstats"},"mean_score":0.534,"scores":[{"term":"django","score":0.393},{"term":"1.0","score":0.842}]}`
			var searchResult products.ProductSearchResult
			err := json.Unmarshal([]byte(searchResultJSON), &searchResult)
			Expect(err).NotTo(HaveOccurred())
			Expect(searchResult.Product.Up).To(Equal("alpha1"))
			Expect(searchResult.Scores).To(HaveLen(2))
			Expect(searchResult.Scores[0].Term).To(Equal("django"))
			Expect(searchResult.Scores[1].Term).To(Equal("1.0"))
			Expect(fmt.Sprintf("%.3f", searchResult.Scores[0].Score)).To(Equal("0.393"))
			Expect(fmt.Sprintf("%.3f", searchResult.Scores[1].Score)).To(Equal("0.842"))
			Expect(fmt.Sprintf("%.3f", searchResult.MeanScore)).To(Equal("0.534"))
		})
		g.It("should marshal search results with scores", func() {
			product := products.Product{
				ID:         1234,
				Name:       "product name",
				Org:        "some org",
				Version:    "3.1.2",
				Title:      "mah title",
				ExternalID: "cpe:/a:djangoproject:django:1.0:alpha1",
			}
			github := products.Github{
				URI:            "https://github.com/some/repo",
				CommitterCount: 5,
			}
			scores := []products.ProductSearchScore{
				{Term: "foo", Score: 3.2},
			}
			searchResult := products.ProductSearchResult{
				Product:   product,
				Github:    github,
				MeanScore: 3.6,
				Scores:    scores,
			}
			b, err := json.Marshal(searchResult)
			Expect(err).NotTo(HaveOccurred())
			s := string(b)
			Expect(s).To(MatchRegexp(`"name":\s*"product name"`))
			Expect(s).To(MatchRegexp(`"mean_score":\s*3.6`))
			Expect(s).To(MatchRegexp(`"score":\s*3.2`))
			Expect(s).To(MatchRegexp(`"term":\s*"foo"`))
		})
	})
}

const (
	SampleValidProduct         = `{"data":[{"id":84647,"name":"jdk","org":"oracle","version":"1.6.0","up":"update_71","edition":"","aliases":null,"created_at":"2017-02-13T20:02:42.600Z","updated_at":"2017-02-13T20:02:42.600Z","title":"Oracle JDK 1.6.0 Update 71","references":[{"April 2014 CPU":"http://www.oracle.com/technetwork/topics/security/cpuapr2014-1972952.html"}],"part":"/a","language":"","external_id":"cpe:/a:oracle:jdk:1.6.0:update_71","source":[{"id":1,"name":"NVD","description":"National Vulnerability Database","created_at":"2017-02-09T20:18:35.385Z","updated_at":"2017-02-13T20:12:05.342Z","attribution":"Copyright © 1999–2017, The MITRE Corporation. CVE and the CVE logo are registered trademarks and CVE-Compatible is a trademark of The MITRE Corporation.","license":"Submissions: For all materials you submit to the Common Vulnerabilities and Exposures (CVE®)","copyright_url":"http://cve.mitre.org/about/termsofuse.html"}]}]}`
	SampleValidRawProduct      = `[{"id":84647,"name":"jdk","org":"oracle","version":"1.6.0","up":"update_71","edition":"","aliases":null,"created_at":"2017-02-13T20:02:42.600Z","updated_at":"2017-02-13T20:02:42.600Z","title":"Oracle JDK 1.6.0 Update 71","references":[{"April 2014 CPU":"http://www.oracle.com/technetwork/topics/security/cpuapr2014-1972952.html"}],"part":"/a","language":"","external_id":"cpe:/a:oracle:jdk:1.6.0:update_71","source":[{"id":1,"name":"NVD","description":"National Vulnerability Database","created_at":"2017-02-09T20:18:35.385Z","updated_at":"2017-02-13T20:12:05.342Z","attribution":"Copyright © 1999–2017, The MITRE Corporation. CVE and the CVE logo are registered trademarks and CVE-Compatible is a trademark of The MITRE Corporation.","license":"Submissions: For all materials you submit to the Common Vulnerabilities and Exposures (CVE®)","copyright_url":"http://cve.mitre.org/about/termsofuse.html"}]}]`
	sampleBunsenSearchResponse = `{"data":[{"id":39862,"name":"less","org":"gnu","version":"-","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less","references":[],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:-"},{"id":39863,"name":"less","org":"gnu","version":"358","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less 358","references":[],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:358"},{"id":39864,"name":"less","org":"gnu","version":"381","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less 381","references":[],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:381"},{"id":39865,"name":"less","org":"gnu","version":"382","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less 382","references":[],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:382"},{"id":39866,"name":"less","org":"gnu","version":"471","up":"","edition":"","aliases":null,"created_at":"2017-02-13T20:02:36.794Z","updated_at":"2017-02-13T20:02:36.794Z","title":"GNU less 471","references":[{"Vendor Website":"http://www.gnu.org/software/less/"}],"part":"/a","language":"","external_id":"cpe:/a:gnu:less:471"}],"meta":{"copyright":"Copyright 2018 Selection Pressure LLC www.selectpress.net","authors":["Ion Channel Dev Team"],"version":"v1","last_update":"2018-05-03T16:27:42.409Z","total_count":5,"limit":10,"offset":0},"links":{"self":"https://api.ionchannel.io/v1/product/search?user_query=less"}}`
)
<|endoftext|>


<commit_before>package kvson

// Element ...
type Element struct {
	ID    string
	Value string
}
<commit_msg>Initial source code<commit_after>package kvson

import "io/ioutil"

// Element ...
type Element struct {
	ID      string
	Payload string
}

// Get an element by its ID
func (e Element) Get(path string, id string) (el Element, err error) {
	filename := path + "/" + id
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return el, err
	}
	el = Element{
		ID:      id,
		Payload: string(data),
	}
	return el, nil
}

// Save an element
func (e Element) Save(path string, id string, payload string) (err error) {
	filename := path + "/" + id
	err = ioutil.WriteFile(filename, []byte(payload), 0644)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package ssh

import (
	"crypto/subtle"
	"net"

	gossh "golang.org/x/crypto/ssh"
)

type Signal string

// POSIX signals as listed in RFC 4254 Section 6.10.
const (
	SIGABRT Signal = "ABRT"
	SIGALRM Signal = "ALRM"
	SIGFPE  Signal = "FPE"
	SIGHUP  Signal = "HUP"
	SIGILL  Signal = "ILL"
	SIGINT  Signal = "INT"
	SIGKILL Signal = "KILL"
	SIGPIPE Signal = "PIPE"
	SIGQUIT Signal = "QUIT"
	SIGSEGV Signal = "SEGV"
	SIGTERM Signal = "TERM"
	SIGUSR1 Signal = "USR1"
	SIGUSR2 Signal = "USR2"
)

var defaultHandler Handler

type Option func(*Server) error
type Handler func(Session)

type PublicKeyHandler func(user string, key PublicKey) bool
type PasswordHandler func(user, password string) bool

type PermissionsCallback func(user string, permissions *Permissions) error
type PtyCallback func(user string, permissions *Permissions) bool

type Window struct {
	Width  int
	Height int
}

type Pty struct {
	Window Window
}

func Serve(l net.Listener, handler Handler, options ...Option) error {
	srv := &Server{Handler: handler}
	for _, option := range options {
		if err := srv.SetOption(option); err != nil {
			return err
		}
	}
	return srv.Serve(l)
}

func ListenAndServe(addr string, handler Handler, options ...Option) error {
	srv := &Server{Addr: addr, Handler: handler}
	for _, option := range options {
		if err := srv.SetOption(option); err != nil {
			return err
		}
	}
	return srv.ListenAndServe()
}

func Handle(handler Handler) {
	defaultHandler = handler
}

// KeysEqual is constant time compare of the keys to avoid timing attacks
func KeysEqual(ak, bk PublicKey) bool {
	a := gossh.Marshal(ak)
	b := gossh.Marshal(bk)
	return (len(a) == len(b) && subtle.ConstantTimeCompare(a, b) == 1)
}
<commit_msg>use Marshal method on publicKey instead of Marshal func<commit_after>package ssh

import (
	"crypto/subtle"
	"net"
)

type Signal string

// POSIX signals as listed in RFC 4254 Section 6.10.
const (
	SIGABRT Signal = "ABRT"
	SIGALRM Signal = "ALRM"
	SIGFPE  Signal = "FPE"
	SIGHUP  Signal = "HUP"
	SIGILL  Signal = "ILL"
	SIGINT  Signal = "INT"
	SIGKILL Signal = "KILL"
	SIGPIPE Signal = "PIPE"
	SIGQUIT Signal = "QUIT"
	SIGSEGV Signal = "SEGV"
	SIGTERM Signal = "TERM"
	SIGUSR1 Signal = "USR1"
	SIGUSR2 Signal = "USR2"
)

var defaultHandler Handler

type Option func(*Server) error
type Handler func(Session)

type PublicKeyHandler func(user string, key PublicKey) bool
type PasswordHandler func(user, password string) bool

type PermissionsCallback func(user string, permissions *Permissions) error
type PtyCallback func(user string, permissions *Permissions) bool

type Window struct {
	Width  int
	Height int
}

type Pty struct {
	Window Window
}

func Serve(l net.Listener, handler Handler, options ...Option) error {
	srv := &Server{Handler: handler}
	for _, option := range options {
		if err := srv.SetOption(option); err != nil {
			return err
		}
	}
	return srv.Serve(l)
}

func ListenAndServe(addr string, handler Handler, options ...Option) error {
	srv := &Server{Addr: addr, Handler: handler}
	for _, option := range options {
		if err := srv.SetOption(option); err != nil {
			return err
		}
	}
	return srv.ListenAndServe()
}

func Handle(handler Handler) {
	defaultHandler = handler
}

// KeysEqual is constant time compare of the keys to avoid timing attacks
func KeysEqual(ak, bk PublicKey) bool {
	a := ak.Marshal()
	b := bk.Marshal()
	return (len(a) == len(b) && subtle.ConstantTimeCompare(a, b) == 1)
}
<|endoftext|>


<commit_before>package metadata

import (
	"fmt"

	"github.com/freneticmonkey/migrate/go/util"
)

// Metadata This struct stores the identification information for each table
// and table field in the target database.  This data is used to match the
// schema of the target database to the YAML schema
type Metadata struct {
	MDID       int64  `db:"mdid, autoincrement, primarykey" json:"mdid"`
	DB         int    `db:"db" json:"db"`
	PropertyID string `db:"property_id" json:"property_id"`
	ParentID   string `db:"parent_id" json:"parent_id"`
	Type       string `db:"type" json:"type"`
	Name       string `db:"name" json:"name"`
	Exists     bool   `db:"exists" json:"exists"`
}

// Insert Insert the Metadata into the Management DB
func (m *Metadata) Insert() error {
	m.DB = targetDBID
	if len(m.PropertyID) == 0 {
		return fmt.Errorf("Inserting empty Metadata")
	}
	if err := configured(); err != nil {
		return err
	}
	return mgmtDb.Insert(m)
}

// Update Update the Metadata in the Management DB
func (m *Metadata) Update() (err error) {
	if err := configured(); err != nil {
		return err
	}
	_, err = mgmtDb.Update(m)
	return err
}

// Delete Remove the Metadata from the database
func (m *Metadata) Delete() (err error) {
	if err := configured(); err != nil {
		return err
	}
	_, err = mgmtDb.Delete(m)
	return err
}

// IsTable Returns if there is a value for ParentID. If empty the property is a table.
func (m *Metadata) IsTable() bool {
	return len(m.ParentID) == 0
}

// OnCreate Check if the Metadata is known to the database yet.  Depends on MDID being set != 0
func (m *Metadata) OnCreate() error {
	// If this Metadata hasn't been inserted into the database yet, insert it
	if m.MDID == 0 {

		if err := configured(); err != nil {
			return err
		}

		return m.Insert()
	}
	return nil
}

// Load Uses the valud of MDID to load from the Management DB
func Load(mdid int64) (m *Metadata, err error) {
	if err = configured(); err != nil {
		return m, err
	}
	md, err := mgmtDb.Get(Metadata{}, mdid)
	if md != nil {
		m = md.(*Metadata)
	}
	return m, err
}

// TableRegistered Returns a boolean indicating that the Table named 'name' is
// registered in the Metadata table
func TableRegistered(name string) (reg bool, err error) {
	if err = configured(); err != nil {
		return false, err
	}

	query := fmt.Sprintf("SELECT count(*) from metadata WHERE name=\"%s\" and type=\"Table\"", name)
	count, err := mgmtDb.SelectInt(query)
	return count > 0, err
}

// LoadAllTableMetadata Load all of the Metadata rows for a table with the
// matching Property and Database IDs
func LoadAllTableMetadata(name string, db int) (md []Metadata, err error) {
	var tblMd Metadata

	tblMd, err = GetTableByName(name)
	if err != nil {
		return md, err
	}

	query := fmt.Sprintf("select * from metadata WHERE name = \"%s\" OR parent_id = \"%s\" AND db=%d", tblMd.PropertyID, tblMd.PropertyID, db)
	_, err = mgmtDb.Select(&md, query)

	util.ErrorCheckf(err, "There was a problem retrieving Metadata for Table with Name: [%s] and PropertyID: [%s]", name, tblMd.PropertyID)
	return md, err
}

// GetTableByName Get a Table metadata object from the database by name
func GetTableByName(name string) (md Metadata, err error) {

	// Find a Table (Tables don't have a ParentID)
	return GetByName(name, "")
}

// GetByName Get a metadata object from the database with name
func GetByName(name string, parentID string) (md Metadata, err error) {
	if err = configured(); err != nil {
		return md, err
	}

	errString := fmt.Sprintf("Failed to find Property with name: [%s]", name)
	query := fmt.Sprintf("SELECT * FROM metadata WHERE name=\"%s\"", name)

	if len(parentID) > 0 {
		query += fmt.Sprintf(" AND parent_id=\"%s\"", parentID)
		errString += fmt.Sprintf(" in ParentID: [%s]", parentID)
	}

	err = mgmtDb.SelectOne(&md, query)
	util.ErrorCheckf(err, errString)

	return md, err
}
<commit_msg>Replaced a Gorp generated select with a manual select.  Had some issues with the mockdb detecting this query.<commit_after>package metadata

import (
	"fmt"

	"github.com/freneticmonkey/migrate/go/util"
)

// Metadata This struct stores the identification information for each table
// and table field in the target database.  This data is used to match the
// schema of the target database to the YAML schema
type Metadata struct {
	MDID       int64  `db:"mdid, autoincrement, primarykey" json:"mdid"`
	DB         int    `db:"db" json:"db"`
	PropertyID string `db:"property_id" json:"property_id"`
	ParentID   string `db:"parent_id" json:"parent_id"`
	Type       string `db:"type" json:"type"`
	Name       string `db:"name" json:"name"`
	Exists     bool   `db:"exists" json:"exists"`
}

// Insert Insert the Metadata into the Management DB
func (m *Metadata) Insert() error {
	m.DB = targetDBID
	if len(m.PropertyID) == 0 {
		return fmt.Errorf("Inserting empty Metadata")
	}
	if err := configured(); err != nil {
		return err
	}
	return mgmtDb.Insert(m)
}

// Update Update the Metadata in the Management DB
func (m *Metadata) Update() (err error) {
	if err := configured(); err != nil {
		return err
	}
	_, err = mgmtDb.Update(m)
	return err
}

// Delete Remove the Metadata from the database
func (m *Metadata) Delete() (err error) {
	if err := configured(); err != nil {
		return err
	}
	_, err = mgmtDb.Delete(m)
	return err
}

// IsTable Returns if there is a value for ParentID. If empty the property is a table.
func (m *Metadata) IsTable() bool {
	return len(m.ParentID) == 0
}

// OnCreate Check if the Metadata is known to the database yet.  Depends on MDID being set != 0
func (m *Metadata) OnCreate() error {
	// If this Metadata hasn't been inserted into the database yet, insert it
	if m.MDID == 0 {

		if err := configured(); err != nil {
			return err
		}

		return m.Insert()
	}
	return nil
}

// Load Uses the valud of MDID to load from the Management DB
func Load(mdid int64) (m *Metadata, err error) {
	var md Metadata
	if err = configured(); err != nil {
		return m, err
	}
	query := fmt.Sprintf("SELECT * FROM `metadata` WHERE mdid=%d", mdid)
	err = mgmtDb.SelectOne(&md, query)

	if err == nil {
		m = &md
	}
	return m, err
}

// TableRegistered Returns a boolean indicating that the Table named 'name' is
// registered in the Metadata table
func TableRegistered(name string) (reg bool, err error) {
	if err = configured(); err != nil {
		return false, err
	}

	query := fmt.Sprintf("SELECT count(*) from metadata WHERE name=\"%s\" and type=\"Table\"", name)
	count, err := mgmtDb.SelectInt(query)
	return count > 0, err
}

// LoadAllTableMetadata Load all of the Metadata rows for a table with the
// matching Property and Database IDs
func LoadAllTableMetadata(name string, db int) (md []Metadata, err error) {
	var tblMd Metadata

	tblMd, err = GetTableByName(name)
	if err != nil {
		return md, err
	}

	query := fmt.Sprintf("select * from metadata WHERE name = \"%s\" OR parent_id = \"%s\" AND db=%d", tblMd.PropertyID, tblMd.PropertyID, db)
	_, err = mgmtDb.Select(&md, query)

	util.ErrorCheckf(err, "There was a problem retrieving Metadata for Table with Name: [%s] and PropertyID: [%s]", name, tblMd.PropertyID)
	return md, err
}

// GetTableByName Get a Table metadata object from the database by name
func GetTableByName(name string) (md Metadata, err error) {

	// Find a Table (Tables don't have a ParentID)
	return GetByName(name, "")
}

// GetByName Get a metadata object from the database with name
func GetByName(name string, parentID string) (md Metadata, err error) {
	if err = configured(); err != nil {
		return md, err
	}

	errString := fmt.Sprintf("Failed to find Property with name: [%s]", name)
	query := fmt.Sprintf("SELECT * FROM metadata WHERE name=\"%s\"", name)

	if len(parentID) > 0 {
		query += fmt.Sprintf(" AND parent_id=\"%s\"", parentID)
		errString += fmt.Sprintf(" in ParentID: [%s]", parentID)
	}

	err = mgmtDb.SelectOne(&md, query)
	util.ErrorCheckf(err, errString)

	return md, err
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "flag"
    "image"
    "image/color"
    "image/png"
    "image/draw"
    "os"
    "regexp"
)

var DEFAULT_ICON_SIZE = 60;

type Options struct {
    Fen     string
    OutputFilename     string
    CellSize int
}

var g_Options Options;

var fen = "8/8/8/4k3/5R2/8/8/3QK3 w - - 0 1";

var board = [8][8]byte{
 {'r','n','b','q','k','b','n','r'},
 {'p','p','p','p','p','p','p','p'},
 {' ',' ',' ',' ',' ',' ',' ',' '},
 {' ',' ',' ',' ',' ',' ',' ',' '},
 {' ',' ',' ',' ',' ',' ',' ',' '},
 {' ',' ',' ',' ',' ',' ',' ',' '},
 {'P','P','P','P','P','P','P','P'},
 {'R','N','B','Q','K','B','N','R'}};

var validPieces = []byte{'r','n','b','q','k','p', 'R','N','B','Q','K','P'};
var icons map[byte] *image.Image = make(map[byte] *image.Image);

func (options *Options) ParseCommandLineOptions() {
    flag.StringVar(&options.OutputFilename, "output", "out.png", "The output filename")
    flag.StringVar(&options.Fen, "fen", "8/8/8/8/8/8/8/8 w - - 0 0", "The fen expression")
    flag.IntVar(&options.CellSize, "cellsize", DEFAULT_ICON_SIZE, "The board cell size")

    flag.Parse();
}

func loadIcon(inputFilename string) *image.Image {
    infile, err := os.Open(inputFilename)
    if err != nil {
        // replace this with real error handling
        panic(err)
    }
    defer infile.Close()

    // Decode will figure out what type of image is in the file on its own.
    // We just have to be sure all the image packages we want are imported.
    src, _, err := image.Decode(infile)
    if err != nil {
        // replace this with real error handling
        panic(err)
    }
    return &src;
}

func contains(s []byte, e byte) bool {
    for _, a := range s {
        if a == e {
            return true
        }
    }
    return false
}

func Rect(x1 int, y1, x2, y2 int, col color.RGBA, img *image.RGBA) {
    for x := x1; x<= x2; x++ {
        for y := y1; y <= y2; y++ {
            img.Set(x, y, col)
        }
    }
}

func DrawBackground(img *image.RGBA){
    // Lichess colors : 8ca2ad and dee3e6
    var whiteColor = color.RGBA{222, 227, 230, 255};
    var blackColor = color.RGBA{140,162, 173, 255};

    var s = g_Options.CellSize;

    for x := 0; x< 8; x++ {
        for y := 0; y < 8; y++ {
            color := blackColor;
            if (x+y)%2 == 0 {
                color = whiteColor;
            }

            Rect(x*s, y*s, (x+1)*s, (y+1)*s, color, img)
        }
    }
}

func DrawBoard(board [8][8]byte, img *image.RGBA){
    for x := 0; x< 8; x++ {
        for y := 0; y < 8; y++ {
            var piece = board[y][x];

            var isValidPiece = piece != ' ' && contains(validPieces, piece);
            var _, isLoaded = icons[piece];
            if isValidPiece && isLoaded {
                var coords = image.Point{-x*g_Options.CellSize,-y*g_Options.CellSize}
                draw.Draw(img, img.Bounds(), *(icons[piece]), coords, draw.Over);
            }
        }
    }
}

func loadIcons(){
    for _, s := range validPieces {
        var iconFile = "icons/"+ string(s) +"60.png";
        icons[s] = loadIcon(iconFile)
    }
}

func main() {
    g_Options.ParseCommandLineOptions();
    loadIcons();

    img := image.NewRGBA(image.Rect(0, 0, 8*g_Options.CellSize, 8*g_Options.CellSize))
    img.Set(2, 3, color.RGBA{255, 0, 0, 255})

    f, _ := os.OpenFile("out.png", os.O_WRONLY|os.O_CREATE, 0600)

    defer f.Close()

    DrawBackground(img);
    DrawBoard(board, img)

    png.Encode(f, img)

    var fen = "4k3/8/8/8/8/8/8/8 w - - 0 0"
    var linePattern = "[1-9rnbqkpRNBQKP]+";
    var fenRegex = fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s/%s w|b - - \\d+ \\d+", linePattern, linePattern, linePattern, linePattern, linePattern, linePattern, linePattern, linePattern)
    var isValid, _ = regexp.MatchString(fenRegex, fen)

    fmt.Println(isValid)
    fmt.Println("Success !")
}
<commit_msg>implemented fen conversion algorithm<commit_after>package main

import (
    "fmt"
    "flag"
    "image"
    "image/color"
    "image/png"
    "image/draw"
    "os"
    "regexp"
    "strings"
    "errors"
)

var DEFAULT_ICON_SIZE = 60;

type Options struct {
    Fen     string
    OutputFilename     string
    CellSize int
}

var g_Options Options;

var fen = "8/8/8/4k3/5R2/8/8/3QK3 w - - 0 1";

var defaultBoard = [8][8]byte{
 {'r','n','b','q','k','b','n','r'},
 {'p','p','p','p','p','p','p','p'},
 {' ',' ',' ',' ',' ',' ',' ',' '},
 {' ',' ',' ',' ',' ',' ',' ',' '},
 {' ',' ',' ',' ',' ',' ',' ',' '},
 {' ',' ',' ',' ',' ',' ',' ',' '},
 {'P','P','P','P','P','P','P','P'},
 {'R','N','B','Q','K','B','N','R'}};

var validPieces = []byte{'r','n','b','q','k','p', 'R','N','B','Q','K','P'};
var icons map[byte] *image.Image = make(map[byte] *image.Image);

func (options *Options) ParseCommandLineOptions() {
    flag.StringVar(&options.OutputFilename, "output", "out.png", "The output filename")
    flag.StringVar(&options.Fen, "fen", "8/8/8/8/8/8/8/8 w - - 0 0", "The fen expression")
    flag.IntVar(&options.CellSize, "cellsize", DEFAULT_ICON_SIZE, "The board cell size")

    flag.Parse();
}

func loadIcon(inputFilename string) *image.Image {
    infile, err := os.Open(inputFilename)
    if err != nil {
        // replace this with real error handling
        panic(err)
    }
    defer infile.Close()

    // Decode will figure out what type of image is in the file on its own.
    // We just have to be sure all the image packages we want are imported.
    src, _, err := image.Decode(infile)
    if err != nil {
        // replace this with real error handling
        panic(err)
    }
    return &src;
}

func contains(s []byte, e byte) bool {
    for _, a := range s {
        if a == e {
            return true
        }
    }
    return false
}

func Rect(x1 int, y1, x2, y2 int, col color.RGBA, img *image.RGBA) {
    for x := x1; x<= x2; x++ {
        for y := y1; y <= y2; y++ {
            img.Set(x, y, col)
        }
    }
}

func DrawBackground(img *image.RGBA){
    // Lichess colors : 8ca2ad and dee3e6
    var whiteColor = color.RGBA{222, 227, 230, 255};
    var blackColor = color.RGBA{140,162, 173, 255};

    var s = g_Options.CellSize;

    for x := 0; x< 8; x++ {
        for y := 0; y < 8; y++ {
            color := blackColor;
            if (x+y)%2 == 0 {
                color = whiteColor;
            }

            Rect(x*s, y*s, (x+1)*s, (y+1)*s, color, img)
        }
    }
}

func DrawBoard(board [8][8]byte, img *image.RGBA){
    for x := 0; x< 8; x++ {
        for y := 0; y < 8; y++ {
            var piece = board[y][x];

            var isValidPiece = piece != ' ' && contains(validPieces, piece);
            var _, isLoaded = icons[piece];
            if isValidPiece && isLoaded {
                var coords = image.Point{-x*g_Options.CellSize,-y*g_Options.CellSize}
                draw.Draw(img, img.Bounds(), *(icons[piece]), coords, draw.Over);
            }
        }
    }
}

func loadIcons(){
    for _, s := range validPieces {
        var iconFile = "icons/"+ string(s) +"60.png";
        icons[s] = loadIcon(iconFile)
    }
}

func isValidFen(fen string) bool{
    var linePattern = "[1-9rnbqkpRNBQKP]+";
    var fenRegex = fmt.Sprintf("%s/%s/%s/%s/%s/%s/%s/%s w|b - - \\d+ \\d+", linePattern, linePattern, linePattern, linePattern, linePattern, linePattern, linePattern, linePattern)
    var isValid, _ = regexp.MatchString(fenRegex, fen)
    return isValid
}

func getBoardLine(fenElement string) ([8]byte, error) {
    var line = [8]byte{};
    var pos = 0;
    for _, cellValue := range fenElement {
        if pos >= 8 {
            return line, errors.New(fmt.Sprintf("Oops: %s is not a valid fen element", fenElement))
            break;
        }
        if contains(validPieces, byte(cellValue)){
            line[pos] = byte(cellValue)
            pos = pos + 1
            continue;
        }  else {
            pos = pos + int((int(cellValue) - int('0')))
        }
    }

    return line, nil;
}

func getBoardFromFen(fen string) ([8][8]byte, error) {
    if false == isValidFen(fen) {
        return defaultBoard, errors.New("Invalid FEN !");
    }
    var splits = strings.Split(fen, " ")
    var lines = strings.Split(splits[0], "/")

    var board = [8][8]byte{};
    for y := 0; y < 8; y++ {
        var err error
        board[y], err = getBoardLine(lines[y])
        if err != nil {
            return defaultBoard, err
        }
    }

    return board, nil;
}

func main() {
    var fen = "4k3/r6Bp/8p/8/8/8/8/K6Q w - - 0 0"

    g_Options.ParseCommandLineOptions();
    loadIcons();

    img := image.NewRGBA(image.Rect(0, 0, 8*g_Options.CellSize, 8*g_Options.CellSize))

    f, _ := os.OpenFile(g_Options.OutputFilename, os.O_WRONLY|os.O_CREATE, 0600)
    defer f.Close()

    var board, err = getBoardFromFen(fen);
    DrawBackground(img);
    DrawBoard(board, img)

    if err != nil {
        fmt.Println(err)
        fmt.Println("Output will be a default board")
        os.Exit(65) // DATAERR according to /usr/include/sysexits.h
    }

    png.Encode(f, img)
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2016 Maciek Borzecki <maciek.borzecki@gmail.com>
//
// 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 (
	"flag"
	"net/http"
	"os"
	"time"

	log "github.com/Sirupsen/logrus"
)

var (
	optDebug      = flag.Bool("debug", false, "Enable debug logging")
	optCacheRoot  = flag.String("cache-root", "./tmp", "Cache directory path")
	optListenAddr = flag.String("listen", ":8080", "Listen address")
	optMirrors    = flag.String("mirrors", "", "Mirror list file")
	optTimeout    = flag.Duration("client-timeout", 15*time.Second, "Forward request timeout")
)

func main() {

	flag.Parse()

	if *optDebug {
		log.SetLevel(log.DebugLevel)
		log.Debugf("debug logging enabled")
	}

	if *optMirrors == "" {
		log.Errorf("no mirrors, cannot continue")
		os.Exit(1)
	}

	m := Mirrors{}
	if err := m.LoadFile(*optMirrors); err != nil {
		log.Errorf("failed to load mirrors from %v: %v",
			*optMirrors, err)
		os.Exit(1)
	}

	log.Infof("cache root: %v", *optCacheRoot)
	cache := Cache{
		Dir: *optCacheRoot,
	}

	addr := *optListenAddr
	server := http.Server{
		Addr: addr,
		Handler: &ViaDownloadServer{
			Mirrors:       &m,
			Cache:         &cache,
			ClientTimeout: *optTimeout,
		},
	}
	log.Infof("listen on %v", addr)

	if err := server.ListenAndServe(); err != nil {
		log.Fatalf("listen failed: %v", err)
	}
}
<commit_msg>main: add -version<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2016 Maciek Borzecki <maciek.borzecki@gmail.com>
//
// 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 (
	"flag"
	"fmt"
	"net/http"
	"os"
	"time"

	log "github.com/Sirupsen/logrus"
)

var (
	optDebug      = flag.Bool("debug", false, "Enable debug logging")
	optCacheRoot  = flag.String("cache-root", "./tmp", "Cache directory path")
	optListenAddr = flag.String("listen", ":8080", "Listen address")
	optMirrors    = flag.String("mirrors", "", "Mirror list file")
	optTimeout    = flag.Duration("client-timeout", 15*time.Second, "Forward request timeout")
	optVersion    = flag.Bool("version", false, "Show version")

	Version = "(unknown)"
)

func main() {

	flag.Parse()

	if *optVersion {
		fmt.Println(Version)
		return
	}

	if *optDebug {
		log.SetLevel(log.DebugLevel)
		log.Debugf("debug logging enabled")
	}

	if *optMirrors == "" {
		log.Errorf("no mirrors, cannot continue")
		os.Exit(1)
	}

	m := Mirrors{}
	if err := m.LoadFile(*optMirrors); err != nil {
		log.Errorf("failed to load mirrors from %v: %v",
			*optMirrors, err)
		os.Exit(1)
	}

	log.Infof("cache root: %v", *optCacheRoot)
	cache := Cache{
		Dir: *optCacheRoot,
	}

	addr := *optListenAddr
	server := http.Server{
		Addr: addr,
		Handler: &ViaDownloadServer{
			Mirrors:       &m,
			Cache:         &cache,
			ClientTimeout: *optTimeout,
		},
	}
	log.Infof("listen on %v", addr)

	if err := server.ListenAndServe(); err != nil {
		log.Fatalf("listen failed: %v", err)
	}
}
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 amqp

import (
	"fmt"
)

func ExampleParseURL() {
	for _, s := range []string{
		"amqp://username:password@host:1234/path",
		"host:1234",
		"host",
		"host/path",
		"amqps://host",
		"/path",
		"",
		":1234",
                // Taken out because the go 1.4 URL parser isn't the same as later
		//"[::1]",
		//"[::1",
		// Output would be:
		// amqp://[::1]:amqp
		// parse amqp://[::1: missing ']' in host
	} {
		u, err := ParseURL(s)
		if err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(u)
		}
	}
	// Output:
	// amqp://username:password@host:1234/path
	// amqp://host:1234
	// amqp://host:amqp
	// amqp://host:amqp/path
	// amqps://host:amqps
	// amqp://localhost:amqp/path
	// amqp://localhost:amqp
	// parse :1234: missing protocol scheme
}
<commit_msg>PROTON-2190 Fix url_test.go on macOS (#239)<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you 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 amqp

import (
	"fmt"
	"net/url"
	"strings"
	"testing"
)

func ExampleParseURL() {
	for _, s := range []string{
		"amqp://username:password@host:1234/path",
		"host:1234",
		"host",
		"host/path",
		"amqps://host",
		"/path",
		"",
	} {
		u, err := ParseURL(s)
		if err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(u)
		}
	}
	// Output:
	// amqp://username:password@host:1234/path
	// amqp://host:1234
	// amqp://host:amqp
	// amqp://host:amqp/path
	// amqps://host:amqps
	// amqp://localhost:amqp/path
	// amqp://localhost:amqp
}

func TestParseValidURL(t *testing.T) {
	for _, s := range []struct {
		// input
		url string
		// expected
		scheme string
		user   *url.Userinfo
		host   string
		port   string
		path   string
	}{
		{"amqp://username:password@host:1234/path",
			"amqp", url.UserPassword("username", "password"), "host:1234", "1234", "/path"},
		//{"[::1]",
		//	"amqp", &url2.Userinfo{}, "[::]:amqp", "amqp", ""}, // this used to be valid example; does not parse in go 1.13
		//	                                                    //  parse [::1]: first path segment in URL cannot contain colon
	} {
		u, err := ParseURL(s.url)
		if err != nil {
			t.Errorf("Unexpected parsing error on '%s' got error '%s'", s.url, err)
			continue
		}
		if u.Scheme != s.scheme {
			t.Errorf("Unexpected scheme parsing '%s', expected '%s', got '%s'", s.url, s.scheme, u.Scheme)
		}
		if *u.User != *s.user {
			t.Errorf("Unexpected user parsing '%s', expected '%s', got '%s'", s.url, s.user, u.User)
		}
		if u.Host != s.host {
			t.Errorf("Unexpected host parsing '%s', expected '%s', got '%s'", s.url, s.host, u.Host)
		}
		if u.Port() != s.port {
			t.Errorf("Unexpected port parsing '%s', expected '%s', got '%s'", s.url, s.port, u.Port())
		}
		if u.Path != s.path {
			t.Errorf("Unexpected path parsing '%s', expected '%s', got '%s'", s.url, s.path, u.Path)
		}
	}
}

func TestParseInvalidURL(t *testing.T) {
	for _, s := range []struct {
		// input
		url string
		// expected
		inError string
	}{
		// proton errors
		{"http://seznam.cz", "invalid amqp scheme"},
		// go errors
		{":1234", "missing protocol scheme"},
		{"[::1", ""}, // error message is completely different depending on Go toolchain version
	} {
		u, err := ParseURL(s.url)
		if err == nil {
			t.Errorf("Expected error on '%s', parsed out '%s'", s.url, u)
			continue
		}
		if !strings.Contains(err.Error(), s.inError) {
			t.Errorf("Expected error '%s' to contain '%s'", err, s.inError)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/tls"
	"database/sql"
	"embed"
	"fmt"
	"html/template"
	"io/fs"
	"log"
	mathRand "math/rand"
	"net"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/NYTimes/gziphandler"
	"golang.org/x/crypto/acme/autocert"
)

//go:embed views static-files
var staticFiles embed.FS

var templates = template.New("").Funcs(template.FuncMap{"add": func(a, b int) int { return a + b }})

var hostname_whitelist = []string{
	"www.sadbox.org", "sadbox.org", "mail.sadbox.org",
	"www.sadbox.es", "sadbox.es",
	"www.geekwhack.org", "geekwhack.org",
	"www.sadbox.xyz", "sadbox.xyz",
}

var sadboxDB *sql.DB

var channels []channel

type channel struct {
	LinkName    string
	ChannelName string
}

type WebsiteName struct {
	Title, Brand string
}

type Main struct {
	Channels []channel
}

type TemplateContext struct {
	Geekhack *Geekhack
	Webname  *WebsiteName
	Main     *Main
}

func NewContext(r *http.Request, appendToTitle string) *TemplateContext {
	title := "sadbox \u00B7 org"
	host := "sadbox.org"
	for _, v := range hostname_whitelist {
		if v == r.Host {
			trimmed := strings.TrimPrefix(r.Host, "www.")
			title = strings.Replace(trimmed, ".", " \u00B7 ", -1)
			host = trimmed
			break
		}
	}
	return &TemplateContext{
		Webname: &WebsiteName{
			title + " - " + appendToTitle,
			host,
		},
	}
}

func CatchPanic(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if r := recover(); r != nil {
				log.Printf("Recovered from panic: %v", r)
				http.Error(w, "Something went wrong!", http.StatusInternalServerError)
			}
		}()

		handler.ServeHTTP(w, r)
	})
}

func SendToHTTPS(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Connection", "close")
	http.Redirect(w, r, "https://"+r.Host+r.RequestURI, http.StatusMovedPermanently)
}

func RedirectToHTTPS(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println(r.Host)

		// Don't bother sending IPs to https
		ip := net.ParseIP(strings.Trim(r.Host, "[]"))
		if ip != nil {
			handler.ServeHTTP(w, r)
			return
		}

		// If r.Host isn't an ip, maybe it's an ip:port?
		host, _, err := net.SplitHostPort(r.Host)
		if err != nil {
			SendToHTTPS(w, r)
			return
		}
		if ip = net.ParseIP(host); ip == nil { // Couldn't parse the split ip
			SendToHTTPS(w, r)
			return
		}

		handler.ServeHTTP(w, r)
	})
}

func AddHeaders(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Cache-Control", "max-age=120")
		if r.TLS != nil {
			w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
		}
		w.Header().Set("Content-Security-Policy", "default-src 'self'; object-src 'none'; frame-ancestors 'none'")
		w.Header().Set("X-Frame-Options", "DENY")
		w.Header().Set("X-Content-Type-Options", "nosniff")
		w.Header().Set("Referrer-Policy", "no-referrer, same-origin")
		w.Header().Set("X-XSS-Protection", "1; mode=block")
		handler.ServeHTTP(w, r)
	})
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		remoteHost := r.Header.Get("X-Forwarded-For")
		if remoteHost == "" {
			remoteHost = r.RemoteAddr
		}
		log.Printf("%s %s %s", remoteHost, r.Method, r.URL)
		handler.ServeHTTP(w, r)
	})
}

type sessionKeys struct {
	keys [][32]byte
	buf  []byte
	tls  *tls.Config
}

func NewSessionKeys(tls *tls.Config) *sessionKeys {
	sk := &sessionKeys{
		buf: make([]byte, 32),
		tls: tls,
	}
	sk.addNewKey()
	return sk
}

func (sk *sessionKeys) addNewKey() {
	rand.Read(sk.buf)
	newKey := [32]byte{}
	copy(newKey[:], sk.buf)
	sk.keys = append([][32]byte{newKey}, sk.keys...)
	if len(sk.keys) > 4 {
		sk.keys = sk.keys[:5]
	}
	log.Println("Rotating Session Keys")
	sk.tls.SetSessionTicketKeys(sk.keys)
}

func (sk *sessionKeys) Spin() {
	for range time.Tick(24 * time.Hour) {
		sk.addNewKey()
	}
}

func main() {
	log.Println("Starting sadbox.org")

	template.Must(templates.ParseFS(staticFiles, "views/*.tmpl"))
	log.Println(templates.DefinedTemplates())

	var err error
	sadboxDB, err = sql.Open("mysql", os.Getenv("GEEKHACK_DB"))
	if err != nil {
		log.Fatal(err)
	}
	defer sadboxDB.Close()

	err = sadboxDB.Ping()
	if err != nil {
		log.Fatal(err)
	}

	onlyStatic, err := fs.Sub(staticFiles, "static-files")
	if err != nil {
		log.Fatal(err)
	}
	staticFileServer := http.FileServer(http.FS(onlyStatic))
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == "/" {
			ctx := NewContext(r, "home")
			ctx.Main = &Main{channels}
			if err := templates.ExecuteTemplate(w, "main.tmpl", ctx); err != nil {
				log.Println(err)
			}
		} else {
			staticFileServer.ServeHTTP(w, r)
		}
	})

	http.Handle("/dick/", http.StripPrefix("/dick/", http.FileServer(http.Dir("/home/sadbox-web/dick/"))))

	mathRand.Seed(time.Now().UnixNano())

	rows, err := sadboxDB.Query(`SELECT Channel from Channels;`)
	if err != nil {
		log.Fatal(err)
	}
	for rows.Next() {
		var channelName string
		err := rows.Scan(&channelName)
		if err != nil {
			log.Fatal(err)
		}

		chanInfo := channel{fmt.Sprintf("/%s/", strings.Trim(channelName, "#")), channelName}

		ircChanHandler, err := NewIRCChannel(chanInfo)
		if err != nil {
			log.Fatal(err)
		}
		http.Handle(chanInfo.LinkName, ircChanHandler)

		channels = append(channels, chanInfo)
	}

	// Redirects to the right URL so I don't break old links
	http.Handle("/ghstats", http.RedirectHandler("/geekhack/", http.StatusMovedPermanently))
	http.Handle("/geekhack", http.RedirectHandler("/geekhack/", http.StatusMovedPermanently))

	// This will redirect people to the gmail page
	http.Handle("mail.sadbox.org/", http.RedirectHandler("https://mail.google.com/a/sadbox.org", http.StatusFound))

	servemux := gziphandler.GzipHandler(
		CatchPanic(
			Log(
				AddHeaders(http.DefaultServeMux))))

	m := autocert.Manager{
		Prompt:     autocert.AcceptTOS,
		Cache:      autocert.DirCache("/home/sadbox-web/cert-cache"),
		HostPolicy: autocert.HostWhitelist(hostname_whitelist...),
		Email:      "blue6249@gmail.com",
		ForceRSA:   true,
	}

	tlsconfig := m.TLSConfig()
	tlsconfig.PreferServerCipherSuites = true

	go NewSessionKeys(tlsconfig).Spin()

	httpSrv := &http.Server{
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
		Handler:      m.HTTPHandler(RedirectToHTTPS(servemux)),
	}
	go func() { log.Fatal(httpSrv.ListenAndServe()) }()

	server := &http.Server{
		Addr:         ":https",
		Handler:      servemux,
		TLSConfig:    tlsconfig,
		ReadTimeout:  60 * time.Minute,
		ReadHeaderTimeout: 5 * time.Second,
		WriteTimeout: 5 * time.Second,
		IdleTimeout: 30 * time.Minute,
	}
	log.Fatal(server.ListenAndServeTLS("", ""))
}
<commit_msg>bump again?<commit_after>package main

import (
	"crypto/rand"
	"crypto/tls"
	"database/sql"
	"embed"
	"fmt"
	"html/template"
	"io/fs"
	"log"
	mathRand "math/rand"
	"net"
	"net/http"
	"os"
	"strings"
	"time"

	"github.com/NYTimes/gziphandler"
	"golang.org/x/crypto/acme/autocert"
)

//go:embed views static-files
var staticFiles embed.FS

var templates = template.New("").Funcs(template.FuncMap{"add": func(a, b int) int { return a + b }})

var hostname_whitelist = []string{
	"www.sadbox.org", "sadbox.org", "mail.sadbox.org",
	"www.sadbox.es", "sadbox.es",
	"www.geekwhack.org", "geekwhack.org",
	"www.sadbox.xyz", "sadbox.xyz",
}

var sadboxDB *sql.DB

var channels []channel

type channel struct {
	LinkName    string
	ChannelName string
}

type WebsiteName struct {
	Title, Brand string
}

type Main struct {
	Channels []channel
}

type TemplateContext struct {
	Geekhack *Geekhack
	Webname  *WebsiteName
	Main     *Main
}

func NewContext(r *http.Request, appendToTitle string) *TemplateContext {
	title := "sadbox \u00B7 org"
	host := "sadbox.org"
	for _, v := range hostname_whitelist {
		if v == r.Host {
			trimmed := strings.TrimPrefix(r.Host, "www.")
			title = strings.Replace(trimmed, ".", " \u00B7 ", -1)
			host = trimmed
			break
		}
	}
	return &TemplateContext{
		Webname: &WebsiteName{
			title + " - " + appendToTitle,
			host,
		},
	}
}

func CatchPanic(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		defer func() {
			if r := recover(); r != nil {
				log.Printf("Recovered from panic: %v", r)
				http.Error(w, "Something went wrong!", http.StatusInternalServerError)
			}
		}()

		handler.ServeHTTP(w, r)
	})
}

func SendToHTTPS(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Connection", "close")
	http.Redirect(w, r, "https://"+r.Host+r.RequestURI, http.StatusMovedPermanently)
}

func RedirectToHTTPS(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println(r.Host)

		// Don't bother sending IPs to https
		ip := net.ParseIP(strings.Trim(r.Host, "[]"))
		if ip != nil {
			handler.ServeHTTP(w, r)
			return
		}

		// If r.Host isn't an ip, maybe it's an ip:port?
		host, _, err := net.SplitHostPort(r.Host)
		if err != nil {
			SendToHTTPS(w, r)
			return
		}
		if ip = net.ParseIP(host); ip == nil { // Couldn't parse the split ip
			SendToHTTPS(w, r)
			return
		}

		handler.ServeHTTP(w, r)
	})
}

func AddHeaders(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Cache-Control", "max-age=120")
		if r.TLS != nil {
			w.Header().Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload")
		}
		w.Header().Set("Content-Security-Policy", "default-src 'self'; object-src 'none'; frame-ancestors 'none'")
		w.Header().Set("X-Frame-Options", "DENY")
		w.Header().Set("X-Content-Type-Options", "nosniff")
		w.Header().Set("Referrer-Policy", "no-referrer, same-origin")
		w.Header().Set("X-XSS-Protection", "1; mode=block")
		handler.ServeHTTP(w, r)
	})
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		remoteHost := r.Header.Get("X-Forwarded-For")
		if remoteHost == "" {
			remoteHost = r.RemoteAddr
		}
		log.Printf("%s %s %s", remoteHost, r.Method, r.URL)
		handler.ServeHTTP(w, r)
	})
}

type sessionKeys struct {
	keys [][32]byte
	buf  []byte
	tls  *tls.Config
}

func NewSessionKeys(tls *tls.Config) *sessionKeys {
	sk := &sessionKeys{
		buf: make([]byte, 32),
		tls: tls,
	}
	sk.addNewKey()
	return sk
}

func (sk *sessionKeys) addNewKey() {
	rand.Read(sk.buf)
	newKey := [32]byte{}
	copy(newKey[:], sk.buf)
	sk.keys = append([][32]byte{newKey}, sk.keys...)
	if len(sk.keys) > 4 {
		sk.keys = sk.keys[:5]
	}
	log.Println("Rotating Session Keys")
	sk.tls.SetSessionTicketKeys(sk.keys)
}

func (sk *sessionKeys) Spin() {
	for range time.Tick(24 * time.Hour) {
		sk.addNewKey()
	}
}

func main() {
	log.Println("Starting sadbox.org")

	template.Must(templates.ParseFS(staticFiles, "views/*.tmpl"))
	log.Println(templates.DefinedTemplates())

	var err error
	sadboxDB, err = sql.Open("mysql", os.Getenv("GEEKHACK_DB"))
	if err != nil {
		log.Fatal(err)
	}
	defer sadboxDB.Close()

	err = sadboxDB.Ping()
	if err != nil {
		log.Fatal(err)
	}

	onlyStatic, err := fs.Sub(staticFiles, "static-files")
	if err != nil {
		log.Fatal(err)
	}
	staticFileServer := http.FileServer(http.FS(onlyStatic))
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path == "/" {
			ctx := NewContext(r, "home")
			ctx.Main = &Main{channels}
			if err := templates.ExecuteTemplate(w, "main.tmpl", ctx); err != nil {
				log.Println(err)
			}
		} else {
			staticFileServer.ServeHTTP(w, r)
		}
	})

	http.Handle("/dick/", http.StripPrefix("/dick/", http.FileServer(http.Dir("/home/sadbox-web/dick/"))))

	mathRand.Seed(time.Now().UnixNano())

	rows, err := sadboxDB.Query(`SELECT Channel from Channels;`)
	if err != nil {
		log.Fatal(err)
	}
	for rows.Next() {
		var channelName string
		err := rows.Scan(&channelName)
		if err != nil {
			log.Fatal(err)
		}

		chanInfo := channel{fmt.Sprintf("/%s/", strings.Trim(channelName, "#")), channelName}

		ircChanHandler, err := NewIRCChannel(chanInfo)
		if err != nil {
			log.Fatal(err)
		}
		http.Handle(chanInfo.LinkName, ircChanHandler)

		channels = append(channels, chanInfo)
	}

	// Redirects to the right URL so I don't break old links
	http.Handle("/ghstats", http.RedirectHandler("/geekhack/", http.StatusMovedPermanently))
	http.Handle("/geekhack", http.RedirectHandler("/geekhack/", http.StatusMovedPermanently))

	// This will redirect people to the gmail page
	http.Handle("mail.sadbox.org/", http.RedirectHandler("https://mail.google.com/a/sadbox.org", http.StatusFound))

	servemux := gziphandler.GzipHandler(
		CatchPanic(
			Log(
				AddHeaders(http.DefaultServeMux))))

	m := autocert.Manager{
		Prompt:     autocert.AcceptTOS,
		Cache:      autocert.DirCache("/home/sadbox-web/cert-cache"),
		HostPolicy: autocert.HostWhitelist(hostname_whitelist...),
		Email:      "blue6249@gmail.com",
		ForceRSA:   true,
	}

	tlsconfig := m.TLSConfig()
	tlsconfig.PreferServerCipherSuites = true

	go NewSessionKeys(tlsconfig).Spin()

	httpSrv := &http.Server{
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
		Handler:      m.HTTPHandler(RedirectToHTTPS(servemux)),
	}
	go func() { log.Fatal(httpSrv.ListenAndServe()) }()

	server := &http.Server{
		Addr:         ":https",
		Handler:      servemux,
		TLSConfig:    tlsconfig,
		ReadTimeout:  60 * time.Minute,
		ReadHeaderTimeout: 30 * time.Second,
		WriteTimeout: 60 * time.Minute,
		IdleTimeout: 30 * time.Minute,
	}
	log.Fatal(server.ListenAndServeTLS("", ""))
}
<|endoftext|>


<commit_before>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package teams

import (
	"context"
	"testing"

	"github.com/keybase/client/go/kbtest"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/stretchr/testify/require"
)

func createUserAndRootTeam(t *testing.T) (fu *kbtest.FakeUser, nm keybase1.TeamName, g *libkb.GlobalContext, cleanup func()) {
	tc := SetupTest(t, "team", 1)
	cleanup = func() { tc.Cleanup() }

	// Note that the length limit for a team name, with the additional suffix
	// below, is 16 characters. We have 5 to play with, including the implicit
	// underscore after the prefix.
	u, err := kbtest.CreateAndSignupFakeUser("t", tc.G)
	require.NoError(t, err)

	teamName := u.Username + "t"

	err = CreateRootTeam(context.TODO(), tc.G, teamName)
	require.NoError(t, err)

	nm, err = keybase1.TeamNameFromString(teamName)
	require.NoError(t, err)
	require.Equal(t, nm.String(), teamName)

	return u, nm, tc.G, cleanup
}

func TestCreateTeam(t *testing.T) {
	_, _, _, cleanup := createUserAndRootTeam(t)
	cleanup()
}

func TestCreateTeamAfterAccountReset(t *testing.T) {
	tc := SetupTest(t, "team", 1)
	defer tc.Cleanup()

	// Note that the length limit for a team name, with the additional suffix
	// below, is 16 characters. We have 5 to play with, including the implicit
	// underscore after the prefix.
	u, err := kbtest.CreateAndSignupFakeUser("t", tc.G)
	require.NoError(t, err)

	// Now the user's fully qualified username should be like user%seqno. If we
	// don't format this properly, the server will reject the post.
	kbtest.ResetAccount(tc, u)

	// this will reprovision as an eldest device:
	err = u.Login(tc.G)
	require.NoError(t, err)
	if err = kbtest.AssertProvisioned(tc); err != nil {
		t.Fatal(err)
	}

	teamName := u.Username + "T"
	err = CreateRootTeam(context.TODO(), tc.G, teamName)
	require.NoError(t, err)
}

func TestCreateSubteam(t *testing.T) {
	tc := SetupTest(t, "team", 1)
	defer tc.Cleanup()

	u, err := kbtest.CreateAndSignupFakeUser("t", tc.G)
	require.NoError(t, err)

	parentTeamName, err := keybase1.TeamNameFromString(u.Username + "T")
	require.NoError(t, err)
	err = CreateRootTeam(context.TODO(), tc.G, parentTeamName.String())
	require.NoError(t, err)

	subteamBasename := "mysubteam"
	_, err = CreateSubteam(context.TODO(), tc.G, subteamBasename, parentTeamName)
	require.NoError(t, err)

	// Fetch the subteam we just created, to make sure it's there.
	subteamFQName, err := parentTeamName.Append(subteamBasename)
	require.NoError(t, err)
	subteam, err := Load(context.TODO(), tc.G, keybase1.LoadTeamArg{
		Name: subteamFQName.String(),
	})
	require.NoError(t, err)
	require.Equal(t, subteamFQName, subteam.Name())
	require.Equal(t, keybase1.Seqno(1), subteam.chain().GetLatestSeqno())

	assertRole(tc, subteamFQName.String(), u.Username, keybase1.TeamRole_OWNER)
}

func TestCreateSubSubteam(t *testing.T) {
	tc := SetupTest(t, "team", 1)
	defer tc.Cleanup()

	u, err := kbtest.CreateAndSignupFakeUser("t", tc.G)
	require.NoError(t, err)

	parentTeamName, err := keybase1.TeamNameFromString(u.Username + "T")
	require.NoError(t, err)
	err = CreateRootTeam(context.TODO(), tc.G, parentTeamName.String())
	require.NoError(t, err)

	subteamBasename := "bbb"
	_, err = CreateSubteam(context.TODO(), tc.G, subteamBasename, parentTeamName)
	require.NoError(t, err)
	subteamName, err := parentTeamName.Append(subteamBasename)
	require.NoError(t, err)

	subsubteamBasename := "ccc"
	_, err = CreateSubteam(context.TODO(), tc.G, subsubteamBasename, subteamName)
	require.NoError(t, err)
}
<commit_msg>Add test of explicit admin in subteam<commit_after>// Copyright 2017 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package teams

import (
	"context"
	"testing"

	"github.com/keybase/client/go/kbtest"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol/keybase1"
	"github.com/stretchr/testify/require"
)

func createUserAndRootTeam(t *testing.T) (fu *kbtest.FakeUser, nm keybase1.TeamName, g *libkb.GlobalContext, cleanup func()) {
	tc := SetupTest(t, "team", 1)
	cleanup = func() { tc.Cleanup() }

	// Note that the length limit for a team name, with the additional suffix
	// below, is 16 characters. We have 5 to play with, including the implicit
	// underscore after the prefix.
	u, err := kbtest.CreateAndSignupFakeUser("t", tc.G)
	require.NoError(t, err)

	teamName := u.Username + "t"

	err = CreateRootTeam(context.TODO(), tc.G, teamName)
	require.NoError(t, err)

	nm, err = keybase1.TeamNameFromString(teamName)
	require.NoError(t, err)
	require.Equal(t, nm.String(), teamName)

	return u, nm, tc.G, cleanup
}

func TestCreateTeam(t *testing.T) {
	_, _, _, cleanup := createUserAndRootTeam(t)
	cleanup()
}

func TestCreateTeamAfterAccountReset(t *testing.T) {
	tc := SetupTest(t, "team", 1)
	defer tc.Cleanup()

	// Note that the length limit for a team name, with the additional suffix
	// below, is 16 characters. We have 5 to play with, including the implicit
	// underscore after the prefix.
	u, err := kbtest.CreateAndSignupFakeUser("t", tc.G)
	require.NoError(t, err)

	// Now the user's fully qualified username should be like user%seqno. If we
	// don't format this properly, the server will reject the post.
	kbtest.ResetAccount(tc, u)

	// this will reprovision as an eldest device:
	err = u.Login(tc.G)
	require.NoError(t, err)
	if err = kbtest.AssertProvisioned(tc); err != nil {
		t.Fatal(err)
	}

	teamName := u.Username + "T"
	err = CreateRootTeam(context.TODO(), tc.G, teamName)
	require.NoError(t, err)
}

func TestCreateSubteam(t *testing.T) {
	tc := SetupTest(t, "team", 1)
	defer tc.Cleanup()

	u, err := kbtest.CreateAndSignupFakeUser("t", tc.G)
	require.NoError(t, err)

	parentTeamName, err := keybase1.TeamNameFromString(u.Username + "T")
	require.NoError(t, err)
	err = CreateRootTeam(context.TODO(), tc.G, parentTeamName.String())
	require.NoError(t, err)

	subteamBasename := "mysubteam"
	_, err = CreateSubteam(context.TODO(), tc.G, subteamBasename, parentTeamName)
	require.NoError(t, err)

	// Fetch the subteam we just created, to make sure it's there.
	subteamFQName, err := parentTeamName.Append(subteamBasename)
	require.NoError(t, err)
	subteam, err := Load(context.TODO(), tc.G, keybase1.LoadTeamArg{
		Name: subteamFQName.String(),
	})
	require.NoError(t, err)
	require.Equal(t, subteamFQName, subteam.Name())
	require.Equal(t, keybase1.Seqno(1), subteam.chain().GetLatestSeqno())

	// current behavior of this package is to make the creator the admin, so
	// make sure that is the case until we change it
	assertRole(tc, subteamFQName.String(), u.Username, keybase1.TeamRole_ADMIN)
}

func TestCreateSubSubteam(t *testing.T) {
	tc := SetupTest(t, "team", 1)
	defer tc.Cleanup()

	u, err := kbtest.CreateAndSignupFakeUser("t", tc.G)
	require.NoError(t, err)

	parentTeamName, err := keybase1.TeamNameFromString(u.Username + "T")
	require.NoError(t, err)
	err = CreateRootTeam(context.TODO(), tc.G, parentTeamName.String())
	require.NoError(t, err)

	subteamBasename := "bbb"
	_, err = CreateSubteam(context.TODO(), tc.G, subteamBasename, parentTeamName)
	require.NoError(t, err)
	subteamName, err := parentTeamName.Append(subteamBasename)
	require.NoError(t, err)

	// current behavior of this package is to make the creator the admin, so
	// make sure that is the case until we change it
	assertRole(tc, subteamName.String(), u.Username, keybase1.TeamRole_ADMIN)

	subsubteamBasename := "ccc"
	_, err = CreateSubteam(context.TODO(), tc.G, subsubteamBasename, subteamName)
	require.NoError(t, err)

	subsubteamName, err := parentTeamName.Append(subteamBasename)
	require.NoError(t, err)

	// current behavior of this package is to make the creator the admin, so
	// make sure that is the case until we change it
	assertRole(tc, subsubteamName.String(), u.Username, keybase1.TeamRole_ADMIN)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
)

func main() {
	fmt.Println("program start today")
	fmt.Println("yidane come here")
	fmt.Println("Frank-Ding:wq")
	fmt.Println("jiangyd conne here")
}
<commit_msg>liupeng come heregit status!<commit_after>package main

import (
	"fmt"
)

func main() {
	fmt.Println("program start today")
	fmt.Println("yidane come here")
	fmt.Println("Frank-Ding:wq")
	fmt.Println("jiangyd conne here")
	fmt.Println("liupeng come here!!!")
}
<|endoftext|>


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

package vtctl

import (
	"flag"
	"fmt"
	"time"

	"github.com/youtube/vitess/go/vt/topo"
	"github.com/youtube/vitess/go/vt/wrangler"
	"golang.org/x/net/context"
)

func init() {
	addCommand("Tablets", command{
		"DemoteMaster",
		commandDemoteMaster,
		"<tablet alias>",
		"Demotes a master tablet."})
	addCommand("Tablets", command{
		"ReparentTablet",
		commandReparentTablet,
		"<tablet alias>",
		"Reparent a tablet to the current master in the shard. This only works if the current slave position matches the last known reparent action."})
	addCommand("Shards", command{
		"ReparentShard",
		commandReparentShard,
		"[-force] [-leave-master-read-only] <keyspace/shard> <tablet alias>",
		"Specify which shard to reparent and which tablet should be the new master."})
	addCommand("Shards", command{
		"InitShardMaster",
		commandInitShardMaster,
		"[-force] [-wait_slave_timeout=<duration>] <keyspace/shard> <tablet alias>",
		"Sets the initial master for a shard. Will make all other tablets in the shard slaves of the provided master. WARNING: this could cause data loss on an already replicating shard, then PlannedReparentShard or EmergencyReparentShard should be used instead."})
	addCommand("Shards", command{
		"PlannedReparentShard",
		commandPlannedReparentShard,
		"<keyspace/shard> <tablet alias>",
		"Reparents the shard to the new master. Both old and new master need to be up and running."})
	addCommand("Shards", command{
		"EmergencyReparentShard",
		commandEmergencyReparentShard,
		"<keyspace/shard> <tablet alias>",
		"Reparents the shard to the new master. Assumes the old master is dead and not responsding."})
}

func commandDemoteMaster(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 1 {
		return fmt.Errorf("action DemoteMaster requires <tablet alias>")
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletInfo, err := wr.TopoServer().GetTablet(tabletAlias)
	if err != nil {
		return err
	}
	_, err = wr.TabletManagerClient().DemoteMaster(ctx, tabletInfo)
	return err
}

func commandReparentTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 1 {
		return fmt.Errorf("action ReparentTablet requires <tablet alias>")
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	return wr.ReparentTablet(ctx, tabletAlias)
}

func commandReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	leaveMasterReadOnly := subFlags.Bool("leave-master-read-only", false, "leaves the master read-only after reparenting")
	force := subFlags.Bool("force", false, "will force the reparent even if the master is already correct")
	waitSlaveTimeout := subFlags.Duration("wait_slave_timeout", 30*time.Second, "time to wait for slaves to catch up in reparenting")
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 2 {
		return fmt.Errorf("action ReparentShard requires <keyspace/shard> <tablet alias>")
	}

	keyspace, shard, err := topo.ParseKeyspaceShardString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(1))
	if err != nil {
		return err
	}
	return wr.ReparentShard(ctx, keyspace, shard, tabletAlias, *leaveMasterReadOnly, *force, *waitSlaveTimeout)
}

func commandInitShardMaster(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	force := subFlags.Bool("force", false, "will force the reparent even if the provided tablet is not a master or the shard master")
	waitSlaveTimeout := subFlags.Duration("wait_slave_timeout", 30*time.Second, "time to wait for slaves to catch up in reparenting")
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 2 {
		return fmt.Errorf("action InitShardMaster requires <keyspace/shard> <tablet alias>")
	}
	keyspace, shard, err := topo.ParseKeyspaceShardString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(1))
	if err != nil {
		return err
	}
	return wr.InitShardMaster(ctx, keyspace, shard, tabletAlias, *force, *waitSlaveTimeout)
}

func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	waitSlaveTimeout := subFlags.Duration("wait_slave_timeout", 30*time.Second, "time to wait for slaves to catch up in reparenting")
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 2 {
		return fmt.Errorf("action PlannedReparentShard requires <keyspace/shard> <tablet alias>")
	}

	keyspace, shard, err := topo.ParseKeyspaceShardString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(1))
	if err != nil {
		return err
	}
	return wr.PlannedReparentShard(ctx, keyspace, shard, tabletAlias, *waitSlaveTimeout)
}

func commandEmergencyReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	waitSlaveTimeout := subFlags.Duration("wait_slave_timeout", 30*time.Second, "time to wait for slaves to catch up in reparenting")
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 2 {
		return fmt.Errorf("action EmergencyReparentShard requires <keyspace/shard> <tablet alias>")
	}

	keyspace, shard, err := topo.ParseKeyspaceShardString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(1))
	if err != nil {
		return err
	}
	return wr.EmergencyReparentShard(ctx, keyspace, shard, tabletAlias, *waitSlaveTimeout)
}
<commit_msg>Removing external 'vtctl ReparentShard' command.<commit_after>// Copyright 2013, Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package vtctl

import (
	"flag"
	"fmt"
	"time"

	"github.com/youtube/vitess/go/vt/topo"
	"github.com/youtube/vitess/go/vt/wrangler"
	"golang.org/x/net/context"
)

func init() {
	addCommand("Tablets", command{
		"DemoteMaster",
		commandDemoteMaster,
		"<tablet alias>",
		"Demotes a master tablet."})
	addCommand("Tablets", command{
		"ReparentTablet",
		commandReparentTablet,
		"<tablet alias>",
		"Reparent a tablet to the current master in the shard. This only works if the current slave position matches the last known reparent action."})
	addCommand("Shards", command{
		"InitShardMaster",
		commandInitShardMaster,
		"[-force] [-wait_slave_timeout=<duration>] <keyspace/shard> <tablet alias>",
		"Sets the initial master for a shard. Will make all other tablets in the shard slaves of the provided master. WARNING: this could cause data loss on an already replicating shard, then PlannedReparentShard or EmergencyReparentShard should be used instead."})
	addCommand("Shards", command{
		"PlannedReparentShard",
		commandPlannedReparentShard,
		"<keyspace/shard> <tablet alias>",
		"Reparents the shard to the new master. Both old and new master need to be up and running."})
	addCommand("Shards", command{
		"EmergencyReparentShard",
		commandEmergencyReparentShard,
		"<keyspace/shard> <tablet alias>",
		"Reparents the shard to the new master. Assumes the old master is dead and not responsding."})
}

func commandDemoteMaster(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 1 {
		return fmt.Errorf("action DemoteMaster requires <tablet alias>")
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletInfo, err := wr.TopoServer().GetTablet(tabletAlias)
	if err != nil {
		return err
	}
	_, err = wr.TabletManagerClient().DemoteMaster(ctx, tabletInfo)
	return err
}

func commandReparentTablet(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 1 {
		return fmt.Errorf("action ReparentTablet requires <tablet alias>")
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	return wr.ReparentTablet(ctx, tabletAlias)
}

func commandInitShardMaster(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	force := subFlags.Bool("force", false, "will force the reparent even if the provided tablet is not a master or the shard master")
	waitSlaveTimeout := subFlags.Duration("wait_slave_timeout", 30*time.Second, "time to wait for slaves to catch up in reparenting")
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 2 {
		return fmt.Errorf("action InitShardMaster requires <keyspace/shard> <tablet alias>")
	}
	keyspace, shard, err := topo.ParseKeyspaceShardString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(1))
	if err != nil {
		return err
	}
	return wr.InitShardMaster(ctx, keyspace, shard, tabletAlias, *force, *waitSlaveTimeout)
}

func commandPlannedReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	waitSlaveTimeout := subFlags.Duration("wait_slave_timeout", 30*time.Second, "time to wait for slaves to catch up in reparenting")
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 2 {
		return fmt.Errorf("action PlannedReparentShard requires <keyspace/shard> <tablet alias>")
	}

	keyspace, shard, err := topo.ParseKeyspaceShardString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(1))
	if err != nil {
		return err
	}
	return wr.PlannedReparentShard(ctx, keyspace, shard, tabletAlias, *waitSlaveTimeout)
}

func commandEmergencyReparentShard(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error {
	waitSlaveTimeout := subFlags.Duration("wait_slave_timeout", 30*time.Second, "time to wait for slaves to catch up in reparenting")
	if err := subFlags.Parse(args); err != nil {
		return err
	}
	if subFlags.NArg() != 2 {
		return fmt.Errorf("action EmergencyReparentShard requires <keyspace/shard> <tablet alias>")
	}

	keyspace, shard, err := topo.ParseKeyspaceShardString(subFlags.Arg(0))
	if err != nil {
		return err
	}
	tabletAlias, err := topo.ParseTabletAliasString(subFlags.Arg(1))
	if err != nil {
		return err
	}
	return wr.EmergencyReparentShard(ctx, keyspace, shard, tabletAlias, *waitSlaveTimeout)
}
<|endoftext|>


<commit_before>// Package c2go contains the main function for running the executable.
//
// Installation
//
//     go get -u github.com/elliotchance/c2go
//
// Usage
//
//     c2go myfile.c
//
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"errors"
	"reflect"

	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/transpiler"
)

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.16.4 Radium 2017-10-18"

var stderr io.Writer = os.Stderr

// ProgramArgs defines the options available when processing the program. There
// is no constructor since the zeroed out values are the appropriate defaults -
// you need only set the options you need.
//
// TODO: Better separation on CLI modes
// https://github.com/elliotchance/c2go/issues/134
type ProgramArgs struct {
	verbose     bool
	ast         bool
	inputFile   string
	outputFile  string
	packageName string

	// A private option to output the Go as a *_test.go file.
	outputAsTest bool
}

func readAST(data []byte) []string {
	uncolored := regexp.MustCompile(`\x1b\[[\d;]+m`).ReplaceAll(data, []byte{})
	return strings.Split(string(uncolored), "\n")
}

type treeNode struct {
	indent int
	node   ast.Node
}

func convertLinesToNodes(lines []string) []treeNode {
	nodes := make([]treeNode, len(lines))
	var counter int
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}

		// It is tempting to discard null AST nodes, but these may
		// have semantic importance: for example, they represent omitted
		// for-loop conditions, as in for(;;).
		line = strings.Replace(line, "<<<NULL>>>", "NullStmt", 1)
		trimmed := strings.TrimLeft(line, "|\\- `")
		node := ast.Parse(trimmed)
		indentLevel := (len(line) - len(trimmed)) / 2
		nodes[counter] = treeNode{indentLevel, node}
		counter++
	}
	nodes = nodes[0:counter]

	return nodes
}

// buildTree converts an array of nodes, each prefixed with a depth into a tree.
func buildTree(nodes []treeNode, depth int) []ast.Node {
	if len(nodes) == 0 {
		return []ast.Node{}
	}

	// Split the list into sections, treat each section as a tree with its own
	// root.
	sections := [][]treeNode{}
	for _, node := range nodes {
		if node.indent == depth {
			sections = append(sections, []treeNode{node})
		} else {
			sections[len(sections)-1] = append(sections[len(sections)-1], node)
		}
	}

	results := []ast.Node{}
	for _, section := range sections {
		slice := []treeNode{}
		for _, n := range section {
			if n.indent > depth {
				slice = append(slice, n)
			}
		}

		children := buildTree(slice, depth+1)
		for _, child := range children {
			section[0].node.AddChild(child)
		}
		results = append(results, section[0].node)
	}

	return results
}

func toJSON(tree []interface{}) []map[string]interface{} {
	r := make([]map[string]interface{}, len(tree))

	for j, n := range tree {
		rn := reflect.ValueOf(n).Elem()
		r[j] = make(map[string]interface{})
		r[j]["node"] = rn.Type().Name()

		for i := 0; i < rn.NumField(); i++ {
			name := strings.ToLower(rn.Type().Field(i).Name)
			value := rn.Field(i).Interface()

			if name == "children" {
				v := value.([]interface{})

				if len(v) == 0 {
					continue
				}

				value = toJSON(v)
			}

			r[j][name] = value
		}
	}

	return r
}

func check(prefix string, e error) {
	if e != nil {
		panic(prefix + e.Error())
	}
}

// Start begins transpiling an input file.
func Start(args ProgramArgs) error {
	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("The $GOPATH must be set")
	}

	// 1. Compile it first (checking for errors)
	_, err := os.Stat(args.inputFile)
	if err != nil {
		return fmt.Errorf("Input file is not found")
	}

	// 2. Preprocess
	var pp []byte
	{
		// See : https://clang.llvm.org/docs/CommandGuide/clang.html
		// clang -E <file>    Run the preprocessor stage.
		cmd := exec.Command("clang", "-E", args.inputFile)
		var out bytes.Buffer
		var stderr bytes.Buffer
		cmd.Stdout = &out
		cmd.Stderr = &stderr
		err = cmd.Run()
		if err != nil {
			return fmt.Errorf("preprocess failed: %v\nStdErr = %v", err, stderr.String())
		}
		pp = []byte(out.String())
	}

	ppFilePath := path.Join("/tmp", "pp.c")
	err = ioutil.WriteFile(ppFilePath, pp, 0644)
	if err != nil {
		return fmt.Errorf("writing to %s failed: %v", ppFilePath, err)
	}

	// 3. Generate JSON from AST
	astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output()
	if err != nil {
		// If clang fails it still prints out the AST, so we have to run it
		// again to get the real error.
		errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput()

		panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
	}

	lines := readAST(astPP)
	if args.ast {
		for _, l := range lines {
			fmt.Println(l)
		}
		fmt.Println()

		return nil
	}

	p := program.NewProgram()
	p.Verbose = args.verbose
	p.OutputAsTest = true // args.outputAsTest

	nodes := convertLinesToNodes(lines)
	tree := buildTree(nodes, 0)
	ast.FixPositions(tree)

	// Repair the floating literals. See RepairFloatingLiteralsFromSource for
	// more information.
	floatingErrors := ast.RepairFloatingLiteralsFromSource(tree[0], ppFilePath)

	for _, fErr := range floatingErrors {
		message := fmt.Sprintf("could not read exact floating literal: %s",
			fErr.Err.Error())
		p.AddMessage(p.GenerateWarningMessage(errors.New(message), fErr.Node))
	}

	err = transpiler.TranspileAST(args.inputFile, args.packageName, p, tree[0].(ast.Node))
	if err != nil {
		panic(err)
	}

	outputFilePath := args.outputFile

	if outputFilePath == "" {
		cleanFileName := filepath.Clean(filepath.Base(args.inputFile))
		extension := filepath.Ext(args.inputFile)
		outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go"
	}

	err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0644)
	if err != nil {
		return fmt.Errorf("writing C output file failed: %v", err)
	}

	return nil
}

// newTempFile - returns temp file
func newTempFile(dir, prefix, suffix string) (*os.File, error) {
	for index := 1; index < 10000; index++ {
		path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix))
		if _, err := os.Stat(path); err != nil {
			return os.Create(path)
		}
	}
	return nil, fmt.Errorf("could not create file: %s%03d%s", prefix, 1, suffix)
}

var (
	versionFlag       = flag.Bool("v", false, "print the version and exit")
	transpileCommand  = flag.NewFlagSet("transpile", flag.ContinueOnError)
	verboseFlag       = transpileCommand.Bool("V", false, "print progress as comments")
	outputFlag        = transpileCommand.String("o", "", "output Go generated code to the specified file")
	packageFlag       = transpileCommand.String("p", "main", "set the name of the generated package")
	transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
	astCommand        = flag.NewFlagSet("ast", flag.ContinueOnError)
	astHelpFlag       = astCommand.Bool("h", false, "print help information")
)

func main() {
	code := runCommand()
	if code != 0 {
		os.Exit(code)
	}
}

func runCommand() int {
	flag.Usage = func() {
		usage := "Usage: %s [-v] [<command>] [<flags>] file.c\n\n"
		usage += "Commands:\n"
		usage += "  transpile\ttranspile an input C source file to Go\n"
		usage += "  ast\t\tprint AST before translated Go code\n\n"

		usage += "Flags:\n"
		fmt.Fprintf(stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	transpileCommand.SetOutput(stderr)
	astCommand.SetOutput(stderr)

	flag.Parse()

	if *versionFlag {
		// Simply print out the version and exit.
		fmt.Println(Version)
		return 0
	}

	if flag.NArg() < 1 {
		flag.Usage()
		return 1
	}

	args := ProgramArgs{verbose: *verboseFlag, ast: false}

	switch os.Args[1] {
	case "ast":
		err := astCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("ast command cannot parse: %v", err)
			return 1
		}

		if *astHelpFlag || astCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s ast file.c\n", os.Args[0])
			astCommand.PrintDefaults()
			return 1
		}

		args.ast = true
		args.inputFile = astCommand.Arg(0)
	case "transpile":
		err := transpileCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("transpile command cannot parse: %v", err)
			return 1
		}

		if *transpileHelpFlag || transpileCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file.c\n", os.Args[0])
			transpileCommand.PrintDefaults()
			return 1
		}

		args.inputFile = transpileCommand.Arg(0)
		args.outputFile = *outputFlag
		args.packageName = *packageFlag
	default:
		flag.Usage()
		return 1
	}

	if err := Start(args); err != nil {
		fmt.Printf("Error: %v", err)
		return 1
	}

	return 0
}
<commit_msg>Use temporary folder for file pp.c. Fixes #244  (#247)<commit_after>// Package c2go contains the main function for running the executable.
//
// Installation
//
//     go get -u github.com/elliotchance/c2go
//
// Usage
//
//     c2go myfile.c
//
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"errors"
	"reflect"

	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/transpiler"
)

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.16.4 Radium 2017-10-18"

var stderr io.Writer = os.Stderr

// ProgramArgs defines the options available when processing the program. There
// is no constructor since the zeroed out values are the appropriate defaults -
// you need only set the options you need.
//
// TODO: Better separation on CLI modes
// https://github.com/elliotchance/c2go/issues/134
type ProgramArgs struct {
	verbose     bool
	ast         bool
	inputFile   string
	outputFile  string
	packageName string

	// A private option to output the Go as a *_test.go file.
	outputAsTest bool
}

func readAST(data []byte) []string {
	uncolored := regexp.MustCompile(`\x1b\[[\d;]+m`).ReplaceAll(data, []byte{})
	return strings.Split(string(uncolored), "\n")
}

type treeNode struct {
	indent int
	node   ast.Node
}

func convertLinesToNodes(lines []string) []treeNode {
	nodes := make([]treeNode, len(lines))
	var counter int
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}

		// It is tempting to discard null AST nodes, but these may
		// have semantic importance: for example, they represent omitted
		// for-loop conditions, as in for(;;).
		line = strings.Replace(line, "<<<NULL>>>", "NullStmt", 1)
		trimmed := strings.TrimLeft(line, "|\\- `")
		node := ast.Parse(trimmed)
		indentLevel := (len(line) - len(trimmed)) / 2
		nodes[counter] = treeNode{indentLevel, node}
		counter++
	}
	nodes = nodes[0:counter]

	return nodes
}

// buildTree converts an array of nodes, each prefixed with a depth into a tree.
func buildTree(nodes []treeNode, depth int) []ast.Node {
	if len(nodes) == 0 {
		return []ast.Node{}
	}

	// Split the list into sections, treat each section as a tree with its own
	// root.
	sections := [][]treeNode{}
	for _, node := range nodes {
		if node.indent == depth {
			sections = append(sections, []treeNode{node})
		} else {
			sections[len(sections)-1] = append(sections[len(sections)-1], node)
		}
	}

	results := []ast.Node{}
	for _, section := range sections {
		slice := []treeNode{}
		for _, n := range section {
			if n.indent > depth {
				slice = append(slice, n)
			}
		}

		children := buildTree(slice, depth+1)
		for _, child := range children {
			section[0].node.AddChild(child)
		}
		results = append(results, section[0].node)
	}

	return results
}

func toJSON(tree []interface{}) []map[string]interface{} {
	r := make([]map[string]interface{}, len(tree))

	for j, n := range tree {
		rn := reflect.ValueOf(n).Elem()
		r[j] = make(map[string]interface{})
		r[j]["node"] = rn.Type().Name()

		for i := 0; i < rn.NumField(); i++ {
			name := strings.ToLower(rn.Type().Field(i).Name)
			value := rn.Field(i).Interface()

			if name == "children" {
				v := value.([]interface{})

				if len(v) == 0 {
					continue
				}

				value = toJSON(v)
			}

			r[j][name] = value
		}
	}

	return r
}

func check(prefix string, e error) {
	if e != nil {
		panic(prefix + e.Error())
	}
}

// Start begins transpiling an input file.
func Start(args ProgramArgs) error {
	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("The $GOPATH must be set")
	}

	// 1. Compile it first (checking for errors)
	_, err := os.Stat(args.inputFile)
	if err != nil {
		return fmt.Errorf("Input file is not found")
	}

	// 2. Preprocess
	var pp []byte
	{
		// See : https://clang.llvm.org/docs/CommandGuide/clang.html
		// clang -E <file>    Run the preprocessor stage.
		cmd := exec.Command("clang", "-E", args.inputFile)
		var out bytes.Buffer
		var stderr bytes.Buffer
		cmd.Stdout = &out
		cmd.Stderr = &stderr
		err = cmd.Run()
		if err != nil {
			return fmt.Errorf("preprocess failed: %v\nStdErr = %v", err, stderr.String())
		}
		pp = []byte(out.String())
	}

	dir, err := ioutil.TempDir("", "c2go")
	if err != nil {
		return fmt.Errorf("Cannot create temp folder: %v", err)
	}
	defer os.RemoveAll(dir) // clean up

	ppFilePath := path.Join(dir, "pp.c")
	err = ioutil.WriteFile(ppFilePath, pp, 0644)
	if err != nil {
		return fmt.Errorf("writing to %s failed: %v", ppFilePath, err)
	}

	// 3. Generate JSON from AST
	astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", ppFilePath).Output()
	if err != nil {
		// If clang fails it still prints out the AST, so we have to run it
		// again to get the real error.
		errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput()

		panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
	}

	lines := readAST(astPP)
	if args.ast {
		for _, l := range lines {
			fmt.Println(l)
		}
		fmt.Println()

		return nil
	}

	p := program.NewProgram()
	p.Verbose = args.verbose
	p.OutputAsTest = true // args.outputAsTest

	nodes := convertLinesToNodes(lines)
	tree := buildTree(nodes, 0)
	ast.FixPositions(tree)

	// Repair the floating literals. See RepairFloatingLiteralsFromSource for
	// more information.
	floatingErrors := ast.RepairFloatingLiteralsFromSource(tree[0], ppFilePath)

	for _, fErr := range floatingErrors {
		message := fmt.Sprintf("could not read exact floating literal: %s",
			fErr.Err.Error())
		p.AddMessage(p.GenerateWarningMessage(errors.New(message), fErr.Node))
	}

	err = transpiler.TranspileAST(args.inputFile, args.packageName, p, tree[0].(ast.Node))
	if err != nil {
		panic(err)
	}

	outputFilePath := args.outputFile

	if outputFilePath == "" {
		cleanFileName := filepath.Clean(filepath.Base(args.inputFile))
		extension := filepath.Ext(args.inputFile)
		outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go"
	}

	err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0644)
	if err != nil {
		return fmt.Errorf("writing C output file failed: %v", err)
	}

	return nil
}

// newTempFile - returns temp file
func newTempFile(dir, prefix, suffix string) (*os.File, error) {
	for index := 1; index < 10000; index++ {
		path := filepath.Join(dir, fmt.Sprintf("%s%03d%s", prefix, index, suffix))
		if _, err := os.Stat(path); err != nil {
			return os.Create(path)
		}
	}
	return nil, fmt.Errorf("could not create file: %s%03d%s", prefix, 1, suffix)
}

var (
	versionFlag       = flag.Bool("v", false, "print the version and exit")
	transpileCommand  = flag.NewFlagSet("transpile", flag.ContinueOnError)
	verboseFlag       = transpileCommand.Bool("V", false, "print progress as comments")
	outputFlag        = transpileCommand.String("o", "", "output Go generated code to the specified file")
	packageFlag       = transpileCommand.String("p", "main", "set the name of the generated package")
	transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
	astCommand        = flag.NewFlagSet("ast", flag.ContinueOnError)
	astHelpFlag       = astCommand.Bool("h", false, "print help information")
)

func main() {
	code := runCommand()
	if code != 0 {
		os.Exit(code)
	}
}

func runCommand() int {
	flag.Usage = func() {
		usage := "Usage: %s [-v] [<command>] [<flags>] file.c\n\n"
		usage += "Commands:\n"
		usage += "  transpile\ttranspile an input C source file to Go\n"
		usage += "  ast\t\tprint AST before translated Go code\n\n"

		usage += "Flags:\n"
		fmt.Fprintf(stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	transpileCommand.SetOutput(stderr)
	astCommand.SetOutput(stderr)

	flag.Parse()

	if *versionFlag {
		// Simply print out the version and exit.
		fmt.Println(Version)
		return 0
	}

	if flag.NArg() < 1 {
		flag.Usage()
		return 1
	}

	args := ProgramArgs{verbose: *verboseFlag, ast: false}

	switch os.Args[1] {
	case "ast":
		err := astCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("ast command cannot parse: %v", err)
			return 1
		}

		if *astHelpFlag || astCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s ast file.c\n", os.Args[0])
			astCommand.PrintDefaults()
			return 1
		}

		args.ast = true
		args.inputFile = astCommand.Arg(0)
	case "transpile":
		err := transpileCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("transpile command cannot parse: %v", err)
			return 1
		}

		if *transpileHelpFlag || transpileCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file.c\n", os.Args[0])
			transpileCommand.PrintDefaults()
			return 1
		}

		args.inputFile = transpileCommand.Arg(0)
		args.outputFile = *outputFlag
		args.packageName = *packageFlag
	default:
		flag.Usage()
		return 1
	}

	if err := Start(args); err != nil {
		fmt.Printf("Error: %v", err)
		return 1
	}

	return 0
}
<|endoftext|>