<commit_before>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
	"regexp"
)

var _ = Describe("stack command", func() {
	var (
		orgName          string
		spaceName        string
		stackName        string
		stackDescription string
	)

	BeforeEach(func() {
		orgName = helpers.NewOrgName()
		spaceName = helpers.NewSpaceName()
		stackName = helpers.PrefixedRandomName("stack")
		stackDescription = "this is a test stack"
	})

	Describe("help", func() {
		When("--help flag is set", func() {
			It("Displays command usage to output", func() {
				session := helpers.CF("stack", "--help")

				Eventually(session).Should(Say(`NAME:`))
				Eventually(session).Should(Say(`stack - Show information for a stack \(a stack is a pre-built file system, including an operating system, that can run apps\)`))
				Eventually(session).Should(Say("USAGE:"))
				Eventually(session).Should(Say("cf stack STACK_NAME"))

				Eventually(session).Should(Exit(0))
			})
		})
	})

	When("the stack name is not provided", func() {
		It("tells the user that the stack name is required, prints help text, and exits 1", func() {
			session := helpers.CF("stack")

			Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `STACK_NAME` was not provided"))
			Eventually(session).Should(Say("NAME:"))
			Eventually(session).Should(Exit(1))
		})
	})

	When("the environment is not setup correctly", func() {
		It("fails with the appropriate errors", func() {
			helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "stack", stackName)
		})
	})

	When("the environment is set up correctly", func() {
		var username string

		BeforeEach(func() {
			helpers.SetupCF(orgName, spaceName)
			username, _ = helpers.GetCredentials()
		})

		AfterEach(func() {
			helpers.QuickDeleteOrg(orgName)
		})

		When("the input is invalid", func() {
			When("there are not enough arguments", func() {
				It("outputs the usage and exits 1", func() {
					session := helpers.CF("stack")

					Eventually(session.Err).Should(Say("Incorrect Usage:"))
					Eventually(session).Should(Say("NAME:"))
					Eventually(session).Should(Exit(1))
				})
			})

			When("there too many arguments", func() {
				It("ignores the extra arguments", func() {
					session := helpers.CF("stack", stackName, "extra")

					Eventually(session).Should(Say(`Getting stack %s in org %s / space %s as %s\.\.\.`, stackName, orgName, spaceName, username))
					Eventually(session.Err).Should(Say("Stack %s not found", stackName))
					Eventually(session).Should(Say("FAILED"))
					Eventually(session).Should(Exit(1))
				})
			})
		})

		When("the stack does not exist", func() {
			It("Fails", func() {
				session := helpers.CF("stack", stackName)

				Eventually(session).Should(Say(`Getting stack %s in org %s / space %s as %s\.\.\.`, stackName, orgName, spaceName, username))
				Eventually(session.Err).Should(Say("Stack %s not found", stackName))
				Eventually(session).Should(Say("FAILED"))
				Eventually(session).Should(Exit(1))
			})
		})

		When("the stack exists", func() {
			BeforeEach(func() {
				stackName = "cflinuxfs3"
				stackDescription = regexp.QuoteMeta("Cloud Foundry Linux-based filesystem (Ubuntu 18.04)")
			})

			It("Shows the details for the stack", func() {
				session := helpers.CF("stack", "cflinuxfs3")

				Eventually(session).Should(Say(`Getting stack %s in org %s / space %s as %s\.\.\.`, stackName, orgName, spaceName, username))
				Eventually(session).Should(Say(`name:\s+%s`, stackName))
				Eventually(session).Should(Say(`description:\s+%s`, stackDescription))
				Eventually(session).Should(Exit(0))
			})

			When("the stack exists and the --guid flag is passed", func() {
				It("prints nothing but the guid", func() {
					session := helpers.CF("stack", stackName, "--guid")

					Consistently(session).ShouldNot(Say(`Getting stack %s in org %s / space %s as %s\.\.\.`, stackName, orgName, spaceName, username))
					Consistently(session).ShouldNot(Say(`name:\s+%s`, stackName))
					Consistently(session).ShouldNot(Say(`description:\s+%s`, stackDescription))
					Eventually(session).Should(Say(`^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}`))
					Eventually(session).Should(Exit(0))
				})
			})
		})
	})
})
<commit_msg>Revert "Fix integration tests so they dont leak stacks"<commit_after>package isolated

import (
	"code.cloudfoundry.org/cli/integration/helpers"
	"fmt"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/onsi/gomega/gbytes"
	. "github.com/onsi/gomega/gexec"
)

var _ = Describe("stack command", func() {
	var (
		orgName          string
		spaceName        string
		stackName        string
		stackDescription string
	)

	BeforeEach(func() {
		orgName = helpers.NewOrgName()
		spaceName = helpers.NewSpaceName()
		stackName = helpers.PrefixedRandomName("stack")
		stackDescription = "this is a test stack"
	})

	Describe("help", func() {
		When("--help flag is set", func() {
			It("Displays command usage to output", func() {
				session := helpers.CF("stack", "--help")

				Eventually(session).Should(Say(`NAME:`))
				Eventually(session).Should(Say(`stack - Show information for a stack \(a stack is a pre-built file system, including an operating system, that can run apps\)`))
				Eventually(session).Should(Say("USAGE:"))
				Eventually(session).Should(Say("cf stack STACK_NAME"))

				Eventually(session).Should(Exit(0))
			})
		})
	})

	When("the stack name is not provided", func() {
		It("tells the user that the stack name is required, prints help text, and exits 1", func() {
			session := helpers.CF("stack")

			Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `STACK_NAME` was not provided"))
			Eventually(session).Should(Say("NAME:"))
			Eventually(session).Should(Exit(1))
		})
	})

	When("the environment is not setup correctly", func() {
		It("fails with the appropriate errors", func() {
			helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "stack", stackName)
		})
	})

	When("the environment is set up correctly", func() {
		var username string

		BeforeEach(func() {
			helpers.SetupCF(orgName, spaceName)
			username, _ = helpers.GetCredentials()
		})

		AfterEach(func() {
			helpers.QuickDeleteOrg(orgName)
		})

		When("the input is invalid", func() {
			When("there are not enough arguments", func() {
				It("outputs the usage and exits 1", func() {
					session := helpers.CF("stack")

					Eventually(session.Err).Should(Say("Incorrect Usage:"))
					Eventually(session).Should(Say("NAME:"))
					Eventually(session).Should(Exit(1))
				})
			})

			When("there too many arguments", func() {
				It("ignores the extra arguments", func() {
					session := helpers.CF("stack", stackName, "extra")

					Eventually(session).Should(Say(`Getting stack %s in org %s / space %s as %s\.\.\.`, stackName, orgName, spaceName, username))
					Eventually(session.Err).Should(Say("Stack %s not found", stackName))
					Eventually(session).Should(Say("FAILED"))
					Eventually(session).Should(Exit(1))
				})
			})
		})

		When("the stack does not exist", func() {
			It("Fails", func() {
				session := helpers.CF("stack", stackName)

				Eventually(session).Should(Say(`Getting stack %s in org %s / space %s as %s\.\.\.`, stackName, orgName, spaceName, username))
				Eventually(session.Err).Should(Say("Stack %s not found", stackName))
				Eventually(session).Should(Say("FAILED"))
				Eventually(session).Should(Exit(1))
			})
		})

		When("the stack exists", func() {
			BeforeEach(func() {
				jsonBody := fmt.Sprintf(`{"name": "%s", "description": "%s"}`, stackName, stackDescription)
				session := helpers.CF("curl", "-d", jsonBody, "-X", "POST", "/v3/stacks")
				Eventually(session).Should(Exit(0))
			})
			It("Shows the details for the stack", func() {
				session := helpers.CF("stack", stackName)

				Eventually(session).Should(Say(`Getting stack %s in org %s / space %s as %s\.\.\.`, stackName, orgName, spaceName, username))
				Eventually(session).Should(Say(`name:\s+%s`, stackName))
				Eventually(session).Should(Say(`description:\s+%s`, stackDescription))
				Eventually(session).Should(Exit(0))
			})

			When("the stack exists and the --guid flag is passed", func() {
				It("prints nothing but the guid", func() {
					session := helpers.CF("stack", stackName, "--guid")

					Consistently(session).ShouldNot(Say(`Getting stack %s in org %s / space %s as %s\.\.\.`, stackName, orgName, spaceName, username))
					Consistently(session).ShouldNot(Say(`name:\s+%s`, stackName))
					Consistently(session).ShouldNot(Say(`description:\s+%s`, stackDescription))
					Eventually(session).Should(Say(`^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}`))
					Eventually(session).Should(Exit(0))
				})
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto"
	"crypto/x509"
	"fmt"
	"golang.org/x/crypto/ocsp"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
)

func getOCSPServer(cert *x509.Certificate) (string, error) {
	ocspServers := cert.OCSPServer
	if len(ocspServers) == 0 {
		return "", errNoOCSPServersFound
	}
	return ocspServers[0], nil
}

func getOCSPResponse(client HttpClient, cert *x509.Certificate, issuer *x509.Certificate) (*ocsp.Response, error) {
	ocspServer, err := getOCSPServer(cert)
	if err != nil {
		return nil, err
	}

	options := ocsp.RequestOptions{Hash: crypto.SHA1}
	request, err := ocsp.CreateRequest(cert, issuer, &options)
	if err != nil {
		return nil, err
	}

	url, err := url.Parse(ocspServer)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest("POST", ocspServer, bytes.NewBuffer(request))
	if err != nil {
		return nil, err
	}
	req.Host = url.Hostname()
	req.Header.Set("content-type", "application/ocsp-request")

	response, err := client.Do(req)
	if err != nil {
		return nil, errFailedToFetchOCSPResponse
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	parsedResponse, err := ocsp.ParseResponseForCert(body, cert, issuer)
	if err != nil {
		return nil, err
	}

	return parsedResponse, nil
}

func printStatusResponse(resp *ocsp.Response) {
	fmt.Fprintf(out, "Serial number: %s\n\n", resp.SerialNumber)
	fmt.Fprintf(out, "Status: %s\n", statusMessage(resp.Status))

	if resp.Status == ocsp.Revoked {
		fmt.Fprintf(out, "Reason: %s\n", revocationReason(resp.RevocationReason))
		fmt.Fprintf(out, "Revoked at: %s\n", resp.RevokedAt)
	}

	fmt.Fprintf(out, "\nProduced at: %s\n", resp.ProducedAt)
	fmt.Fprintf(out, "This update: %s\n", resp.ThisUpdate)
	fmt.Fprintf(out, "Next update: %s\n", resp.NextUpdate)
}

var (
	statusMessages = map[int]string{
		ocsp.Good:         "Good",
		ocsp.Revoked:      "Revoked",
		ocsp.ServerFailed: "Server failed",
		ocsp.Unknown:      "Unknown",
	}
	revocationReasonMessages = map[int]string{
		ocsp.Unspecified:          "Unspecified",
		ocsp.KeyCompromise:        "Key compromise",
		ocsp.CACompromise:         "CA compromise",
		ocsp.AffiliationChanged:   "Affiliation changed",
		ocsp.Superseded:           "Superseded",
		ocsp.CessationOfOperation: "Cessation of operation",
		ocsp.CertificateHold:      "Certificate hold",
		ocsp.RemoveFromCRL:        "Remove from CRL",
		ocsp.PrivilegeWithdrawn:   "Privilege withdrawn",
		ocsp.AACompromise:         "AA compromise",
	}
)

func statusMessage(code int) string {
	return statusMessages[code]
}

func revocationReason(code int) string {
	return revocationReasonMessages[code]
}
<commit_msg>Removed unused import.<commit_after>package main

import (
	"bytes"
	"crypto"
	"crypto/x509"
	"fmt"
	"golang.org/x/crypto/ocsp"
	"io/ioutil"
	"net/http"
	"net/url"
)

func getOCSPServer(cert *x509.Certificate) (string, error) {
	ocspServers := cert.OCSPServer
	if len(ocspServers) == 0 {
		return "", errNoOCSPServersFound
	}
	return ocspServers[0], nil
}

func getOCSPResponse(client HttpClient, cert *x509.Certificate, issuer *x509.Certificate) (*ocsp.Response, error) {
	ocspServer, err := getOCSPServer(cert)
	if err != nil {
		return nil, err
	}

	options := ocsp.RequestOptions{Hash: crypto.SHA1}
	request, err := ocsp.CreateRequest(cert, issuer, &options)
	if err != nil {
		return nil, err
	}

	url, err := url.Parse(ocspServer)
	if err != nil {
		return nil, err
	}

	req, err := http.NewRequest("POST", ocspServer, bytes.NewBuffer(request))
	if err != nil {
		return nil, err
	}
	req.Host = url.Hostname()
	req.Header.Set("content-type", "application/ocsp-request")

	response, err := client.Do(req)
	if err != nil {
		return nil, errFailedToFetchOCSPResponse
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	parsedResponse, err := ocsp.ParseResponseForCert(body, cert, issuer)
	if err != nil {
		return nil, err
	}

	return parsedResponse, nil
}

func printStatusResponse(resp *ocsp.Response) {
	fmt.Fprintf(out, "Serial number: %s\n\n", resp.SerialNumber)
	fmt.Fprintf(out, "Status: %s\n", statusMessage(resp.Status))

	if resp.Status == ocsp.Revoked {
		fmt.Fprintf(out, "Reason: %s\n", revocationReason(resp.RevocationReason))
		fmt.Fprintf(out, "Revoked at: %s\n", resp.RevokedAt)
	}

	fmt.Fprintf(out, "\nProduced at: %s\n", resp.ProducedAt)
	fmt.Fprintf(out, "This update: %s\n", resp.ThisUpdate)
	fmt.Fprintf(out, "Next update: %s\n", resp.NextUpdate)
}

var (
	statusMessages = map[int]string{
		ocsp.Good:         "Good",
		ocsp.Revoked:      "Revoked",
		ocsp.ServerFailed: "Server failed",
		ocsp.Unknown:      "Unknown",
	}
	revocationReasonMessages = map[int]string{
		ocsp.Unspecified:          "Unspecified",
		ocsp.KeyCompromise:        "Key compromise",
		ocsp.CACompromise:         "CA compromise",
		ocsp.AffiliationChanged:   "Affiliation changed",
		ocsp.Superseded:           "Superseded",
		ocsp.CessationOfOperation: "Cessation of operation",
		ocsp.CertificateHold:      "Certificate hold",
		ocsp.RemoveFromCRL:        "Remove from CRL",
		ocsp.PrivilegeWithdrawn:   "Privilege withdrawn",
		ocsp.AACompromise:         "AA compromise",
	}
)

func statusMessage(code int) string {
	return statusMessages[code]
}

func revocationReason(code int) string {
	return revocationReasonMessages[code]
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"
)

// Tree is an element in the tree.
type Tree struct {
	// Parent, left, and right pointers in the tree of elements.
	// The root of the tree has parent = nil
	parent, child, sibling *Tree
	Value Entry
}

type Entry struct {
	Id       int64     "The ID of the post"
	Title    string    "Title of the post. Will be empty for entries that are really intended to be comments."
	Body     string    "Contents of the post. Will be empty for entries that are intended to be links."
	Url      string    //Used if the post is just a link
	Created  time.Time "Time at which the post was created."
	AuthorId int64     "ID of the author of the post"
	Forum    bool      `schema:"-"` //Is this Entry actually a forum instead?

	//These are not stored in the DB and are just generated fields
	AuthorHandle string  //Name of the author
	Seconds      float64 //Seconds since creation
	Upvotes      int64
	Downvotes    int64
}

func (e Entry) Points() int64 {
	return e.Upvotes - e.Downvotes
}

func New(value Entry) *Tree {
	t := &Tree{Value: value}

	fmt.Printf("Created %p %v\n", t, t.Value.Title)

	return t
}

func (e *Tree) Child() *Tree { return e.child }

func (e *Tree) Sibling() *Tree { return e.sibling }

func (e *Tree) Parent() *Tree { return e.parent }

func (e *Tree) AddChild(newE *Tree) {
	//fmt.Printf("Adding %p %v as a child of %p %v\n", newE, newE.Value.Title, e, e.Value.Title)

	if e.child == nil {
		//Slot is available
		e.child, newE.parent = newE, e
	} else {
		//Slot is unavailable.
		//fmt.Printf("%p %v's child slot is full. Adding %p %v as a sibling of %p %v\n\n", e, e.Value.Title, newE, newE.Value.Title, e.child, e.child.Value.Title)
		e.child.addSibling(newE)
	}

	return
}

func (e *Tree) addSibling(newE *Tree) {
	if newE == nil {
		return
	}

	if newE.Value.Points() <= e.Value.Points() {
		// The new element belongs BELOW the old one
		//fmt.Printf("%p %v should be below %p %v\n\n", newE, newE.Value.Title, e, e.Value.Title)
		if e.sibling == nil {
			// The old element has no sibling so insertion below it is trivial
			newE.parent, e.sibling = e, newE

			return
		} else {
			// The old element already has a sibling
			// Try to add the new element as a sibling of the sibling
			e.sibling.addSibling(newE)

			return
		}
	} else {
		// The new element belongs ABOVE the old one
		//fmt.Printf("%p %v should be above %p %v\n\n", newE, newE.Value.Title, e, e.Value.Title)

		// New element may or may not have a sibling, but we will pop it off and then add it back
		// at the end to cover our bases in case it does
		newESib := newE.sibling

		/*
		fmt.Printf("e: %p %v\n", e, e)
		fmt.Printf("newE: %p %v\n", newE, newE)
		fmt.Printf("e.Parent: %p %v\n", e.parent, e.parent)
		fmt.Printf("newE.sibling %p %v\n", newE.sibling, newE.sibling)
		fmt.Printf("newE.parent %p %v\n", newE.parent, newE.parent)
		*/

		if e == e.parent.child {
			// Old element was a child of its parent
			//fmt.Printf("e (%p) was a child of its parent (%p). Now newE (%p) %v will interpose.\n", e, e.parent, newE, newE.Value.Title)

			e.parent.child, newE.parent, newE.sibling, e.parent = newE, e.parent, e, newE
		} else {
			// Old element was presumptively a sibling of its parent
			//fmt.Printf("e (%p) %v was a sib of its parent (%p) %v. Now newE (%p) %v will interpose.\n", e, e.Value.Title, e.parent, e.parent.Value.Title, newE, newE.Value.Title)

			e.parent.sibling, newE.parent, newE.sibling, e.parent = newE, e.parent, e, newE
		}

		newE.addSibling(newESib)

		return
	}
}

func (e *Tree) Walk() {
	if e == nil {
		return
	}

	if e.parent == nil {
		fmt.Printf("\n\nWalking...\n(Root) ")
	}
	fmt.Printf("%p: %+v\n", e, e)
	e.Child().Walk()
	e.Sibling().Walk()
}

func main () {
	t := New(Entry{Title: "Root", Upvotes: 10})
	t.AddChild(New(Entry{Title: "Depth 1 #3", Upvotes: 1}))
	//t.AddChild(New(Entry{Title: "Level 2 #2", Upvotes: 0}))
	//t.AddChild(New(Entry{Title: "Level 2 #3", Upvotes: 1}))

	t2 := New(Entry{Title: "Depth 1 #2", Upvotes: 2})
	t2.AddChild(New(Entry{Title: "Depth 2 #2", Upvotes: 2}))
	t2.AddChild(New(Entry{Title: "Depth 2 #1", Upvotes: 3}))
	//t2.sibling, t2.child  = t2.child, nil
	//t2.sibling.parent = t2

	t.AddChild(t2)

	t.AddChild(New(Entry{Title: "Depth 1 #1", Upvotes: 3}))

	t.Walk()
}
<commit_msg>Removed most commented-out code<commit_after>package main

import (
	"fmt"
	"time"
)

// Tree is an element in the tree.
type Tree struct {
	// Parent, left, and right pointers in the tree of elements.
	// The root of the tree has parent = nil
	parent, child, sibling *Tree
	Value Entry
}

type Entry struct {
	Id       int64     "The ID of the post"
	Title    string    "Title of the post. Will be empty for entries that are really intended to be comments."
	Body     string    "Contents of the post. Will be empty for entries that are intended to be links."
	Url      string    //Used if the post is just a link
	Created  time.Time "Time at which the post was created."
	AuthorId int64     "ID of the author of the post"
	Forum    bool      `schema:"-"` //Is this Entry actually a forum instead?

	//These are not stored in the DB and are just generated fields
	AuthorHandle string  //Name of the author
	Seconds      float64 //Seconds since creation
	Upvotes      int64
	Downvotes    int64
}

func (e Entry) Points() int64 {
	return e.Upvotes - e.Downvotes
}

func New(value Entry) *Tree {
	t := &Tree{Value: value}

	fmt.Printf("Created %p %v\n", t, t.Value.Title)

	return t
}

func (e *Tree) Child() *Tree { return e.child }

func (e *Tree) Sibling() *Tree { return e.sibling }

func (e *Tree) Parent() *Tree { return e.parent }

func (e *Tree) AddChild(newE *Tree) {
	if e.child == nil {
		//Slot is available, directly add the child
		e.child, newE.parent = newE, e
	} else {
		//Slot is unavailable, figure out where the child belongs among peer siblings
		e.child.addSibling(newE)
	}

	return
}

func (e *Tree) addSibling(newE *Tree) {
	if newE == nil {
		return
	}

	if newE.Value.Points() <= e.Value.Points() {
		// The new element belongs BELOW the old one
		if e.sibling == nil {
			// The old element has no sibling so insertion below it is trivial
			newE.parent, e.sibling = e, newE

			return
		} else {
			// The old element already has a sibling
			// Try to add the new element as a sibling of the sibling
			e.sibling.addSibling(newE)

			return
		}
	} else {
		// The new element belongs ABOVE the old one

		// New element may or may not have a sibling, but we will pop it off and then add it back
		// at the end to cover our bases in case it does
		newESib := newE.sibling

		if e == e.parent.child {
			// Old element was a child of its parent
			e.parent.child, newE.parent, newE.sibling, e.parent = newE, e.parent, e, newE
		} else {
			// Old element was presumptively a sibling of its parent
			e.parent.sibling, newE.parent, newE.sibling, e.parent = newE, e.parent, e, newE
		}

		// Add back sibling of new element (if any)
		newE.addSibling(newESib)

		return
	}
}

func (e *Tree) Walk() {
	if e == nil {
		return
	}

	if e.parent == nil {
		fmt.Printf("\n\nWalking...\n(Root) ")
	}
	fmt.Printf("%p: %+v\n", e, e)
	e.Child().Walk()
	e.Sibling().Walk()
}

func main () {
	t := New(Entry{Title: "Root", Upvotes: 10})
	t.AddChild(New(Entry{Title: "Depth 1 #4", Upvotes: 0}))
	t.AddChild(New(Entry{Title: "Depth 1 #3", Upvotes: 1}))

	t2 := New(Entry{Title: "Depth 1 #2", Upvotes: 2})
	t2.AddChild(New(Entry{Title: "Depth 2 #2", Upvotes: 2}))
	t2.AddChild(New(Entry{Title: "Depth 2 #1", Upvotes: 3}))
	//t2.sibling, t2.child  = t2.child, nil
	//t2.sibling.parent = t2

	t.AddChild(t2)

	t.AddChild(New(Entry{Title: "Depth 1 #1", Upvotes: 3}))

	t.Walk()
}
<|endoftext|>


<commit_before>// Implementation of an R-Way Trie data structure.
//
// A Trie has a root Node which is the base of the tree.
// Each subsequent Node has a letter and children, which are
// nodes that have letter values associated with them.
package trie

import "sort"

type Node struct {
	val      rune
	term     bool
	depth    int
	meta     interface{}
	mask     uint64
	parent   *Node
	children map[rune]*Node
}

type Trie struct {
	root *Node
	size int
}

type ByKeys []string

func (a ByKeys) Len() int           { return len(a) }
func (a ByKeys) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByKeys) Less(i, j int) bool { return len(a[i]) < len(a[j]) }

const nul = 0x0

// Creates a new Trie with an initialized root Node.
func New() *Trie {
	return &Trie{
		root: &Node{children: make(map[rune]*Node), depth: 0},
		size: 0,
	}
}

// Returns the root node for the Trie.
func (t *Trie) Root() *Node {
	return t.root
}

// Adds the key to the Trie, including meta data. Meta data
// is stored as `interface{}` and must be type cast by
// the caller.
func (t *Trie) Add(key string, meta interface{}) *Node {
	t.size++
	runes := []rune(key)
	bitmask := maskruneslice(runes)
	node := t.root
	node.mask |= bitmask
	for i := range runes {
		r := runes[i]
		bitmask = maskruneslice(runes[i:])
		if n, ok := node.children[r]; ok {
			node = n
			node.mask |= bitmask
		} else {
			node = node.NewChild(r, bitmask, nil, false)
		}
	}
	node = node.NewChild(nul, 0, meta, true)
	return node
}

// Finds and returns meta data associated
// with `key`.
func (t *Trie) Find(key string) (*Node, bool) {
	node := findNode(t.Root(), []rune(key))
	if node == nil {
		return nil, false
	}

	node, ok := node.Children()[nul]
	if !ok || !node.term {
		return nil, false
	}

	return node, true
}

func (t *Trie) HasKeysWithPrefix(key string) bool {
	node := findNode(t.Root(), []rune(key))
	return node != nil
}

// Removes a key from the trie, ensuring that
// all bitmasks up to root are appropriately recalculated.
func (t *Trie) Remove(key string) {
	var (
		i    int
		rs   = []rune(key)
		node = findNode(t.Root(), []rune(key))
	)

	t.size--
	for n := node.Parent(); n != nil; n = n.Parent() {
		i++
		if len(n.Children()) > 1 {
			r := rs[len(rs)-i]
			n.RemoveChild(r)
			break
		}
	}
}

// Returns all the keys currently stored in the trie.
func (t *Trie) Keys() []string {
	return t.PrefixSearch("")
}

// Performs a fuzzy search against the keys in the trie.
func (t Trie) FuzzySearch(pre string) []string {
	keys := fuzzycollect(t.Root(), []rune(pre))
	sort.Sort(ByKeys(keys))
	return keys
}

// Performs a prefix search against the keys in the trie.
func (t Trie) PrefixSearch(pre string) []string {
	node := findNode(t.Root(), []rune(pre))
	if node == nil {
		return nil
	}

	return collect(node)
}

// Creates and returns a pointer to a new child for the node.
func (n *Node) NewChild(val rune, bitmask uint64, meta interface{}, term bool) *Node {
	node := &Node{
		val:      val,
		mask:     bitmask,
		term:     term,
		meta:     meta,
		parent:   n,
		children: make(map[rune]*Node),
		depth:    n.depth + 1,
	}
	n.children[val] = node
	n.mask |= bitmask
	return node
}

func (n *Node) RemoveChild(r rune) {
	delete(n.children, r)
	for nd := n.parent; nd != nil; nd = nd.parent {
		nd.mask ^= nd.mask
		nd.mask |= uint64(1) << uint64(nd.val-'a')
		for _, c := range nd.children {
			nd.mask |= c.mask
		}
	}
}

// Returns the parent of this node.
func (n Node) Parent() *Node {
	return n.parent
}

// Returns the meta information of this node.
func (n Node) Meta() interface{} {
	return n.meta
}

// Returns the children of this node.
func (n Node) Children() map[rune]*Node {
	return n.children
}

func (n Node) Terminating() bool {
	return n.term
}

func (n Node) Val() rune {
	return n.val
}

func (n Node) Depth() int {
	return n.depth
}

// Returns a uint64 representing the current
// mask of this node.
func (n Node) Mask() uint64 {
	return n.mask
}

func findNode(node *Node, runes []rune) *Node {
	if node == nil {
		return nil
	}

	if len(runes) == 0 {
		return node
	}

	n, ok := node.Children()[runes[0]]
	if !ok {
		return nil
	}

	var nrunes []rune
	if len(runes) > 1 {
		nrunes = runes[1:]
	} else {
		nrunes = runes[0:0]
	}

	return findNode(n, nrunes)
}

func maskruneslice(rs []rune) uint64 {
	var m uint64
	for _, r := range rs {
		m |= uint64(1) << uint64(r-'a')
	}
	return m
}

func collect(node *Node) []string {
	var (
		keys []string
		n    *Node
		i    int
	)
	nodes := []*Node{node}
	for l := len(nodes); l != 0; l = len(nodes) {
		i = l - 1
		n = nodes[i]
		nodes = nodes[:i]
		for _, c := range n.children {
			nodes = append(nodes, c)
		}
		if n.term {
			word := ""
			for p := n.parent; p.depth != 0; p = p.parent {
				word = string(p.val) + word
			}
			keys = append(keys, word)
		}
	}
	return keys
}

type potentialSubtree struct {
	idx  int
	node *Node
}

func fuzzycollect(node *Node, partial []rune) []string {
	var (
		m    uint64
		i    int
		p    potentialSubtree
		keys []string
	)

	potential := []potentialSubtree{potentialSubtree{node: node, idx: 0}}
	for l := len(potential); l > 0; l = len(potential) {
		i = l - 1
		p = potential[i]
		potential = potential[:i]
		m = maskruneslice(partial[p.idx:])
		if (p.node.mask & m) != m {
			continue
		}

		if p.node.val == partial[p.idx] {
			p.idx++
			if p.idx == len(partial) {
				keys = append(keys, collect(p.node)...)
				continue
			}
		}

		for _, c := range p.node.children {
			potential = append(potential, potentialSubtree{node: c, idx: p.idx})
		}
	}
	return keys
}
<commit_msg>Add sync.Mutex to allow concurrent operations<commit_after>// Implementation of an R-Way Trie data structure.
//
// A Trie has a root Node which is the base of the tree.
// Each subsequent Node has a letter and children, which are
// nodes that have letter values associated with them.
package trie

import (
	"sort"
	"sync"
)

type Node struct {
	val      rune
	term     bool
	depth    int
	meta     interface{}
	mask     uint64
	parent   *Node
	children map[rune]*Node
}

type Trie struct {
	mu   sync.Mutex
	root *Node
	size int
}

type ByKeys []string

func (a ByKeys) Len() int           { return len(a) }
func (a ByKeys) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByKeys) Less(i, j int) bool { return len(a[i]) < len(a[j]) }

const nul = 0x0

// Creates a new Trie with an initialized root Node.
func New() *Trie {
	return &Trie{
		root: &Node{children: make(map[rune]*Node), depth: 0},
		size: 0,
	}
}

// Returns the root node for the Trie.
func (t *Trie) Root() *Node {
	return t.root
}

// Adds the key to the Trie, including meta data. Meta data
// is stored as `interface{}` and must be type cast by
// the caller.
func (t *Trie) Add(key string, meta interface{}) *Node {
	t.mu.Lock()
	defer t.mu.Unlock()

	t.size++
	runes := []rune(key)
	bitmask := maskruneslice(runes)
	node := t.root
	node.mask |= bitmask
	for i := range runes {
		r := runes[i]
		bitmask = maskruneslice(runes[i:])
		if n, ok := node.children[r]; ok {
			node = n
			node.mask |= bitmask
		} else {
			node = node.NewChild(r, bitmask, nil, false)
		}
	}
	node = node.NewChild(nul, 0, meta, true)
	return node
}

// Finds and returns meta data associated
// with `key`.
func (t *Trie) Find(key string) (*Node, bool) {
	node := findNode(t.Root(), []rune(key))
	if node == nil {
		return nil, false
	}

	node, ok := node.Children()[nul]
	if !ok || !node.term {
		return nil, false
	}

	return node, true
}

func (t *Trie) HasKeysWithPrefix(key string) bool {
	node := findNode(t.Root(), []rune(key))
	return node != nil
}

// Removes a key from the trie, ensuring that
// all bitmasks up to root are appropriately recalculated.
func (t *Trie) Remove(key string) {
	var (
		i    int
		rs   = []rune(key)
		node = findNode(t.Root(), []rune(key))
	)

	t.mu.Lock()
	defer t.mu.Unlock()

	t.size--
	for n := node.Parent(); n != nil; n = n.Parent() {
		i++
		if len(n.Children()) > 1 {
			r := rs[len(rs)-i]
			n.RemoveChild(r)
			break
		}
	}
}

// Returns all the keys currently stored in the trie.
func (t *Trie) Keys() []string {
	return t.PrefixSearch("")
}

// Performs a fuzzy search against the keys in the trie.
func (t Trie) FuzzySearch(pre string) []string {
	keys := fuzzycollect(t.Root(), []rune(pre))
	sort.Sort(ByKeys(keys))
	return keys
}

// Performs a prefix search against the keys in the trie.
func (t Trie) PrefixSearch(pre string) []string {
	node := findNode(t.Root(), []rune(pre))
	if node == nil {
		return nil
	}

	return collect(node)
}

// Creates and returns a pointer to a new child for the node.
func (n *Node) NewChild(val rune, bitmask uint64, meta interface{}, term bool) *Node {
	node := &Node{
		val:      val,
		mask:     bitmask,
		term:     term,
		meta:     meta,
		parent:   n,
		children: make(map[rune]*Node),
		depth:    n.depth + 1,
	}
	n.children[val] = node
	n.mask |= bitmask
	return node
}

func (n *Node) RemoveChild(r rune) {
	delete(n.children, r)
	for nd := n.parent; nd != nil; nd = nd.parent {
		nd.mask ^= nd.mask
		nd.mask |= uint64(1) << uint64(nd.val-'a')
		for _, c := range nd.children {
			nd.mask |= c.mask
		}
	}
}

// Returns the parent of this node.
func (n Node) Parent() *Node {
	return n.parent
}

// Returns the meta information of this node.
func (n Node) Meta() interface{} {
	return n.meta
}

// Returns the children of this node.
func (n Node) Children() map[rune]*Node {
	return n.children
}

func (n Node) Terminating() bool {
	return n.term
}

func (n Node) Val() rune {
	return n.val
}

func (n Node) Depth() int {
	return n.depth
}

// Returns a uint64 representing the current
// mask of this node.
func (n Node) Mask() uint64 {
	return n.mask
}

func findNode(node *Node, runes []rune) *Node {
	if node == nil {
		return nil
	}

	if len(runes) == 0 {
		return node
	}

	n, ok := node.Children()[runes[0]]
	if !ok {
		return nil
	}

	var nrunes []rune
	if len(runes) > 1 {
		nrunes = runes[1:]
	} else {
		nrunes = runes[0:0]
	}

	return findNode(n, nrunes)
}

func maskruneslice(rs []rune) uint64 {
	var m uint64
	for _, r := range rs {
		m |= uint64(1) << uint64(r-'a')
	}
	return m
}

func collect(node *Node) []string {
	var (
		keys []string
		n    *Node
		i    int
	)
	nodes := []*Node{node}
	for l := len(nodes); l != 0; l = len(nodes) {
		i = l - 1
		n = nodes[i]
		nodes = nodes[:i]
		for _, c := range n.children {
			nodes = append(nodes, c)
		}
		if n.term {
			word := ""
			for p := n.parent; p.depth != 0; p = p.parent {
				word = string(p.val) + word
			}
			keys = append(keys, word)
		}
	}
	return keys
}

type potentialSubtree struct {
	idx  int
	node *Node
}

func fuzzycollect(node *Node, partial []rune) []string {
	var (
		m    uint64
		i    int
		p    potentialSubtree
		keys []string
	)

	potential := []potentialSubtree{potentialSubtree{node: node, idx: 0}}
	for l := len(potential); l > 0; l = len(potential) {
		i = l - 1
		p = potential[i]
		potential = potential[:i]
		m = maskruneslice(partial[p.idx:])
		if (p.node.mask & m) != m {
			continue
		}

		if p.node.val == partial[p.idx] {
			p.idx++
			if p.idx == len(partial) {
				keys = append(keys, collect(p.node)...)
				continue
			}
		}

		for _, c := range p.node.children {
			potential = append(potential, potentialSubtree{node: c, idx: p.idx})
		}
	}
	return keys
}
<|endoftext|>


<commit_before>package tros

import (
	"fmt"
	"reflect"
	"sort"
)

/*
func main() {
	in := []struct {
		A, B string
	}{{"a", "c"}, {"b", "b"}, {"c", "a"}}
	Sort(in, "A")
	fmt.Println(in)

	Sort(in, "B")
	fmt.Println(in)
}*/

// Sort sorts a slice of structs based on the values of the structs' fields with the given field name fn
func Sort(i interface{}, fn string) error {
	sval := reflect.ValueOf(i)
	if sval.Kind() != reflect.Slice {
		return fmt.Errorf("non-slice interface, got %q", sval.Kind())
	}
	s := sortable{sval, fn, sval.Len(), nil}
	sort.Sort(sort.Interface(s))
	return s.err
}

type sortable struct {
	sval reflect.Value
	fn   string
	len  int
	err  error
}

func (s sortable) Len() int { return s.len }

func (s sortable) Swap(i, j int) {
	if s.err != nil {
		return
	}
	a, b := s.sval.Index(i), s.sval.Index(j)
	tmp := reflect.New(a.Type()).Elem()
	tmp.Set(a)
	a.Set(b)
	b.Set(tmp)
}

func (s sortable) Less(i, j int) bool {
	a, b := s.sval.Index(i), s.sval.Index(j)
	af, bf := a.FieldByName(s.fn), b.FieldByName(s.fn)
	afk, bfk := af.Kind(), bf.Kind()
	if afk != bfk {
		s.err = fmt.Errorf("unmatched kinds, %q vs %q", afk, bfk)
		return false
	}
	switch afk {
	case reflect.Bool:
		return !af.Bool() && bf.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return af.Int() < bf.Int()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return af.Uint() < bf.Uint()
	case reflect.Float32, reflect.Float64:
		return af.Float() < bf.Float()
	case reflect.String:
		return af.String() < bf.String()
	default:
		s.err = fmt.Errorf("unsupported kind %q", afk)
		return false
	}
}
<commit_msg>remove commented out main<commit_after>package tros

import (
	"fmt"
	"reflect"
	"sort"
)

// Sort sorts a slice of structs based on the values of the structs' fields with the given field name fn
func Sort(i interface{}, fn string) error {
	sval := reflect.ValueOf(i)
	if sval.Kind() != reflect.Slice {
		return fmt.Errorf("non-slice interface, got %q", sval.Kind())
	}
	s := sortable{sval, fn, sval.Len(), nil}
	sort.Sort(sort.Interface(s))
	return s.err
}

type sortable struct {
	sval reflect.Value
	fn   string
	len  int
	err  error
}

func (s sortable) Len() int { return s.len }

func (s sortable) Swap(i, j int) {
	if s.err != nil {
		return
	}
	a, b := s.sval.Index(i), s.sval.Index(j)
	tmp := reflect.New(a.Type()).Elem()
	tmp.Set(a)
	a.Set(b)
	b.Set(tmp)
}

func (s sortable) Less(i, j int) bool {
	a, b := s.sval.Index(i), s.sval.Index(j)
	af, bf := a.FieldByName(s.fn), b.FieldByName(s.fn)
	afk, bfk := af.Kind(), bf.Kind()
	if afk != bfk {
		s.err = fmt.Errorf("unmatched kinds, %q vs %q", afk, bfk)
		return false
	}
	switch afk {
	case reflect.Bool:
		return !af.Bool() && bf.Bool()
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return af.Int() < bf.Int()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		return af.Uint() < bf.Uint()
	case reflect.Float32, reflect.Float64:
		return af.Float() < bf.Float()
	case reflect.String:
		return af.String() < bf.String()
	default:
		s.err = fmt.Errorf("unsupported kind %q", afk)
		return false
	}
}
<|endoftext|>


<commit_before>/**
 * report.go - provides basic reporting features for stnparse output.
 * @author R. S. Doiel, <rsdoiel@gmail.com>
 * copyright (c) 2015 all rights reserved.
 * Released under the BSD 2-Clause license
 * See: http://opensource.org/licenses/BSD-2-Clause
 */

// Package report provides basic report rendering for Simple Timesheet Notation.
package report

import (
	"../../stn"
	"fmt"
	"strings"
)

// EntryAggregation
type EntryAggregation struct {
	Entries []stn.Entry
}

// Aggregate - add an entry to the EntryAggregate
func (a *EntryAggregation) Aggregate(entry *stn.Entry) bool {
	i := len(a.Entries)
	a.Entries = append(a.Entries, *entry)
	if len(a.Entries) == (i + 1) {
		return true
	}
	return false
}

// Summarize - give the output of stnparse or stnfilter aggregate the results
// by the first notation and the durration of time.
func (e *EntryAggregation) Summarize() string {
	var outText []string

	summary := make(map[string]float64)
	for _, item := range e.Entries {
		// Calc duration
		duration := item.End.Sub(item.Start)
		// Calc key
		key := item.Annotations[0]
		// if map entry does not exist create one with key and duration
		// else add the new duration to old and update map
		val, ok := summary[key]
		if ok == true {
			summary[key] = val + duration.Hours()
		} else {
			summary[key] = duration.Hours()
		}
	}
	outText = append(outText, "Hours\tProject")
	for k, v := range summary {
		outText = append(outText, fmt.Sprintf("%5.2f\t%s", v, k))
	}
	return strings.Join(outText, "\n")
}
<commit_msg>added total in reporting<commit_after>/**
 * report.go - provides basic reporting features for stnparse output.
 * @author R. S. Doiel, <rsdoiel@gmail.com>
 * copyright (c) 2015 all rights reserved.
 * Released under the BSD 2-Clause license
 * See: http://opensource.org/licenses/BSD-2-Clause
 */

// Package report provides basic report rendering for Simple Timesheet Notation.
package report

import (
	"../../stn"
	"fmt"
	"strings"
)

// EntryAggregation
type EntryAggregation struct {
	Entries []stn.Entry
}

// Aggregate - add an entry to the EntryAggregate
func (a *EntryAggregation) Aggregate(entry *stn.Entry) bool {
	i := len(a.Entries)
	a.Entries = append(a.Entries, *entry)
	if len(a.Entries) == (i + 1) {
		return true
	}
	return false
}

// Summarize - give the output of stnparse or stnfilter aggregate the results
// by the first notation and the durration of time.
func (e *EntryAggregation) Summarize() string {
	var outText []string

	summary := make(map[string]float64)
	for _, item := range e.Entries {
		// Calc duration
		duration := item.End.Sub(item.Start)
		// Calc key
		key := item.Annotations[0]
		// if map entry does not exist create one with key and duration
		// else add the new duration to old and update map
		val, ok := summary[key]
		if ok == true {
			summary[key] = val + duration.Hours()
		} else {
			summary[key] = duration.Hours()
		}
	}
	outText = append(outText, "Hours\tProject")
	total := 0.0
	for k, v := range summary {
		total += v
		outText = append(outText, fmt.Sprintf("%5.2f\t%s", v, k))
	}
	outText = append(outText, "")
	outText = append(outText, fmt.Sprintf("%5.2f\tTotal Hours", total))
	outText = append(outText, "")
	return strings.Join(outText, "\n")
}
<|endoftext|>


<commit_before>// Package turn implements RFC 5766 Traversal Using Relays around NAT.
package turn

import (
	"encoding/binary"
	"fmt"

	"github.com/ernado/stun"
)

// bin is shorthand for binary.BigEndian.
var bin = binary.BigEndian

// BadAttrLength means that length for attribute is invalid.
type BadAttrLength struct {
	Attr     stun.AttrType
	Got      int
	Expected int
}

func (e BadAttrLength) Error() string {
	return fmt.Sprintf("incorrect length for %s: got %d, expected %d",
		e.Attr,
		e.Got,
		e.Expected,
	)
}
<commit_msg>turn: add DefaultTLSPort<commit_after>// Package turn implements RFC 5766 Traversal Using Relays around NAT.
package turn

import (
	"encoding/binary"
	"fmt"

	"github.com/ernado/stun"
)

// bin is shorthand for binary.BigEndian.
var bin = binary.BigEndian

// BadAttrLength means that length for attribute is invalid.
type BadAttrLength struct {
	Attr     stun.AttrType
	Got      int
	Expected int
}

func (e BadAttrLength) Error() string {
	return fmt.Sprintf("incorrect length for %s: got %d, expected %d",
		e.Attr,
		e.Got,
		e.Expected,
	)
}

// Default ports for TURN from RFC 5766 Section 4.
const (
	// DefaultPort for TURN is same as STUN.
	DefaultPort = stun.DefaultPort
	// DefaultTLSPort is for TURN over TLS.
	DefaultTLSPort = 5349
)
<|endoftext|>


<commit_before>package git

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/polydawn/gosh"
	. "github.com/smartystreets/goconvey/convey"

	"go.polydawn.net/repeatr/lib/testutil"
	"go.polydawn.net/repeatr/rio"
)

//func TestCoreCompliance(t *testing.T) {
//	Convey("Spec Compliance: Git Transmat", t, testutil.WithTmpdir(func() {
//		// Nope.
//		// Most of the core compliance tests require round-trip;
//		// we can't satisfy any of those because we don't (yet) support scan with git.
//	}))
//}

func TestGitLocalFileInputCompat(t *testing.T) {
	// note that this test eschews use of regular file fixtures for a few reasons:
	//  - because it's capable of working without root if it doesn't try to chown
	//  - because we're doing custom content anyway so we have multiple commits
	//  both of these could be addressed with upgrades to filefixtures in the future.
	Convey("Given a local git repo", t, testutil.Requires(
		testutil.WithTmpdir(func(c C) {
			git := git.Bake(gosh.Opts{Env: map[string]string{
				"GIT_AUTHOR_NAME":     "repeatr",
				"GIT_AUTHOR_EMAIL":    "repeatr",
				"GIT_COMMITTER_NAME":  "repeatr",
				"GIT_COMMITTER_EMAIL": "repeatr",
			}})
			var dataHash_1 rio.CommitID
			var dataHash_2 rio.CommitID
			var dataHash_3 rio.CommitID
			git.Bake("init", "--", "repo-a").RunAndReport()
			testutil.UsingDir("repo-a", func() {
				git.Bake("commit", "--allow-empty", "-m", "testrepo-a initial commit").RunAndReport()
				dataHash_1 = rio.CommitID(strings.Trim(git.Bake("rev-parse", "HEAD").Output(), "\n"))
				ioutil.WriteFile("file-a", []byte("abcd"), 0644)
				git.Bake("add", ".").RunAndReport()
				git.Bake("commit", "-m", "testrepo-a commit 1").RunAndReport()
				dataHash_2 = rio.CommitID(strings.Trim(git.Bake("rev-parse", "HEAD").Output(), "\n"))
				ioutil.WriteFile("file-e", []byte("efghi"), 0644)
				git.Bake("add", ".").RunAndReport()
				git.Bake("commit", "-m", "testrepo-a commit 2").RunAndReport()
				dataHash_3 = rio.CommitID(strings.Trim(git.Bake("rev-parse", "HEAD").Output(), "\n"))
			})

			transmat := New("./workdir")

			Convey("Materialization should be able to produce the latest commit", FailureContinues, func() {
				uris := []rio.SiloURI{rio.SiloURI("./repo-a")}
				// materialize from the ID returned by foreign git
				arena := transmat.Materialize(Kind, dataHash_3, uris, testutil.TestLogger(c), rio.AcceptHashMismatch)
				// assert hash match
				// (normally survival would attest this, but we used the `AcceptHashMismatch` to supress panics in the name of letting the test see more after failures.)
				So(arena.Hash(), ShouldEqual, dataHash_3)
				// check filesystem to loosely match the original fixture
				So(filepath.Join(arena.Path(), "file-a"), testutil.ShouldBeFile)
				So(filepath.Join(arena.Path(), "file-e"), testutil.ShouldBeFile)
				So(filepath.Join(arena.Path(), ".git"), testutil.ShouldBeNotFile)
			})

			Convey("Materialization should be able to produce older commits", FailureContinues, func() {
				uris := []rio.SiloURI{rio.SiloURI("./repo-a")}
				// materialize from the ID returned by foreign git
				arena := transmat.Materialize(Kind, dataHash_2, uris, testutil.TestLogger(c), rio.AcceptHashMismatch)
				// assert hash match
				// (normally survival would attest this, but we used the `AcceptHashMismatch` to supress panics in the name of letting the test see more after failures.)
				So(arena.Hash(), ShouldEqual, dataHash_2)
				// check filesystem to loosely match the original fixture
				So(filepath.Join(arena.Path(), "file-a"), testutil.ShouldBeFile)
				So(filepath.Join(arena.Path(), "file-e"), testutil.ShouldBeNotFile)
				So(filepath.Join(arena.Path(), ".git"), testutil.ShouldBeNotFile)
			})

			Convey("Materialization should work, even when cwd is inside the repo", FailureContinues, func() {
				So(os.Mkdir("repo-a/meta", 0755), ShouldBeNil)
				testutil.UsingDir("repo-a/meta", func() {
					uris := []rio.SiloURI{rio.SiloURI("./..")}
					// materialize from the ID returned by foreign git
					arena := transmat.Materialize(Kind, dataHash_3, uris, testutil.TestLogger(c), rio.AcceptHashMismatch)
					// assert hash match
					// (normally survival would attest this, but we used the `AcceptHashMismatch` to supress panics in the name of letting the test see more after failures.)
					So(arena.Hash(), ShouldEqual, dataHash_3)
					// check filesystem to loosely match the original fixture
					So(filepath.Join(arena.Path(), "file-a"), testutil.ShouldBeFile)
					So(filepath.Join(arena.Path(), "file-e"), testutil.ShouldBeFile)
					So(filepath.Join(arena.Path(), ".git"), testutil.ShouldBeNotFile)
				})
			})
		})),
	)

	// TODO you really should do this with a fixture loop
	// but that does also leave questions about multi-commits, branches, etc.
	// so do both i guess.
	//filefixture.Beta.Create("repo-a")
}
<commit_msg>Fix a test requirement; 'goad test' now correct without privs.<commit_after>package git

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/polydawn/gosh"
	. "github.com/smartystreets/goconvey/convey"

	"go.polydawn.net/repeatr/lib/testutil"
	"go.polydawn.net/repeatr/rio"
)

//func TestCoreCompliance(t *testing.T) {
//	Convey("Spec Compliance: Git Transmat", t, testutil.WithTmpdir(func() {
//		// Nope.
//		// Most of the core compliance tests require round-trip;
//		// we can't satisfy any of those because we don't (yet) support scan with git.
//	}))
//}

func TestGitLocalFileInputCompat(t *testing.T) {
	// note that this test eschews use of regular file fixtures for a few reasons:
	//  - because it's capable of working without root if it doesn't try to chown
	//  - because we're doing custom content anyway so we have multiple commits
	//  both of these could be addressed with upgrades to filefixtures in the future.
	Convey("Given a local git repo", t, testutil.Requires(
		testutil.RequiresRoot,
		testutil.WithTmpdir(func(c C) {
			git := git.Bake(gosh.Opts{Env: map[string]string{
				"GIT_AUTHOR_NAME":     "repeatr",
				"GIT_AUTHOR_EMAIL":    "repeatr",
				"GIT_COMMITTER_NAME":  "repeatr",
				"GIT_COMMITTER_EMAIL": "repeatr",
			}})
			var dataHash_1 rio.CommitID
			var dataHash_2 rio.CommitID
			var dataHash_3 rio.CommitID
			git.Bake("init", "--", "repo-a").RunAndReport()
			testutil.UsingDir("repo-a", func() {
				git.Bake("commit", "--allow-empty", "-m", "testrepo-a initial commit").RunAndReport()
				dataHash_1 = rio.CommitID(strings.Trim(git.Bake("rev-parse", "HEAD").Output(), "\n"))
				ioutil.WriteFile("file-a", []byte("abcd"), 0644)
				git.Bake("add", ".").RunAndReport()
				git.Bake("commit", "-m", "testrepo-a commit 1").RunAndReport()
				dataHash_2 = rio.CommitID(strings.Trim(git.Bake("rev-parse", "HEAD").Output(), "\n"))
				ioutil.WriteFile("file-e", []byte("efghi"), 0644)
				git.Bake("add", ".").RunAndReport()
				git.Bake("commit", "-m", "testrepo-a commit 2").RunAndReport()
				dataHash_3 = rio.CommitID(strings.Trim(git.Bake("rev-parse", "HEAD").Output(), "\n"))
			})

			transmat := New("./workdir")

			Convey("Materialization should be able to produce the latest commit", FailureContinues, func() {
				uris := []rio.SiloURI{rio.SiloURI("./repo-a")}
				// materialize from the ID returned by foreign git
				arena := transmat.Materialize(Kind, dataHash_3, uris, testutil.TestLogger(c), rio.AcceptHashMismatch)
				// assert hash match
				// (normally survival would attest this, but we used the `AcceptHashMismatch` to supress panics in the name of letting the test see more after failures.)
				So(arena.Hash(), ShouldEqual, dataHash_3)
				// check filesystem to loosely match the original fixture
				So(filepath.Join(arena.Path(), "file-a"), testutil.ShouldBeFile)
				So(filepath.Join(arena.Path(), "file-e"), testutil.ShouldBeFile)
				So(filepath.Join(arena.Path(), ".git"), testutil.ShouldBeNotFile)
			})

			Convey("Materialization should be able to produce older commits", FailureContinues, func() {
				uris := []rio.SiloURI{rio.SiloURI("./repo-a")}
				// materialize from the ID returned by foreign git
				arena := transmat.Materialize(Kind, dataHash_2, uris, testutil.TestLogger(c), rio.AcceptHashMismatch)
				// assert hash match
				// (normally survival would attest this, but we used the `AcceptHashMismatch` to supress panics in the name of letting the test see more after failures.)
				So(arena.Hash(), ShouldEqual, dataHash_2)
				// check filesystem to loosely match the original fixture
				So(filepath.Join(arena.Path(), "file-a"), testutil.ShouldBeFile)
				So(filepath.Join(arena.Path(), "file-e"), testutil.ShouldBeNotFile)
				So(filepath.Join(arena.Path(), ".git"), testutil.ShouldBeNotFile)
			})

			Convey("Materialization should work, even when cwd is inside the repo", FailureContinues, func() {
				So(os.Mkdir("repo-a/meta", 0755), ShouldBeNil)
				testutil.UsingDir("repo-a/meta", func() {
					uris := []rio.SiloURI{rio.SiloURI("./..")}
					// materialize from the ID returned by foreign git
					arena := transmat.Materialize(Kind, dataHash_3, uris, testutil.TestLogger(c), rio.AcceptHashMismatch)
					// assert hash match
					// (normally survival would attest this, but we used the `AcceptHashMismatch` to supress panics in the name of letting the test see more after failures.)
					So(arena.Hash(), ShouldEqual, dataHash_3)
					// check filesystem to loosely match the original fixture
					So(filepath.Join(arena.Path(), "file-a"), testutil.ShouldBeFile)
					So(filepath.Join(arena.Path(), "file-e"), testutil.ShouldBeFile)
					So(filepath.Join(arena.Path(), ".git"), testutil.ShouldBeNotFile)
				})
			})
		})),
	)

	// TODO you really should do this with a fixture loop
	// but that does also leave questions about multi-commits, branches, etc.
	// so do both i guess.
	//filefixture.Beta.Create("repo-a")
}
<|endoftext|>


<commit_before>package home

import (
    "testing"
    // "database/sql"
    // _ "github.com/go-sql-driver/mysql"
)

// ATTACH LEFTS AND RIGHTS TO TREE: It should be able to assign lefts and rights to a tree
func TestAttachLeftsAndRights(t *testing.T) {
    beforeEach("mysql")

    // Row 1 node 1
    expectedOut := &treeNode{Parent: nil, Children: nil, Node: Condition{Text: "AND", Type: "logic", Operator: "AND"}, Left: 1, Right: 24}

    // Row 2 node 1
    outChild1 := treeNode{Parent: nil, Children: nil, Node: Condition{Text: "OR", Type: "logic", Operator: "OR"}, Left: 2, Right: 17}
    // Row 2 node 2
    outChild2 := treeNode{Parent: nil, Children: nil, Node: Condition{Text: "OR", Type: "logic", Operator: "OR"}, Left: 18, Right: 23}
    expectedOut.Children = []*treeNode{&outChild1, &outChild2}

    // Row 3 node 1
    outChild3 := treeNode{Parent: &outChild1, Children: nil, Node: Condition{Text: "AND", Type: "logic", Operator: "AND"}, Left: 3, Right: 14}
    // Row 3 node 2
    outChild4 := treeNode{Parent: &outChild1, Children: nil, Node: Condition{Text: "age eq 1", Type: "equality", Field: "age", Operator: "eq", Value: "1"}, Left: 15, Right: 16}
    outChild1.Children = []*treeNode{&outChild3, &outChild4}

    // Row 3 node 3
    outChild5 := treeNode{Parent: &outChild2, Children: nil, Node: Condition{Text: "age eq 2", Type: "equality", Field: "age", Operator: "eq", Value: "2"}, Left: 19, Right: 20}
    // Row 3 node 4
    outChild6 := treeNode{Parent: &outChild2, Children: nil, Node: Condition{Text: "age eq 3", Type: "equality", Field: "age", Operator: "eq", Value: "3"}, Left: 21, Right: 22}
    outChild2.Children = []*treeNode{&outChild5, &outChild6}

    // Row 4 nodes 1-5
    outChild7 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 4", Type: "equality", Field: "age", Operator: "eq", Value: "4"}, Left: 4, Right: 5}
    outChild8 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 5", Type: "equality", Field: "age", Operator: "eq", Value: "5"}, Left: 6, Right: 7}
    outChild9 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 6", Type: "equality", Field: "age", Operator: "eq", Value: "6"}, Left: 8, Right: 9}
    outChild10 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 7", Type: "equality", Field: "age", Operator: "eq", Value: "7"}, Left: 10, Right: 11}
    outChild11 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 8", Type: "equality", Field: "age", Operator: "eq", Value: "8"}, Left: 12, Right: 13}
    outChild3.Children = []*treeNode{&outChild7, &outChild8, &outChild9, &outChild10, &outChild11}

    testingTreeRoot.attachLeftsAndRights()

    if !testingTreeRoot.matches(expectedOut) {
        t.Errorf("%v.attachLeftsAndRights - got %v, want %v", testingTreeRoot, testingTreeRoot.print(), expectedOut.print())
    }
}

// CONVERT TREE TO MYSQL: It should be able to convert a tree to mysql input values
func TestToMysql(t *testing.T) {
    beforeEach("mysql")

    equalityReturned, logicReturned, _ := testingTreeRoot.toMysql()

    if equalityReturned != testingMysqlEqualityInput {
        t.Errorf("%v.toMysql() equalityReturned - got %v, want %v", testingTreeRoot, equalityReturned, testingMysqlEqualityInput)
    }

    if logicReturned != testingMysqlLogicInput {
        t.Errorf("%v.toMysql() logicReturned - got %v, want %v", testingTreeRoot, logicReturned, testingMysqlLogicInput)
    }
}

// // INSERT INTO MYSQL
// func TestDatabaseAndBack(t *testing.T) {
//     var Field, Operator, Value, Type string
//     var Left, Right int
//     var conditionRowsReturned []conditionSqlRow

//     db, _ := sql.Open("mysql", "root:@/")
//     defer db.Close()

//     equalityStr, logicStr, _ := testingTreeRoot.toMysql()
//     updateDatabase(equalityStr, logicStr)

//     // Get equality sql rows
//     rows, _ := db.Query("SELECT COALESCE(field, ''), operator, COALESCE(value, ''), type, lt, rt FROM logictree.conditions")
//     defer rows.Close()

//     for rows.Next() {
//         rows.Scan(&Field, &Operator, &Value, &Type, &Left, &Right)
//         conditionRowsReturned = append(conditionRowsReturned, conditionSqlRow{Field: Field, Operator: Operator, Value: Value, Type: Type, Left: Left, Right: Right})
//     }

//     if !conditionSqlMatchesArray(conditionRowsReturned, testingMysqlOutput) {
//         t.Errorf("updateDatabase(%v) equalityReturned - got %v, want %v", testingTreeRoot, conditionRowsReturned, testingMysqlOutput)
//     }

//     treeReturned := unserializeRawTree(conditionRowsReturned)

//     if !treeReturned.matches(testingTreeRoot) {
//         t.Errorf("unserializeRaw(%v) - got %v, want %v", conditionRowsReturned, treeReturned.print(), testingTreeRoot.print())
//     }
// }

<commit_msg>Passing full stack test with unserialize raw<commit_after>package home

import (
    "testing"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

// ATTACH LEFTS AND RIGHTS TO TREE: It should be able to assign lefts and rights to a tree
func TestAttachLeftsAndRights(t *testing.T) {
    beforeEach("mysql")

    // Row 1 node 1
    expectedOut := &treeNode{Parent: nil, Children: nil, Node: Condition{Text: "AND", Type: "logic", Operator: "AND"}, Left: 1, Right: 24}

    // Row 2 node 1
    outChild1 := treeNode{Parent: nil, Children: nil, Node: Condition{Text: "OR", Type: "logic", Operator: "OR"}, Left: 2, Right: 17}
    // Row 2 node 2
    outChild2 := treeNode{Parent: nil, Children: nil, Node: Condition{Text: "OR", Type: "logic", Operator: "OR"}, Left: 18, Right: 23}
    expectedOut.Children = []*treeNode{&outChild1, &outChild2}

    // Row 3 node 1
    outChild3 := treeNode{Parent: &outChild1, Children: nil, Node: Condition{Text: "AND", Type: "logic", Operator: "AND"}, Left: 3, Right: 14}
    // Row 3 node 2
    outChild4 := treeNode{Parent: &outChild1, Children: nil, Node: Condition{Text: "age eq 1", Type: "equality", Field: "age", Operator: "eq", Value: "1"}, Left: 15, Right: 16}
    outChild1.Children = []*treeNode{&outChild3, &outChild4}

    // Row 3 node 3
    outChild5 := treeNode{Parent: &outChild2, Children: nil, Node: Condition{Text: "age eq 2", Type: "equality", Field: "age", Operator: "eq", Value: "2"}, Left: 19, Right: 20}
    // Row 3 node 4
    outChild6 := treeNode{Parent: &outChild2, Children: nil, Node: Condition{Text: "age eq 3", Type: "equality", Field: "age", Operator: "eq", Value: "3"}, Left: 21, Right: 22}
    outChild2.Children = []*treeNode{&outChild5, &outChild6}

    // Row 4 nodes 1-5
    outChild7 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 4", Type: "equality", Field: "age", Operator: "eq", Value: "4"}, Left: 4, Right: 5}
    outChild8 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 5", Type: "equality", Field: "age", Operator: "eq", Value: "5"}, Left: 6, Right: 7}
    outChild9 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 6", Type: "equality", Field: "age", Operator: "eq", Value: "6"}, Left: 8, Right: 9}
    outChild10 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 7", Type: "equality", Field: "age", Operator: "eq", Value: "7"}, Left: 10, Right: 11}
    outChild11 := treeNode{Parent: &outChild3, Children: nil, Node: Condition{Text: "age eq 8", Type: "equality", Field: "age", Operator: "eq", Value: "8"}, Left: 12, Right: 13}
    outChild3.Children = []*treeNode{&outChild7, &outChild8, &outChild9, &outChild10, &outChild11}

    testingTreeRoot.attachLeftsAndRights()

    if !testingTreeRoot.matches(expectedOut) {
        t.Errorf("%v.attachLeftsAndRights - got %v, want %v", testingTreeRoot, testingTreeRoot.print(), expectedOut.print())
    }
}

// CONVERT TREE TO MYSQL: It should be able to convert a tree to mysql input values
func TestToMysql(t *testing.T) {
    beforeEach("mysql")

    equalityReturned, logicReturned, _ := testingTreeRoot.toMysql()

    if equalityReturned != testingMysqlEqualityInput {
        t.Errorf("%v.toMysql() equalityReturned - got %v, want %v", testingTreeRoot, equalityReturned, testingMysqlEqualityInput)
    }

    if logicReturned != testingMysqlLogicInput {
        t.Errorf("%v.toMysql() logicReturned - got %v, want %v", testingTreeRoot, logicReturned, testingMysqlLogicInput)
    }
}

// INSERT INTO MYSQL
func TestDatabaseAndBack(t *testing.T) {
    var Field, Operator, Value, Type string
    var Left, Right int
    var conditionRowsReturned []conditionSqlRow

    db, _ := sql.Open("mysql", "root:@/")
    defer db.Close()

    equalityStr, logicStr, _ := testingTreeRoot.toMysql()
    updateDatabase(equalityStr, logicStr)

    // Get equality sql rows
    rows, _ := db.Query("SELECT COALESCE(field, ''), operator, COALESCE(value, ''), type, lt, rt FROM logictree.conditions ORDER BY lt")
    defer rows.Close()

    for rows.Next() {
        rows.Scan(&Field, &Operator, &Value, &Type, &Left, &Right)
        conditionRowsReturned = append(conditionRowsReturned, conditionSqlRow{Field: Field, Operator: Operator, Value: Value, Type: Type, Left: Left, Right: Right})
    }

    if !conditionSqlMatchesArray(conditionRowsReturned, testingMysqlRows) {
        t.Errorf("updateDatabase(%v) equalityReturned - got %v, want %v", testingTreeRoot, conditionRowsReturned, testingMysqlRows)
    }

    treeReturned := unserializeRawTree(conditionRowsReturned)

    if !treeReturned.matches(testingTreeRoot) {
        t.Errorf("unserializeRaw(%v) - got %v, want %v", conditionRowsReturned, treeReturned.print(), testingTreeRoot.print())
    }
}

<|endoftext|>


<commit_before>package swgohgg

import (
	"fmt"
	"log"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

type Ability struct {
	Name      string
	Character string
	IsZeta    bool
}

func (c *Client) Zetas() (zetas []Ability, err error) {
	for page := 1; page <= 4; page++ {
		var (
			doc *goquery.Document
			url = fmt.Sprintf("https://swgoh.gg/characters/zeta-abilities/?page=%d", page)
		)
		doc, err = c.Get(url)
		if err != nil {
			return
		}
		aux := make([]Ability, 0)
		doc.Find(".media-list-stream .character h5").Each(func(i int, s *goquery.Selection) {
			// Commander Luke Skywalker · Rebel Maneuvers
			split := strings.Split(s.Text(), " · ")
			if len(split) >= 2 {
				aux = append(aux, Ability{
					Character: strings.TrimSpace(split[0]),
					Name:      strings.TrimSpace(split[1]),
					IsZeta:    true,
				})
			} else {
				log.Printf("> Skipped (len=%d)", len(split))
			}
		})
		if len(aux) == 0 {
			break
		}
		zetas = append(zetas, aux...)
	}
	return
}
<commit_msg>Fix abilities by adding missing page<commit_after>package swgohgg

import (
	"fmt"
	"log"
	"strings"

	"github.com/PuerkitoBio/goquery"
)

type Ability struct {
	Name      string
	Character string
	IsZeta    bool
}

func (c *Client) Zetas() (zetas []Ability, err error) {
	for page := 1; page <= 5; page++ {
		var (
			doc *goquery.Document
			url = fmt.Sprintf("https://swgoh.gg/characters/zeta-abilities/?page=%d", page)
		)
		doc, err = c.Get(url)
		if err != nil {
			return
		}
		aux := make([]Ability, 0)
		doc.Find(".media-list-stream .character h5").Each(func(i int, s *goquery.Selection) {
			// Commander Luke Skywalker · Rebel Maneuvers
			split := strings.Split(s.Text(), " · ")
			if len(split) >= 2 {
				aux = append(aux, Ability{
					Character: strings.TrimSpace(split[0]),
					Name:      strings.TrimSpace(split[1]),
					IsZeta:    true,
				})
			} else {
				log.Printf("> Skipped (len=%d)", len(split))
			}
		})
		if len(aux) == 0 {
			break
		}
		zetas = append(zetas, aux...)
	}
	return
}
<|endoftext|>


<commit_before>package gogo

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

const (
	FS_ZERO = iota
	FS_PAT33
	FS_EDGE_DIS
	FS_EDGE_DIS_X
	FS_EDGE_DIS_Y
)

func (b *Board) GenSimpleFeatures(last, cur Point) map[int]map[int64]byte {
	ret := make(map[int]map[int64]byte)
	for i, ph := range b.patternHash {
		if b.w[i].Color() != GRAY {
			continue
		}
		h1 := b.FeatureHash(MakePoint(b.w[i].x, b.w[i].y, cur.Color()))
		fs := make(map[int64]byte)
		fh := int64(0)
		for _, h := range ph {
			fh ^= h
			fs[fh^h1] = 1
		}
		ret[i] = fs
	}
	return ret
}

func NewBoardFromPath(size int, path []*GameTreeNode) *Board {
	ret := NewBoard(size)
	for i := len(path) - 1; i >= 0; i-- {
		v := path[i]
		ret.Put(v.x, v.y, v.stone)
	}
	return ret
}

func (b *Board) SelfBattle(lastMove Point, color Color) Color {
	rand.Seed(time.Now().UnixNano())

	for {
		pass := 0
		lastMove = b.GenQuickMove(lastMove, color)
		if !lastMove.Valid() {
			pass += 1
		}

		lastMove = b.GenQuickMove(lastMove, OppColor(color))
		if !lastMove.Valid() {
			pass += 1
		}
		if pass >= 2 {
			break
		}
	}
	score := b.Score()
	if score > 0 {
		return BLACK
	} else {
		return WHITE
	}
}

func (p *GameTreeNode) BackPropVisit(root *GameTreeNode) {
	b := p
	for {
		if b == nil {
			break
		}
		b.visit += 1
		if b == root {
			break
		}
		b = b.Father
	}
}

func (p *GameTreeNode) BackPropWin(root *GameTreeNode) {
	b := p
	for {
		if b == nil {
			break
		}
		b.win += 1
		if b == root {
			break
		}
		b = b.Father
	}
}

func (g *Game) MCTreePolicy() *GameTreeNode {
	root := g.GT.Current
	node := root
	for {
		if len(node.Children) > 0 {
			maxScore := 0.0
			for _, child := range node.Children {
				score := float64(child.win) / float64(child.visit)
				score += math.Sqrt(2.0 * math.Log(float64(node.visit)) / float64(child.visit))
				if maxScore < score {
					maxScore = score
					node = child
				}
			}
		} else {
			return node
		}
	}
	return nil
}

type SingleBattleResult struct {
	node     *GameTreeNode
	winColor Color
}

func (g *Game) singleSimulate(newBoard *Board, gn *GameTreeNode, pm Point, ch chan SingleBattleResult) {
	winColor := newBoard.Copy().SelfBattle(pm, OppColor(pm.color))
	ch <- SingleBattleResult{gn, winColor}
}

func (g *Game) MCTSMove(stone Color) {
	root := g.GT.Current
	for root.visit < 1000 {
		fmt.Println(root.visit)
		node := g.MCTreePolicy()
		board := NewBoardFromPath(g.B.size, node.Path2Root())
		//info := board.CollectBoardInfo(InvalidPoint())
		cand := board.QuickCandidateMoves(Point{node.x, node.y, node.stone}, OppColor(node.stone), 20)
		//cand := info.CandidateMoves(Point{node.x, node.y, node.stone}, OppColor(node.stone), g.B.Model(), 5)
		ch := make(chan SingleBattleResult, len(cand)+1)
		n := 0
		for m, v := range cand {
			pm := board.w[m]
			if node == root {
				fmt.Printf("%s%d[%f] ", string(LX[pm.x]), pm.y+1, v)
			}
			pm.color = OppColor(node.stone)
			newBoard := board.Copy()
			if err := newBoard.Put(pm.x, pm.y, pm.color); err != nil {
				continue
			}
			gn := NewGameTreeNode(pm.color, pm.x, pm.y)
			node.AddChild(gn)
			for i := 0; i < 5; i++ {
				n += 1
				go g.singleSimulate(newBoard, gn, pm, ch)
			}
		}
		for i := 0; i < n; i++ {
			sbr := <-ch
			if sbr.winColor == stone {
				sbr.node.BackPropWin(root)
			}
			sbr.node.BackPropVisit(root)
		}
		close(ch)
		if node == root {
			fmt.Println()
		}
		if len(node.Children) == 0 {
			break
		}
	}

	maxRate := 0.0
	bestMove := root.Children[0]

	for _, child := range root.Children {
		winrate := float64(child.win) / float64(child.visit)
		fmt.Println(string(LX[child.x]), child.y+1, child.win, child.visit, winrate)
		if winrate > maxRate {
			maxRate = winrate
			bestMove = child
		}
	}

	root.Children = []*GameTreeNode{}
	g.Put(bestMove.stone, bestMove.x, bestMove.y)
}
<commit_msg>simple feature<commit_after>package gogo

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

const (
	FS_ZERO = iota
	FS_PAT33
	FS_EDGE_DIS
	FS_EDGE_DIS_X
	FS_EDGE_DIS_Y
)

func (b *Board) GenSimpleFeatures(last, cur Point) map[int]map[int64]byte {
	ret := make(map[int]map[int64]byte)
	for i, p := range b.w {
		if p.color != GRAY {
			continue
		}
		fh := b.FeatureHash(MakePoint(b.w[i].x, b.w[i].y, cur.Color()))
		fs := make(map[int64]byte)
		ph := b.GetPatternHash(i)
		for _, h := range ph {
			fs[fh^h] = 1
		}
		ret[i] = fs
	}
	return ret
}

func NewBoardFromPath(size int, path []*GameTreeNode) *Board {
	ret := NewBoard(size)
	for i := len(path) - 1; i >= 0; i-- {
		v := path[i]
		ret.Put(v.x, v.y, v.stone)
	}
	return ret
}

func (b *Board) SelfBattle(lastMove Point, color Color) Color {
	rand.Seed(time.Now().UnixNano())

	for {
		pass := 0
		lastMove = b.GenQuickMove(lastMove, color)
		if !lastMove.Valid() {
			pass += 1
		}

		lastMove = b.GenQuickMove(lastMove, OppColor(color))
		if !lastMove.Valid() {
			pass += 1
		}
		if pass >= 2 {
			break
		}
	}
	score := b.Score()
	if score > 0 {
		return BLACK
	} else {
		return WHITE
	}
}

func (p *GameTreeNode) BackPropVisit(root *GameTreeNode) {
	b := p
	for {
		if b == nil {
			break
		}
		b.visit += 1
		if b == root {
			break
		}
		b = b.Father
	}
}

func (p *GameTreeNode) BackPropWin(root *GameTreeNode) {
	b := p
	for {
		if b == nil {
			break
		}
		b.win += 1
		if b == root {
			break
		}
		b = b.Father
	}
}

func (g *Game) MCTreePolicy() *GameTreeNode {
	root := g.GT.Current
	node := root
	for {
		if len(node.Children) > 0 {
			maxScore := 0.0
			for _, child := range node.Children {
				score := float64(child.win) / float64(child.visit)
				score += math.Sqrt(2.0 * math.Log(float64(node.visit)) / float64(child.visit))
				if maxScore < score {
					maxScore = score
					node = child
				}
			}
		} else {
			return node
		}
	}
	return nil
}

type SingleBattleResult struct {
	node     *GameTreeNode
	winColor Color
}

func (g *Game) singleSimulate(newBoard *Board, gn *GameTreeNode, pm Point, ch chan SingleBattleResult) {
	winColor := newBoard.Copy().SelfBattle(pm, OppColor(pm.color))
	ch <- SingleBattleResult{gn, winColor}
}

func (g *Game) MCTSMove(stone Color) {
	root := g.GT.Current
	for root.visit < 1000 {
		fmt.Println(root.visit)
		node := g.MCTreePolicy()
		board := NewBoardFromPath(g.B.size, node.Path2Root())
		//info := board.CollectBoardInfo(InvalidPoint())
		cand := board.QuickCandidateMoves(Point{node.x, node.y, node.stone}, OppColor(node.stone), 20)
		//cand := info.CandidateMoves(Point{node.x, node.y, node.stone}, OppColor(node.stone), g.B.Model(), 5)
		ch := make(chan SingleBattleResult, len(cand)+1)
		n := 0
		for m, v := range cand {
			pm := board.w[m]
			if node == root {
				fmt.Printf("%s%d[%f] ", string(LX[pm.x]), pm.y+1, v)
			}
			pm.color = OppColor(node.stone)
			newBoard := board.Copy()
			if err := newBoard.Put(pm.x, pm.y, pm.color); err != nil {
				continue
			}
			gn := NewGameTreeNode(pm.color, pm.x, pm.y)
			node.AddChild(gn)
			for i := 0; i < 5; i++ {
				n += 1
				go g.singleSimulate(newBoard, gn, pm, ch)
			}
		}
		for i := 0; i < n; i++ {
			sbr := <-ch
			if sbr.winColor == stone {
				sbr.node.BackPropWin(root)
			}
			sbr.node.BackPropVisit(root)
		}
		close(ch)
		if node == root {
			fmt.Println()
		}
		if len(node.Children) == 0 {
			break
		}
	}

	maxRate := 0.0
	bestMove := root.Children[0]

	for _, child := range root.Children {
		winrate := float64(child.win) / float64(child.visit)
		fmt.Println(string(LX[child.x]), child.y+1, child.win, child.visit, winrate)
		if winrate > maxRate {
			maxRate = winrate
			bestMove = child
		}
	}

	root.Children = []*GameTreeNode{}
	g.Put(bestMove.stone, bestMove.x, bestMove.y)
}
<|endoftext|>


<commit_before>package gopm_index

import (
    "encoding/json"
)

type PackageMeta struct {
    Name         string       `json:"name"`
    Description  string       `json:"description"`
    Category     string       `json:"category"`
    Keywords     []string     `json:"keywords"`
    Author       PersonMeta   `json:"author"`
    Contributors []PersonMeta `json:"contributors"`
    Repositories []string     `json:"repositories"`
}

type PersonMeta struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

func (meta *PackageMeta) ToJsonString() (str string, err error) {
    var data []byte
    data, err = json.Marshal(meta)
    if err != nil {
        return
    }
    str = string(data)
    return
}
<commit_msg>PackageMeta.ToJsonString() returns a []byte now<commit_after>package gopm_index

import (
    "encoding/json"
)

type PackageMeta struct {
    Name         string       `json:"name"`
    Description  string       `json:"description"`
    Category     string       `json:"category"`
    Keywords     []string     `json:"keywords"`
    Author       PersonMeta   `json:"author"`
    Contributors []PersonMeta `json:"contributors"`
    Repositories []string     `json:"repositories"`
}

type PersonMeta struct {
    Name  string `json:"name"`
    Email string `json:"email"`
}

func (meta *PackageMeta) ToJsonString() (content []byte, err error) {
    content, err = json.Marshal(meta)
    return
}
<|endoftext|>


<commit_before>package ttlcache

import (
	"encoding/json"
	"sync"

	"github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/sonde-go/events"
)

//Resource represents cloud controller data
type Resource struct {
	mutext         sync.RWMutex
	deployment     string
	job            string
	index          string
	ip             string
	valueMetrics   map[string][]*Metric
	counterMetrics map[string][]*Metric
}

//CreateResource Creates a new resource
func CreateResource(deployment, job, index, ip string) *Resource {
	return &Resource{
		deployment:     deployment,
		job:            job,
		index:          index,
		ip:             ip,
		valueMetrics:   make(map[string][]*Metric),
		counterMetrics: make(map[string][]*Metric),
	}
}

//AddMetric adds a metric to a resource
func (r *Resource) AddMetric(envelope *events.Envelope, logger *gosteno.Logger) {
	var metrics []*Metric

	timestamp := envelope.GetTimestamp()

	switch envelope.GetEventType() {
	case events.Envelope_ValueMetric:
		valueMetric := envelope.GetValueMetric()
		r.mutext.Lock()

		metrics = r.getMetrics(r.valueMetrics, valueMetric.GetName())
		var metric = &Metric{}
		metric.update(valueMetric.GetValue(), timestamp, GetInstance().TTL)
		metrics = append(metrics, metric)
		r.valueMetrics[valueMetric.GetName()] = metrics
		r.mutext.Unlock()
		logger.Debugf("Adding Value Event Name %s, Value %d", valueMetric.GetName(), valueMetric.GetValue())
	case events.Envelope_CounterEvent:
		counterEvent := envelope.GetCounterEvent()
		r.mutext.Lock()

		metrics = r.getMetrics(r.counterMetrics, counterEvent.GetName())
		var metric = &Metric{}
		metric.update(float64(counterEvent.GetTotal()), timestamp, GetInstance().TTL)
		metrics = append(metrics, metric)
		r.counterMetrics[counterEvent.GetName()] = metrics
		r.mutext.Unlock()
		logger.Debugf("Adding Counter Event Name %s, Value %d", counterEvent.GetName(), counterEvent.GetTotal())
	case events.Envelope_ContainerMetric:
		// ignored message type
	case events.Envelope_LogMessage:
		// ignored message type
	case events.Envelope_HttpStartStop:
		// ignored message type
	case events.Envelope_Error:
		// ignored message type
	default:
		logger.Warnf("Unknown event type %s", envelope.GetEventType())
	}

	logger.Debugf("After adding the metric: %s", metrics)
}

func (r *Resource) isEmpty() bool {
	r.mutext.RLock()
	defer r.mutext.RUnlock()
	count := 0
	for _, metrics := range r.valueMetrics {
		count += len(metrics)
	}
	// count := len(r.valueMetrics)
	for _, metrics := range r.counterMetrics {
		count += len(metrics)
	}
	return count == 0
}

func (r *Resource) cleanup() {
	r.mutext.Lock()
	defer r.mutext.Unlock()

	for key, metrics := range r.valueMetrics {
		r.valueMetrics[key] = nonExpiredMetric(metrics)
	}

	for key, metrics := range r.counterMetrics {
		r.counterMetrics[key] = nonExpiredMetric(metrics)
	}
}

func nonExpiredMetric(metrics []*Metric) []*Metric {
	var metricsToKeep []*Metric
	for _, metric := range metrics {
		if !metric.expired() {
			metricsToKeep = append(metricsToKeep, metric)
		}
	}
	return metricsToKeep
}

func (r *Resource) getMetrics(metricMap map[string][]*Metric, metricName string) []*Metric {
	var metrics []*Metric
	if value, ok := metricMap[metricName]; ok {
		return value
	}

	metricMap[metricName] = metrics
	return metrics
}

//metricJSON is a private struct for structure metrics in JSON
type metricJSON struct {
	Value     float64 `json:"value"`
	Timestamp int64   `json:"timestamp"`
}

//metricsJSON is a struct to make a slice out of the metrics
type metricsJSON struct {
	Metrics []metricJSON `json:"metrics"`
}

func (r *Resource) MarshalJSON() ([]byte, error) {
	valueMetrics, counterMetrics := convertMap(r.valueMetrics), convertMap(r.counterMetrics)

	return json.Marshal(&struct {
		Deployment     string
		Job            string
		Index          string
		IP             string
		ValueMetrics   map[string]metricsJSON
		CounterMetrics map[string]metricsJSON
	}{
		Deployment:     r.deployment,
		Job:            r.job,
		Index:          r.index,
		IP:             r.ip,
		ValueMetrics:   valueMetrics,
		CounterMetrics: counterMetrics,
	})
}

func convertMap(inputMap map[string][]*Metric) map[string]metricsJSON {
	outputMap := make(map[string]metricsJSON)
	for key, metrics := range inputMap {
		var emptyList []metricJSON
		var jsonMetrics = metricsJSON{Metrics: emptyList}
		for _, metric := range metrics {
			jsonMetrics.Metrics = append(jsonMetrics.Metrics, metricJSON{Value: metric.getData(), Timestamp: metric.getTimestamp()})
		}
		outputMap[key] = jsonMetrics
	}
	return outputMap
}
<commit_msg>Removed debug message.<commit_after>package ttlcache

import (
	"encoding/json"
	"sync"

	"github.com/cloudfoundry/gosteno"
	"github.com/cloudfoundry/sonde-go/events"
)

//Resource represents cloud controller data
type Resource struct {
	mutext         sync.RWMutex
	deployment     string
	job            string
	index          string
	ip             string
	valueMetrics   map[string][]*Metric
	counterMetrics map[string][]*Metric
}

//CreateResource Creates a new resource
func CreateResource(deployment, job, index, ip string) *Resource {
	return &Resource{
		deployment:     deployment,
		job:            job,
		index:          index,
		ip:             ip,
		valueMetrics:   make(map[string][]*Metric),
		counterMetrics: make(map[string][]*Metric),
	}
}

//AddMetric adds a metric to a resource
func (r *Resource) AddMetric(envelope *events.Envelope, logger *gosteno.Logger) {
	var metrics []*Metric

	timestamp := envelope.GetTimestamp()

	switch envelope.GetEventType() {
	case events.Envelope_ValueMetric:
		valueMetric := envelope.GetValueMetric()
		r.mutext.Lock()

		metrics = r.getMetrics(r.valueMetrics, valueMetric.GetName())
		var metric = &Metric{}
		metric.update(valueMetric.GetValue(), timestamp, GetInstance().TTL)
		metrics = append(metrics, metric)
		r.valueMetrics[valueMetric.GetName()] = metrics
		r.mutext.Unlock()
		logger.Debugf("Adding Value Event Name %s, Value %d", valueMetric.GetName(), valueMetric.GetValue())
	case events.Envelope_CounterEvent:
		counterEvent := envelope.GetCounterEvent()
		r.mutext.Lock()

		metrics = r.getMetrics(r.counterMetrics, counterEvent.GetName())
		var metric = &Metric{}
		metric.update(float64(counterEvent.GetTotal()), timestamp, GetInstance().TTL)
		metrics = append(metrics, metric)
		r.counterMetrics[counterEvent.GetName()] = metrics
		r.mutext.Unlock()
		logger.Debugf("Adding Counter Event Name %s, Value %d", counterEvent.GetName(), counterEvent.GetTotal())
	case events.Envelope_ContainerMetric:
		// ignored message type
	case events.Envelope_LogMessage:
		// ignored message type
	case events.Envelope_HttpStartStop:
		// ignored message type
	case events.Envelope_Error:
		// ignored message type
	default:
		logger.Warnf("Unknown event type %s", envelope.GetEventType())
	}
}

func (r *Resource) isEmpty() bool {
	r.mutext.RLock()
	defer r.mutext.RUnlock()
	count := 0
	for _, metrics := range r.valueMetrics {
		count += len(metrics)
	}
	// count := len(r.valueMetrics)
	for _, metrics := range r.counterMetrics {
		count += len(metrics)
	}
	return count == 0
}

func (r *Resource) cleanup() {
	r.mutext.Lock()
	defer r.mutext.Unlock()

	for key, metrics := range r.valueMetrics {
		r.valueMetrics[key] = nonExpiredMetric(metrics)
	}

	for key, metrics := range r.counterMetrics {
		r.counterMetrics[key] = nonExpiredMetric(metrics)
	}
}

func nonExpiredMetric(metrics []*Metric) []*Metric {
	var metricsToKeep []*Metric
	for _, metric := range metrics {
		if !metric.expired() {
			metricsToKeep = append(metricsToKeep, metric)
		}
	}
	return metricsToKeep
}

func (r *Resource) getMetrics(metricMap map[string][]*Metric, metricName string) []*Metric {
	var metrics []*Metric
	if value, ok := metricMap[metricName]; ok {
		return value
	}

	metricMap[metricName] = metrics
	return metrics
}

//metricJSON is a private struct for structure metrics in JSON
type metricJSON struct {
	Value     float64 `json:"value"`
	Timestamp int64   `json:"timestamp"`
}

//metricsJSON is a struct to make a slice out of the metrics
type metricsJSON struct {
	Metrics []metricJSON `json:"metrics"`
}

func (r *Resource) MarshalJSON() ([]byte, error) {
	valueMetrics, counterMetrics := convertMap(r.valueMetrics), convertMap(r.counterMetrics)

	return json.Marshal(&struct {
		Deployment     string
		Job            string
		Index          string
		IP             string
		ValueMetrics   map[string]metricsJSON
		CounterMetrics map[string]metricsJSON
	}{
		Deployment:     r.deployment,
		Job:            r.job,
		Index:          r.index,
		IP:             r.ip,
		ValueMetrics:   valueMetrics,
		CounterMetrics: counterMetrics,
	})
}

func convertMap(inputMap map[string][]*Metric) map[string]metricsJSON {
	outputMap := make(map[string]metricsJSON)
	for key, metrics := range inputMap {
		var emptyList []metricJSON
		var jsonMetrics = metricsJSON{Metrics: emptyList}
		for _, metric := range metrics {
			jsonMetrics.Metrics = append(jsonMetrics.Metrics, metricJSON{Value: metric.getData(), Timestamp: metric.getTimestamp()})
		}
		outputMap[key] = jsonMetrics
	}
	return outputMap
}
<|endoftext|>


<commit_before>package routes

import (
	"log"
	"net/http"
	"os"
	"text/template"
	"time"

	"github.com/google/go-github/github"
	"github.com/julienschmidt/httprouter"
	"golang.org/x/oauth2"

	"github.com/gophergala2016/hugoku/ci"
	"github.com/gophergala2016/hugoku/store"
	"github.com/gophergala2016/hugoku/util/cmd"
	"github.com/gophergala2016/hugoku/util/repo"
	"github.com/gophergala2016/hugoku/util/session"
)

// PostProject ...
func PostProject(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	var buildStatus = "ok"
	user, err := session.GetUser(r)
	if err != nil {
		log.Fatal(err)
	}
	projectName := r.PostFormValue("name")
	if projectName == "" {
		log.Println("Missing projectName")
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
	}
	repoDescription := "Repository for " + projectName + " created by Hugoku"
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: user.Token.AccessToken},
	)
	tc := oauth2.NewClient(oauth2.NoContext, ts)
	client := github.NewClient(tc)

	log.Printf("Creating %s...", projectName)

	buildStartTime := time.Now()
	//path, err := ci.Deploy(username.(string), projectName)
	_, err = ci.Deploy(user.Username, projectName)

	buildDuration := time.Since(buildStartTime)
	log.Printf("Build duration: %s\n", buildDuration)

	if err != nil {
		log.Fatalf("Error while trying to create project: %s", err)
		buildStatus = "fail"
	}

	if !repo.Exists(client, user.Username, projectName) {
		gitHubStartTime := time.Now()
		repo := &github.Repository{
			Name:        github.String(projectName),
			Private:     github.Bool(false),
			Description: github.String(repoDescription),
		}
		repo, _, err = client.Repositories.Create("", repo)
		if err != nil {
			log.Fatalf("Error while trying to create repo: %s", err)
		}

		// Push the repo
		wd, _ := os.Getwd()
		err := os.Chdir(wd + "/repos/" + user.Username + "/" + projectName + "/")
		if err != nil {
			log.Fatal(err)
		}
		cmd.Run("git", []string{"init", "--quiet"})
		cmd.Run("git", []string{"add", "."})
		cmd.Run("git", []string{"commit", "-m", "'initial source code'"})
		cmd.Run("git", []string{"remote", "add", "origin", "git@github.com:" + user.Username + "/" + projectName + ".git"})
		cmd.Run("git", []string{"push", "--quiet", "-u", "origin", "master"})
		err = os.Chdir(wd)
		if err != nil {
			log.Fatal(err)
		}
		githubTime := time.Since(gitHubStartTime)
		log.Printf("Git repo creation duration: %s\n", githubTime)
	}
	buildInfo := store.BuildInfo{BuildTime: time.Now(), BuildDuration: buildDuration, BuildStatus: buildStatus}
	project := store.Project{Name: projectName, Description: repoDescription, BuildsInfo: []store.BuildInfo{buildInfo}, LastBuildInfo: buildInfo}
	user.Projects = append(user.Projects, project)

	err = store.SaveUser(user)

	//http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
}

// GetProject is the Hugoku project page handdler and shows the project and the build history.
func GetProject(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	var id = ps.ByName("id")
	user, err := session.GetUser(r)
	if err != nil {
		log.Fatal("Error getting the user from the session: ", err)
	}
	// TODO: sanitize id
	log.Printf("getProject %s!\n", id)

	if id == "" {
		log.Println("Missing project id!")
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
		return
	}
	project, err := user.GetProject(id)
	if err != nil {
		log.Println("Error getting project: ", id, err)
	}
	t, err := template.ParseFiles("templates/project.html",
		"templates/partials/footer.html",
		"templates/partials/header.html")
	if err != nil {
		log.Fatal("Error parsing the project page template:", err)
	}
	err = t.Execute(w, project)
	if err != nil {
		log.Fatal("Error executing the project page template:", err)
	}
}

// DeleteProject Deletes a project
func DeleteProject(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	var id = ps.ByName("id")
	user, err := session.GetUser(r)
	if err != nil {
		log.Println("Error getting the user from the session: ", err)
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	if id == "" {
		log.Println("Missing project id!")
		http.NotFound(w, r)
		return
	}
	_, err = user.GetProject(id)
	if err != nil {
		log.Println("Error getting project: ", id, err)
		http.NotFound(w, r)
	} else {
		// TODO: sanitize id
		wd, _ := os.Getwd()
		err := os.Chdir(wd + "/repos/" + user.Username + "/")
		if err != nil {
			http.Error(w, "Unexpected Error", http.StatusInternalServerError)
			return
		}
		cmd.Run("rm", []string{"-rf", id})
		log.Printf("DeleteProject %s!\n", id)
		w.WriteHeader(http.StatusNoContent)
	}
}
<commit_msg>Fixed issue #47 Unexpected 405 method not allowed after project creation<commit_after>package routes

import (
	"log"
	"net/http"
	"os"
	"text/template"
	"time"

	"github.com/google/go-github/github"
	"github.com/julienschmidt/httprouter"
	"golang.org/x/oauth2"

	"github.com/gophergala2016/hugoku/ci"
	"github.com/gophergala2016/hugoku/store"
	"github.com/gophergala2016/hugoku/util/cmd"
	"github.com/gophergala2016/hugoku/util/repo"
	"github.com/gophergala2016/hugoku/util/session"
)

// PostProject ...
func PostProject(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	var buildStatus = "ok"
	user, err := session.GetUser(r)
	if err != nil {
		log.Fatal(err)
	}
	projectName := r.PostFormValue("name")
	if projectName == "" {
		log.Println("Missing projectName")
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
	}
	repoDescription := "Repository for " + projectName + " created by Hugoku"
	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: user.Token.AccessToken},
	)
	tc := oauth2.NewClient(oauth2.NoContext, ts)
	client := github.NewClient(tc)

	log.Printf("Creating %s...", projectName)

	buildStartTime := time.Now()
	//path, err := ci.Deploy(username.(string), projectName)
	_, err = ci.Deploy(user.Username, projectName)

	buildDuration := time.Since(buildStartTime)
	log.Printf("Build duration: %s\n", buildDuration)

	if err != nil {
		log.Fatalf("Error while trying to create project: %s", err)
		buildStatus = "fail"
	}

	if !repo.Exists(client, user.Username, projectName) {
		gitHubStartTime := time.Now()
		repo := &github.Repository{
			Name:        github.String(projectName),
			Private:     github.Bool(false),
			Description: github.String(repoDescription),
		}
		repo, _, err = client.Repositories.Create("", repo)
		if err != nil {
			log.Fatalf("Error while trying to create repo: %s", err)
		}

		// Push the repo
		wd, _ := os.Getwd()
		err := os.Chdir(wd + "/repos/" + user.Username + "/" + projectName + "/")
		if err != nil {
			log.Fatal(err)
		}
		cmd.Run("git", []string{"init", "--quiet"})
		cmd.Run("git", []string{"add", "."})
		cmd.Run("git", []string{"commit", "-m", "'initial source code'"})
		cmd.Run("git", []string{"remote", "add", "origin", "git@github.com:" + user.Username + "/" + projectName + ".git"})
		cmd.Run("git", []string{"push", "--quiet", "-u", "origin", "master"})
		err = os.Chdir(wd)
		if err != nil {
			log.Fatal(err)
		}
		githubTime := time.Since(gitHubStartTime)
		log.Printf("Git repo creation duration: %s\n", githubTime)
	}
	buildInfo := store.BuildInfo{BuildTime: time.Now(), BuildDuration: buildDuration, BuildStatus: buildStatus}
	project := store.Project{Name: projectName, Description: repoDescription, BuildsInfo: []store.BuildInfo{buildInfo}, LastBuildInfo: buildInfo}
	user.Projects = append(user.Projects, project)

	err = store.SaveUser(user)

	http.Redirect(w, r, "/", http.StatusSeeOther)
}

// GetProject is the Hugoku project page handdler and shows the project and the build history.
func GetProject(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	var id = ps.ByName("id")
	user, err := session.GetUser(r)
	if err != nil {
		log.Fatal("Error getting the user from the session: ", err)
	}
	// TODO: sanitize id
	log.Printf("getProject %s!\n", id)

	if id == "" {
		log.Println("Missing project id!")
		http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
		return
	}
	project, err := user.GetProject(id)
	if err != nil {
		log.Println("Error getting project: ", id, err)
	}
	t, err := template.ParseFiles("templates/project.html",
		"templates/partials/footer.html",
		"templates/partials/header.html")
	if err != nil {
		log.Fatal("Error parsing the project page template:", err)
	}
	err = t.Execute(w, project)
	if err != nil {
		log.Fatal("Error executing the project page template:", err)
	}
}

// DeleteProject Deletes a project
func DeleteProject(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	var id = ps.ByName("id")
	user, err := session.GetUser(r)
	if err != nil {
		log.Println("Error getting the user from the session: ", err)
		http.Error(w, "Forbidden", http.StatusForbidden)
		return
	}

	if id == "" {
		log.Println("Missing project id!")
		http.NotFound(w, r)
		return
	}
	_, err = user.GetProject(id)
	if err != nil {
		log.Println("Error getting project: ", id, err)
		http.NotFound(w, r)
	} else {
		// TODO: sanitize id
		wd, _ := os.Getwd()
		err := os.Chdir(wd + "/repos/" + user.Username + "/")
		if err != nil {
			http.Error(w, "Unexpected Error", http.StatusInternalServerError)
			return
		}
		cmd.Run("rm", []string{"-rf", id})
		log.Printf("DeleteProject %s!\n", id)
		w.WriteHeader(http.StatusNoContent)
	}
}
<|endoftext|>