<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/codegangsta/cli"
	"io/ioutil"
	"os"
)

type InputNode struct {
	Id      string   `json:"id"`
	Parents []string `json:"parents"`
}

// Type:
// 0: |
// 1: ┘
// 2: ┐
// 3: ┌
type Point struct {
	X    int `json:"x"`
	Y    int `json:"y"`
	Type int `json:"type"`
}

type Path struct {
	Id   string  `json:"id"`
	Path []Point `json:"path"`
}

type OutputNode struct {
	Id                string             `json:"id"`
	Parents           []string           `json:"parents"`
	Column            int                `json:"column"`
	ParentsPaths      map[string][]Point `json:"-"`
	FinalParentsPaths []Path             `json:"parents_paths"`
	Idx               int                `json:"idx"`
	Children          []string           `json:"-"`
}

func serializeOutput(out []*OutputNode) ([]byte, error) {
	for _, node := range out {
		for parentId, path := range node.ParentsPaths {
			node.FinalParentsPaths = append(node.FinalParentsPaths, Path{parentId, path})
		}
	}
	treeBytes, err := json.Marshal(&out)
	return treeBytes, err
}

func getInputNodesFromJson(inputJson string) (nodes []InputNode, err error) {
	if err = json.Unmarshal([]byte(inputJson), &nodes); err != nil {
		return
	}
	return
}

func initNodes(inputNodes []InputNode) []*OutputNode {
	out := make([]*OutputNode, 0)
	for idx, node := range inputNodes {
		newNode := OutputNode{}
		newNode.Id = node.Id
		newNode.Parents = node.Parents
		newNode.Column = -1
		newNode.ParentsPaths = make(map[string][]Point)
		newNode.FinalParentsPaths = make([]Path, 0)
		newNode.Idx = idx
		newNode.Children = make([]string, 0)
		out = append(out, &newNode)
	}
	return out
}

func initIndex(nodes []*OutputNode) map[string]*OutputNode {
	index := make(map[string]*OutputNode)
	for _, node := range nodes {
		index[node.Id] = node
	}
	return index
}

func initChildren(nodes []*OutputNode, index map[string]*OutputNode) {
	for _, node := range nodes {
		for _, parentId := range node.Parents {
			index[parentId].Children = append(index[parentId].Children, node.Id)
		}
	}
}

func setColumns(nodes []*OutputNode, index map[string]*OutputNode) {
	nextColumn := 0
	for _, node := range nodes {
		if node.Column == -1 {
			node.Column = nextColumn
			nextColumn++
		}

		for _, childId := range node.Children {
			child := index[childId]
			if node.Column < child.Column {
				nextColumn--

				if child.Parents[0] != node.Id || len(child.Parents) <= 1 {
					// Insert before the last element '-__-
					pos := len(child.ParentsPaths[node.Id]) - 1
					child.ParentsPaths[node.Id] = append(child.ParentsPaths[node.Id], Point{})
					copy(child.ParentsPaths[node.Id][pos+1:], child.ParentsPaths[node.Id][pos:])
					child.ParentsPaths[node.Id][pos] = Point{child.ParentsPaths[node.Id][pos-1].X, node.Idx, 1}
				}
			}
		}

		for parentIdx, parentId := range node.Parents {
			parent := index[parentId]

			node.ParentsPaths[parent.Id] = append(node.ParentsPaths[parent.Id], Point{node.Column, node.Idx, 0})

			if parent.Column == -1 {
				if parentIdx == 0 || (parentIdx == 1 && index[node.Parents[0]].Column < node.Column) {
					parent.Column = node.Column
				} else {
					parent.Column = nextColumn
					node.ParentsPaths[parent.Id] = append(node.ParentsPaths[parent.Id], Point{parent.Column, node.Idx, 2})
					nextColumn++
				}
			} else {
				if node.Column < parent.Column && parentIdx == 0 {
					for _, childId := range parent.Children {
						child := index[childId]
						idxRemove := len(child.ParentsPaths[parent.Id]) - 1
						if idxRemove > 0 {
							if child.ParentsPaths[parent.Id][idxRemove].Type != 2 {
								child.ParentsPaths[parent.Id] = append(child.ParentsPaths[parent.Id][:idxRemove], child.ParentsPaths[parent.Id][idxRemove+1:]...) // DELETE '-__-
							}
							child.ParentsPaths[parent.Id] = append(child.ParentsPaths[parent.Id], Point{node.Column, parent.Idx, 0})
						}
					}
					parent.Column = node.Column
				} else if node.Column > parent.Column {
					if node.Parents[0] == parent.Id && len(node.Parents) > 1 {
						node.ParentsPaths[parent.Id] = append(node.ParentsPaths[parent.Id], Point{parent.Column, node.Idx, 3})
					}
				}
			}

			node.ParentsPaths[parent.Id] = append(node.ParentsPaths[parent.Id], Point{parent.Column, parent.Idx, 0})

		}
	}
}

func buildTree(inputNodes []InputNode) ([]*OutputNode, error) {
	var nodes []*OutputNode = initNodes(inputNodes)
	var index map[string]*OutputNode = initIndex(nodes)

	initChildren(nodes, index)
	setColumns(nodes, index)

	return nodes, nil
}

func BuildTreeJson(inputJson string) (tree string, err error) {
	nodes, err := getInputNodesFromJson(inputJson)
	if err != nil {
		return
	}

	out, err := buildTree(nodes)
	if err != nil {
		return
	}

	treeBytes, err := serializeOutput(out)
	if err != nil {
		return
	}
	tree = string(treeBytes)
	return
}

func bootstrap(c *cli.Context) {
	var inputJson string
	jsonFlag := c.String("json")
	fileFlag := c.String("file")
	if jsonFlag != "" {
		inputJson = jsonFlag
	} else if fileFlag != "" {
		bytes, err := ioutil.ReadFile(fileFlag)
		if err != nil {
			fmt.Println(err)
			return
		}
		inputJson = string(bytes)
	} else {
		cli.ShowAppHelp(c)
		return
	}

	out, err := BuildTreeJson(inputJson)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(out)
}

func main() {
	var authors []cli.Author
	// Collaborators, add your name here :)
	authors = append(authors, cli.Author{"Alain Gilbert", "alain.gilbert.15@gmail.com"})

	app := cli.NewApp()
	app.Authors = authors
	app.Version = "0.0.0"
	app.Name = "git2graph"
	app.Usage = "Take a git tree, make a graph structure"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "f, file",
			Usage: "File",
		},
		cli.StringFlag{
			Name:  "j, json",
			Usage: "Json input",
		},
	}
	app.Action = bootstrap
	app.Run(os.Args)
}
<commit_msg>make test9 pass... Need to fix the shitty slice api<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/codegangsta/cli"
	"io/ioutil"
	"os"
)

type InputNode struct {
	Id      string   `json:"id"`
	Parents []string `json:"parents"`
}

// Type:
// 0: |
// 1: ┘
// 2: ┐
// 3: ┌
type Point struct {
	X    int `json:"x"`
	Y    int `json:"y"`
	Type int `json:"type"`
}

type Path struct {
	Id   string  `json:"id"`
	Path []Point `json:"path"`
}

type OutputNode struct {
	Id                string             `json:"id"`
	Parents           []string           `json:"parents"`
	Column            int                `json:"column"`
	ParentsPaths      map[string][]Point `json:"-"`
	FinalParentsPaths []Path             `json:"parents_paths"`
	Idx               int                `json:"idx"`
	Children          []string           `json:"-"`
}

func serializeOutput(out []*OutputNode) ([]byte, error) {
	for _, node := range out {
		for parentId, path := range node.ParentsPaths {
			node.FinalParentsPaths = append(node.FinalParentsPaths, Path{parentId, path})
		}
	}
	treeBytes, err := json.Marshal(&out)
	return treeBytes, err
}

func getInputNodesFromJson(inputJson string) (nodes []InputNode, err error) {
	if err = json.Unmarshal([]byte(inputJson), &nodes); err != nil {
		return
	}
	return
}

func initNodes(inputNodes []InputNode) []*OutputNode {
	out := make([]*OutputNode, 0)
	for idx, node := range inputNodes {
		newNode := OutputNode{}
		newNode.Id = node.Id
		newNode.Parents = node.Parents
		newNode.Column = -1
		newNode.ParentsPaths = make(map[string][]Point)
		newNode.FinalParentsPaths = make([]Path, 0)
		newNode.Idx = idx
		newNode.Children = make([]string, 0)
		out = append(out, &newNode)
	}
	return out
}

func initIndex(nodes []*OutputNode) map[string]*OutputNode {
	index := make(map[string]*OutputNode)
	for _, node := range nodes {
		index[node.Id] = node
	}
	return index
}

func initChildren(nodes []*OutputNode, index map[string]*OutputNode) {
	for _, node := range nodes {
		for _, parentId := range node.Parents {
			index[parentId].Children = append(index[parentId].Children, node.Id)
		}
	}
}

func setColumns(nodes []*OutputNode, index map[string]*OutputNode) {
	nextColumn := 0
	for _, node := range nodes {
		if node.Column == -1 {
			node.Column = nextColumn
			nextColumn++
		}

		for _, childId := range node.Children {
			child := index[childId]
			if node.Column < child.Column {
				nextColumn--

				if child.Parents[0] != node.Id || len(child.Parents) <= 1 {
					// Insert before the last element '-__-
					pos := len(child.ParentsPaths[node.Id]) - 1
					child.ParentsPaths[node.Id] = append(child.ParentsPaths[node.Id], Point{})
					copy(child.ParentsPaths[node.Id][pos+1:], child.ParentsPaths[node.Id][pos:])
					child.ParentsPaths[node.Id][pos] = Point{child.ParentsPaths[node.Id][pos-1].X, node.Idx, 1}

					for followingNodeIdx, followingNode := range nodes {
						if followingNodeIdx > node.Idx {
							if followingNode.Column > child.Column {

								for _, followingNodeChildId := range followingNode.Children {
									followingNodeChild := index[followingNodeChildId]

									idxRemove := len(followingNodeChild.ParentsPaths[followingNode.Id]) - 1
									followingNodeChild.ParentsPaths[followingNode.Id] = append(followingNodeChild.ParentsPaths[followingNode.Id][:idxRemove], followingNodeChild.ParentsPaths[followingNode.Id][idxRemove+1:]...) // DELETE '-__-

									// Insert before the last element '-__-
									pos := len(followingNodeChild.ParentsPaths[followingNode.Id]) - 1
									//followingNodeChild.ParentsPaths[followingNode.Id] = append(followingNodeChild.ParentsPaths[followingNode.Id], Point{})
									//copy(followingNodeChild.ParentsPaths[followingNode.Id][pos+1:], followingNodeChild.ParentsPaths[followingNode.Id][pos:])
									//followingNodeChild.ParentsPaths[followingNode.Id][pos] = Point{followingNodeChild.ParentsPaths[followingNode.Id][pos-1].X, node.Idx, 1}

									followingNodeChild.ParentsPaths[followingNode.Id] = append(followingNodeChild.ParentsPaths[followingNode.Id], Point{followingNodeChild.ParentsPaths[followingNode.Id][pos].X, node.Idx, 1})
									followingNodeChild.ParentsPaths[followingNode.Id] = append(followingNodeChild.ParentsPaths[followingNode.Id], Point{followingNode.Column-1, node.Idx, 0})
									followingNodeChild.ParentsPaths[followingNode.Id] = append(followingNodeChild.ParentsPaths[followingNode.Id], Point{followingNode.Column-1, followingNode.Idx, 0})
								}

								followingNode.Column--
							}
						}
					}
				}
			}
		}

		for parentIdx, parentId := range node.Parents {
			parent := index[parentId]

			node.ParentsPaths[parent.Id] = append(node.ParentsPaths[parent.Id], Point{node.Column, node.Idx, 0})

			if parent.Column == -1 {
				if parentIdx == 0 || (parentIdx == 1 && index[node.Parents[0]].Column < node.Column) {
					parent.Column = node.Column
				} else {
					parent.Column = nextColumn
					node.ParentsPaths[parent.Id] = append(node.ParentsPaths[parent.Id], Point{parent.Column, node.Idx, 2})
					nextColumn++
				}
			} else {
				if node.Column < parent.Column && parentIdx == 0 {
					for _, childId := range parent.Children {
						child := index[childId]
						idxRemove := len(child.ParentsPaths[parent.Id]) - 1
						if idxRemove > 0 {
							if child.ParentsPaths[parent.Id][idxRemove].Type != 2 {
								child.ParentsPaths[parent.Id] = append(child.ParentsPaths[parent.Id][:idxRemove], child.ParentsPaths[parent.Id][idxRemove+1:]...) // DELETE '-__-
							}
							child.ParentsPaths[parent.Id] = append(child.ParentsPaths[parent.Id], Point{node.Column, parent.Idx, 0})
						}
					}
					parent.Column = node.Column
				} else if node.Column > parent.Column {
					if node.Parents[0] == parent.Id && len(node.Parents) > 1 {
						node.ParentsPaths[parent.Id] = append(node.ParentsPaths[parent.Id], Point{parent.Column, node.Idx, 3})
					}
				}
			}

			node.ParentsPaths[parent.Id] = append(node.ParentsPaths[parent.Id], Point{parent.Column, parent.Idx, 0})

		}
	}
}

func buildTree(inputNodes []InputNode) ([]*OutputNode, error) {
	var nodes []*OutputNode = initNodes(inputNodes)
	var index map[string]*OutputNode = initIndex(nodes)

	initChildren(nodes, index)
	setColumns(nodes, index)

	return nodes, nil
}

func BuildTreeJson(inputJson string) (tree string, err error) {
	nodes, err := getInputNodesFromJson(inputJson)
	if err != nil {
		return
	}

	out, err := buildTree(nodes)
	if err != nil {
		return
	}

	treeBytes, err := serializeOutput(out)
	if err != nil {
		return
	}
	tree = string(treeBytes)
	return
}

func bootstrap(c *cli.Context) {
	var inputJson string
	jsonFlag := c.String("json")
	fileFlag := c.String("file")
	if jsonFlag != "" {
		inputJson = jsonFlag
	} else if fileFlag != "" {
		bytes, err := ioutil.ReadFile(fileFlag)
		if err != nil {
			fmt.Println(err)
			return
		}
		inputJson = string(bytes)
	} else {
		cli.ShowAppHelp(c)
		return
	}

	out, err := BuildTreeJson(inputJson)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(out)
}

func main() {
	var authors []cli.Author
	// Collaborators, add your name here :)
	authors = append(authors, cli.Author{"Alain Gilbert", "alain.gilbert.15@gmail.com"})

	app := cli.NewApp()
	app.Authors = authors
	app.Version = "0.0.0"
	app.Name = "git2graph"
	app.Usage = "Take a git tree, make a graph structure"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "f, file",
			Usage: "File",
		},
		cli.StringFlag{
			Name:  "j, json",
			Usage: "Json input",
		},
	}
	app.Action = bootstrap
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"crypto/subtle"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

var (
	thePath = flag.String("dir", "/tmp", "working directory")
	git     = flag.String("git", "/usr/bin/git", "path to git")
	addr    = flag.String("addr", ":8124", "binding address to listen on")
	secret  = flag.String("secret", "",
		"Optional secret for authenticating hooks")
)

type commandRequest struct {
	w       http.ResponseWriter
	abspath string
	bg      bool
	after   time.Time
	cmds    []*exec.Cmd
	ch      chan bool
}

var reqch = make(chan commandRequest, 100)
var updates = map[string]time.Time{}

func exists(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}

func maybePanic(err error) {
	if err != nil {
		panic(err)
	}
}

func runCommands(w http.ResponseWriter, bg bool,
	abspath string, cmds []*exec.Cmd) {

	stderr := ioutil.Discard
	stdout := ioutil.Discard

	if !bg {
		stderr = &bytes.Buffer{}
		stdout = &bytes.Buffer{}
	}

	for _, cmd := range cmds {
		if exists(cmd.Path) {
			log.Printf("Running %v in %v", cmd.Args, abspath)
			fmt.Fprintf(stdout, "# Running %v\n", cmd.Args)
			fmt.Fprintf(stderr, "# Running %v\n", cmd.Args)

			cmd.Stdout = stdout
			cmd.Stderr = stderr
			cmd.Dir = abspath
			err := cmd.Run()

			if err != nil {
				log.Printf("Error running %v in %v:  %v",
					cmd.Args, abspath, err)
				if !bg {
					fmt.Fprintf(stderr,
						"\n[gitmirror internal error:  %v]\n", err)
				}
			}

		}
	}

	if !bg {
		fmt.Fprintf(w, "---- stdout ----\n")
		_, err := stdout.(*bytes.Buffer).WriteTo(w)
		maybePanic(err)
		fmt.Fprintf(w, "\n----\n\n\n---- stderr ----\n")
		_, err = stderr.(*bytes.Buffer).WriteTo(w)
		maybePanic(err)
		fmt.Fprintf(w, "\n----\n")
	}
}

func shouldRun(path string, after time.Time) bool {
	if path == "/tmp" {
		return true
	}
	lastRun := updates[path]
	return lastRun.Before(after)
}

func didRun(path string, t time.Time) {
	updates[path] = t
}

func pathRunner(ch chan commandRequest) {
	for r := range ch {
		if shouldRun(r.abspath, r.after) {
			t := time.Now()
			runCommands(r.w, r.bg, r.abspath, r.cmds)
			didRun(r.abspath, t)
		} else {
			log.Printf("Skipping redundant update: %v", r.abspath)
			if !r.bg {
				fmt.Fprintf(r.w, "Redundant request.")
			}
		}
		select {
		case r.ch <- true:
		default:
		}
	}
}

func commandRunner() {
	m := map[string]chan commandRequest{}

	for r := range reqch {
		ch, running := m[r.abspath]
		if !running {
			ch = make(chan commandRequest, 10)
			m[r.abspath] = ch
			go pathRunner(ch)
		}
		ch <- r
	}
}

func queueCommand(w http.ResponseWriter, bg bool,
	abspath string, cmds []*exec.Cmd) chan bool {
	req := commandRequest{w, abspath, bg, time.Now(),
		cmds, make(chan bool)}
	reqch <- req
	return req.ch
}

func updateGit(w http.ResponseWriter, section string,
	bg bool, payload []byte) bool {

	abspath := filepath.Join(*thePath, section)

	if !exists(abspath) {
		if !bg {
			http.Error(w, "Not found", http.StatusNotFound)
		}
		return false
	}

	cmds := []*exec.Cmd{
		exec.Command(*git, "remote", "update", "-p"),
		exec.Command(*git, "gc", "--auto"),
		exec.Command(filepath.Join(abspath, "hooks/post-fetch")),
		exec.Command(filepath.Join(*thePath, "bin/post-fetch")),
	}

	cmds[2].Stdin = bytes.NewBuffer(payload)
	cmds[3].Stdin = bytes.NewBuffer(payload)

	return <-queueCommand(w, bg, abspath, cmds)
}

func getPath(req *http.Request) string {
	return filepath.Clean(filepath.FromSlash(req.URL.Path))[1:]
}

func createRepo(w http.ResponseWriter, section string,
	bg bool, payload []byte) {

	p := struct {
		Repository struct {
			Owner   interface{}
			Private bool
			Name    string
		}
	}{}

	err := json.Unmarshal(payload, &p)
	if err != nil {
		log.Printf("Error unmarshalling data: %v", err)
		http.Error(w, "Error parsing JSON", http.StatusInternalServerError)
		return
	}

	var ownerName string
	switch i := p.Repository.Owner.(type) {
	case string:
		ownerName = i
	case map[string]interface{}:
		ownerName = fmt.Sprintf("%v", i["name"])
	}

	repo := fmt.Sprintf("git://github.com/%v/%v.git",
		ownerName, p.Repository.Name)
	if p.Repository.Private {
		repo = fmt.Sprintf("git@github.com:%v/%v.git",
			ownerName, p.Repository.Name)
	}

	cmds := []*exec.Cmd{
		exec.Command(*git, "clone", "--mirror", "--bare", repo,
			filepath.Join(*thePath, section)),
	}

	if bg {
		w.WriteHeader(201)
	}
	queueCommand(w, true, "/tmp", cmds)
}

func doUpdate(w http.ResponseWriter, path string,
	bg bool, payload []byte) {
	if bg {
		go updateGit(w, path, bg, payload)
		w.WriteHeader(201)
	} else {
		updateGit(w, path, bg, payload)
	}
}

func handleGet(w http.ResponseWriter, req *http.Request, bg bool) {
	path := getPath(req)
	doUpdate(w, path, bg, nil)
}

func parseAndMAC(r io.Reader) (url.Values, error) {
	maxFormSize := int64(1<<63 - 1)
	maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
	r = io.LimitReader(r, maxFormSize+1)
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, err
	}
	log.Printf("Read %v bytes of body", len(b))
	if int64(len(b)) > maxFormSize {
		err = errors.New("http: POST too large")
		return nil, err
	}
	return url.ParseQuery(string(b))
}

func checkHMAC(h hash.Hash, sig string) bool {
	got := fmt.Sprintf("sha1=%x", h.Sum(nil))
	return subtle.ConstantTimeCompare([]byte(got), []byte(sig)) == 1
}

func handlePost(w http.ResponseWriter, req *http.Request, bg bool) {
	mac := hmac.New(sha1.New, []byte(*secret))
	mac.Reset()
	r := io.TeeReader(req.Body, mac)
	form, err := parseAndMAC(r)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	b := []byte(form.Get("payload"))

	if !(*secret == "" || checkHMAC(mac, req.Header.Get("X-Hub-Signature"))) {
		http.Error(w, "not authorized", http.StatusUnauthorized)
		return
	}

	path := getPath(req)
	abspath := filepath.Join(*thePath, path)

	if exists(abspath) {
		doUpdate(w, path, bg, b)
	} else {
		createRepo(w, path, bg, b)
	}
}

func handleReq(w http.ResponseWriter, req *http.Request) {
	backgrounded := req.URL.Query().Get("bg") != "false"

	log.Printf("Handling %v %v", req.Method, req.URL.Path)

	switch req.Method {
	case "GET":
		handleGet(w, req, backgrounded)
	case "POST":
		handlePost(w, req, backgrounded)
	default:
		http.Error(w, "Method not allowed",
			http.StatusMethodNotAllowed)
	}
}

func main() {
	flag.Parse()

	log.SetFlags(log.Lmicroseconds)

	go commandRunner()

	http.HandleFunc("/", handleReq)
	http.HandleFunc("/favicon.ico",
		func(w http.ResponseWriter, req *http.Request) {
			http.Error(w, "No favicon", http.StatusGone)
		})

	log.Fatal(http.ListenAndServe(*addr, nil))
}
<commit_msg>Allow passing repo name as a parameter<commit_after>package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"crypto/subtle"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"time"
)

var (
	thePath = flag.String("dir", "/tmp", "working directory")
	git     = flag.String("git", "/usr/bin/git", "path to git")
	addr    = flag.String("addr", ":8124", "binding address to listen on")
	secret  = flag.String("secret", "",
		"Optional secret for authenticating hooks")
)

type commandRequest struct {
	w       http.ResponseWriter
	abspath string
	bg      bool
	after   time.Time
	cmds    []*exec.Cmd
	ch      chan bool
}

var reqch = make(chan commandRequest, 100)
var updates = map[string]time.Time{}

func exists(path string) bool {
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return false
	}
	return true
}

func maybePanic(err error) {
	if err != nil {
		panic(err)
	}
}

func runCommands(w http.ResponseWriter, bg bool,
	abspath string, cmds []*exec.Cmd) {

	stderr := ioutil.Discard
	stdout := ioutil.Discard

	if !bg {
		stderr = &bytes.Buffer{}
		stdout = &bytes.Buffer{}
	}

	for _, cmd := range cmds {
		if exists(cmd.Path) {
			log.Printf("Running %v in %v", cmd.Args, abspath)
			fmt.Fprintf(stdout, "# Running %v\n", cmd.Args)
			fmt.Fprintf(stderr, "# Running %v\n", cmd.Args)

			cmd.Stdout = stdout
			cmd.Stderr = stderr
			cmd.Dir = abspath
			err := cmd.Run()

			if err != nil {
				log.Printf("Error running %v in %v:  %v",
					cmd.Args, abspath, err)
				if !bg {
					fmt.Fprintf(stderr,
						"\n[gitmirror internal error:  %v]\n", err)
				}
			}

		}
	}

	if !bg {
		fmt.Fprintf(w, "---- stdout ----\n")
		_, err := stdout.(*bytes.Buffer).WriteTo(w)
		maybePanic(err)
		fmt.Fprintf(w, "\n----\n\n\n---- stderr ----\n")
		_, err = stderr.(*bytes.Buffer).WriteTo(w)
		maybePanic(err)
		fmt.Fprintf(w, "\n----\n")
	}
}

func shouldRun(path string, after time.Time) bool {
	if path == "/tmp" {
		return true
	}
	lastRun := updates[path]
	return lastRun.Before(after)
}

func didRun(path string, t time.Time) {
	updates[path] = t
}

func pathRunner(ch chan commandRequest) {
	for r := range ch {
		if shouldRun(r.abspath, r.after) {
			t := time.Now()
			runCommands(r.w, r.bg, r.abspath, r.cmds)
			didRun(r.abspath, t)
		} else {
			log.Printf("Skipping redundant update: %v", r.abspath)
			if !r.bg {
				fmt.Fprintf(r.w, "Redundant request.")
			}
		}
		select {
		case r.ch <- true:
		default:
		}
	}
}

func commandRunner() {
	m := map[string]chan commandRequest{}

	for r := range reqch {
		ch, running := m[r.abspath]
		if !running {
			ch = make(chan commandRequest, 10)
			m[r.abspath] = ch
			go pathRunner(ch)
		}
		ch <- r
	}
}

func queueCommand(w http.ResponseWriter, bg bool,
	abspath string, cmds []*exec.Cmd) chan bool {
	req := commandRequest{w, abspath, bg, time.Now(),
		cmds, make(chan bool)}
	reqch <- req
	return req.ch
}

func updateGit(w http.ResponseWriter, section string,
	bg bool, payload []byte) bool {

	abspath := filepath.Join(*thePath, section)

	if !exists(abspath) {
		if !bg {
			http.Error(w, "Not found", http.StatusNotFound)
		}
		return false
	}

	cmds := []*exec.Cmd{
		exec.Command(*git, "remote", "update", "-p"),
		exec.Command(*git, "gc", "--auto"),
		exec.Command(filepath.Join(abspath, "hooks/post-fetch")),
		exec.Command(filepath.Join(*thePath, "bin/post-fetch")),
	}

	cmds[2].Stdin = bytes.NewBuffer(payload)
	cmds[3].Stdin = bytes.NewBuffer(payload)

	return <-queueCommand(w, bg, abspath, cmds)
}

func getPath(req *http.Request) string {
	if qp := req.URL.Query().Get("name"); qp != "" {
		return filepath.Clean(qp)
	}
	return filepath.Clean(filepath.FromSlash(req.URL.Path))[1:]
}

func createRepo(w http.ResponseWriter, section string,
	bg bool, payload []byte) {

	p := struct {
		Repository struct {
			Owner   interface{}
			Private bool
			Name    string
		}
	}{}

	err := json.Unmarshal(payload, &p)
	if err != nil {
		log.Printf("Error unmarshalling data: %v", err)
		http.Error(w, "Error parsing JSON", http.StatusInternalServerError)
		return
	}

	var ownerName string
	switch i := p.Repository.Owner.(type) {
	case string:
		ownerName = i
	case map[string]interface{}:
		ownerName = fmt.Sprintf("%v", i["name"])
	}

	repo := fmt.Sprintf("git://github.com/%v/%v.git",
		ownerName, p.Repository.Name)
	if p.Repository.Private {
		repo = fmt.Sprintf("git@github.com:%v/%v.git",
			ownerName, p.Repository.Name)
	}

	cmds := []*exec.Cmd{
		exec.Command(*git, "clone", "--mirror", "--bare", repo,
			filepath.Join(*thePath, section)),
	}

	if bg {
		w.WriteHeader(201)
	}
	queueCommand(w, true, "/tmp", cmds)
}

func doUpdate(w http.ResponseWriter, path string,
	bg bool, payload []byte) {
	if bg {
		go updateGit(w, path, bg, payload)
		w.WriteHeader(201)
	} else {
		updateGit(w, path, bg, payload)
	}
}

func handleGet(w http.ResponseWriter, req *http.Request, bg bool) {
	path := getPath(req)
	doUpdate(w, path, bg, nil)
}

func parseAndMAC(r io.Reader) (url.Values, error) {
	maxFormSize := int64(1<<63 - 1)
	maxFormSize = int64(10 << 20) // 10 MB is a lot of text.
	r = io.LimitReader(r, maxFormSize+1)
	b, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, err
	}
	log.Printf("Read %v bytes of body", len(b))
	if int64(len(b)) > maxFormSize {
		err = errors.New("http: POST too large")
		return nil, err
	}
	return url.ParseQuery(string(b))
}

func checkHMAC(h hash.Hash, sig string) bool {
	got := fmt.Sprintf("sha1=%x", h.Sum(nil))
	return subtle.ConstantTimeCompare([]byte(got), []byte(sig)) == 1
}

func handlePost(w http.ResponseWriter, req *http.Request, bg bool) {
	mac := hmac.New(sha1.New, []byte(*secret))
	mac.Reset()
	r := io.TeeReader(req.Body, mac)
	form, err := parseAndMAC(r)
	if err != nil {
		http.Error(w, err.Error(), 500)
		return
	}
	b := []byte(form.Get("payload"))

	if !(*secret == "" || checkHMAC(mac, req.Header.Get("X-Hub-Signature"))) {
		http.Error(w, "not authorized", http.StatusUnauthorized)
		return
	}

	path := getPath(req)
	abspath := filepath.Join(*thePath, path)

	if exists(abspath) {
		doUpdate(w, path, bg, b)
	} else {
		createRepo(w, path, bg, b)
	}
}

func handleReq(w http.ResponseWriter, req *http.Request) {
	backgrounded := req.URL.Query().Get("bg") != "false"

	log.Printf("Handling %v %v", req.Method, req.URL.Path)

	switch req.Method {
	case "GET":
		handleGet(w, req, backgrounded)
	case "POST":
		handlePost(w, req, backgrounded)
	default:
		http.Error(w, "Method not allowed",
			http.StatusMethodNotAllowed)
	}
}

func main() {
	flag.Parse()

	log.SetFlags(log.Lmicroseconds)

	go commandRunner()

	http.HandleFunc("/", handleReq)
	http.HandleFunc("/favicon.ico",
		func(w http.ResponseWriter, req *http.Request) {
			http.Error(w, "No favicon", http.StatusGone)
		})

	log.Fatal(http.ListenAndServe(*addr, nil))
}
<|endoftext|>


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

package gl

// #include <GLES2/gl2.h>
import "C"

import (
	"unsafe"
)

type Buffer C.GLuint
type BufferTarget C.GLenum
type BufferUsage C.GLenum

const (
	ARRAY_BUFFER_BINDING         = C.GL_ARRAY_BUFFER_BINDING
	ELEMENT_ARRAY_BUFFER_BINDING = C.GL_ELEMENT_ARRAY_BUFFER_BINDING

	BUFFER_SIZE  = C.GL_BUFFER_SIZE
	BUFFER_USAGE = C.GL_BUFFER_USAGE

	ARRAY_BUFFER         BufferTarget = C.GL_ARRAY_BUFFER
	ELEMENT_ARRAY_BUFFER              = C.GL_ELEMENT_ARRAY_BUFFER

	STREAM_DRAW  BufferUsage = C.GL_STREAM_DRAW
	STATIC_DRAW              = C.GL_STATIC_DRAW
	DYNAMIC_DRAW             = C.GL_DYNAMIC_DRAW
)

func GenBuffers(buffers []Buffer) {
	C.glGenBuffers(C.GLsizei(len(buffers)), (*C.GLuint)(&buffers[0]))
}

func CreateBuffer() Buffer {
	buffer := Buffer(0)
	C.glGenBuffers(C.GLsizei(1), (*C.GLuint)(&buffer))
	return buffer
}

func BindBuffer(target BufferTarget, buffer Buffer) {
	C.glBindBuffer(C.GLenum(target), C.GLuint(buffer))
}

func BufferDataf(target BufferTarget, data []float32, usage BufferUsage) {
	C.glBufferData(C.GLenum(target), C.GLsizeiptr(unsafe.Sizeof(data[0])*uintptr(len(data))), unsafe.Pointer(&data[0]), C.GLenum(usage))
}

func (b Buffer) Delete() {
	C.glDeleteBuffers(C.GLsizei(1), (*C.GLuint)(&b))
}

// func BufferSubData(target, offset int, data []interface{}) {
// 	C.glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
// }
func DeleteBuffers(buffers []Buffer) {
	C.glDeleteBuffers(C.GLsizei(len(buffers)), (*C.GLuint)(&buffers[0]))
}

// func GetBufferParameteriv(target int, pname int,  params int) {
// 	C.glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
// }
<commit_msg>add BufferSubData<commit_after>// Copyright 2014 Mathias Fiedler
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gl

// #include <GLES2/gl2.h>
import "C"

import (
	"unsafe"
)

type Buffer C.GLuint
type BufferTarget C.GLenum
type BufferUsage C.GLenum

const (
	ARRAY_BUFFER_BINDING         = C.GL_ARRAY_BUFFER_BINDING
	ELEMENT_ARRAY_BUFFER_BINDING = C.GL_ELEMENT_ARRAY_BUFFER_BINDING

	BUFFER_SIZE  = C.GL_BUFFER_SIZE
	BUFFER_USAGE = C.GL_BUFFER_USAGE

	ARRAY_BUFFER         BufferTarget = C.GL_ARRAY_BUFFER
	ELEMENT_ARRAY_BUFFER              = C.GL_ELEMENT_ARRAY_BUFFER

	STREAM_DRAW  BufferUsage = C.GL_STREAM_DRAW
	STATIC_DRAW              = C.GL_STATIC_DRAW
	DYNAMIC_DRAW             = C.GL_DYNAMIC_DRAW
)

func GenBuffers(buffers []Buffer) {
	C.glGenBuffers(C.GLsizei(len(buffers)), (*C.GLuint)(&buffers[0]))
}

func CreateBuffer() Buffer {
	buffer := Buffer(0)
	C.glGenBuffers(C.GLsizei(1), (*C.GLuint)(&buffer))
	return buffer
}

func BindBuffer(target BufferTarget, buffer Buffer) {
	C.glBindBuffer(C.GLenum(target), C.GLuint(buffer))
}

func BufferDataf(target BufferTarget, data []float32, usage BufferUsage) {
	C.glBufferData(C.GLenum(target), C.GLsizeiptr(unsafe.Sizeof(data[0])*uintptr(len(data))), unsafe.Pointer(&data[0]), C.GLenum(usage))
}

func (b Buffer) Delete() {
	C.glDeleteBuffers(C.GLsizei(1), (*C.GLuint)(&b))
}

func DeleteBuffers(buffers []Buffer) {
	C.glDeleteBuffers(C.GLsizei(len(buffers)), (*C.GLuint)(&buffers[0]))
}

func BufferSubData(target BufferTarget, offset int, data []float32) {
	C.glBufferSubData(C.GLenum(target), C.GLintptr(offset), C.GLsizeiptr(unsafe.Sizeof(data[0])*uintptr(len(data))), unsafe.Pointer(&data[0]))
}

// func GetBufferParameteriv(target int, pname int,  params int) {
// 	C.glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
// }
<|endoftext|>


<commit_before>package glib

/*
#include <glib-object.h>
#include <stdlib.h>

extern gboolean _g_source_func(gpointer user_data);
extern void _g_destroy_notify(gpointer user_data);

static void _g_timeout_add_full(gint priority, guint interval, gint64 id) {
	gint64* uid = (gint64*)malloc(sizeof(gint64));
	*uid = id;
	g_timeout_add_full(priority, interval, _g_source_func, (gpointer)uid, _g_destroy_notify);
}

static void _g_idle_add_full(gint priority, gint64 id) {
	gint64* uid = (gint64*)malloc(sizeof(gint64));
	*uid = id;
	g_idle_add_full(priority, _g_source_func, (gpointer)uid, _g_destroy_notify);
}

*/
// #cgo pkg-config: gobject-2.0
import "C"
import "unsafe"
import "runtime"
//import "reflect"
import "github.com/norisatir/go-gtk3/gobject"

type ListClosure func(unsafe.Pointer)
type ConverterFunc func(unsafe.Pointer) interface{}

var _closures map[int64]gobject.ClosureFunc

// GSList {{{
//////////////////////////////

// GSList type
// GSList type which holds C GSList.
// If GC_Free is true, then GC will call g_slist_free on object
// IF GC_FreeFull it true then GC will call g_slist_free_full
// even if GC_Free is true/false (it is ignored).
type GSList struct {
	object         *C.GSList
	GC_Free        bool
	GC_FreeFull    bool
	ConversionFunc ConverterFunc
	DestroyFunc    ListClosure
}

// NewGSList returns new GSList with first element initialized.
// GC_Free and GC_FreeFull will hold default bool values.
func NewGSList() *GSList {
	gl := &GSList{}
	gl.object = C.g_slist_alloc()
	gl.ConversionFunc = nil
	gl.DestroyFunc = nil

	return gl
}

func NewGSListFromNative(list unsafe.Pointer) *GSList {
	gl := &GSList{}
	gl.object = (*C.GSList)(list)
	gl.ConversionFunc = nil
	gl.DestroyFunc = nil

	return gl
}

// GSList finalizer
func GSListFinalizer(gsl *GSList) {
	runtime.SetFinalizer(gsl, func(gsl *GSList) {
		if gsl.GC_FreeFull {
			gsl.FreeFull()
			return
		}

		if gsl.GC_Free {
			gsl.Free()
		}
	})
}

func (self *GSList) Free() {
	C.g_slist_free(self.object)
}

func (self *GSList) FreeFull() {
	if self.DestroyFunc == nil {
		return
	}
	var numElements int = int(self.Length())

	for i := 0; i < numElements; i++ {
		el := C.g_slist_nth_data(self.object, C.guint(i))
		self.DestroyFunc(unsafe.Pointer(el))
	}
}

func (self *GSList) NthData(n uint) interface{} {
	data := C.g_slist_nth_data(self.object, C.guint(n))

	if data == nil {
		return nil
	}

	if self.ConversionFunc != nil {
		return self.ConversionFunc(unsafe.Pointer(data))
	}
	return data
}

func (self *GSList) Length() uint {
	return uint(C.g_slist_length(self.object))
}

func (self *GSList) Foreach(f interface{}, data ...interface{}) {
	// Create id and closure
	cl, _ := gobject.CreateCustomClosure(f, data...)
	listLength := int(self.Length())

	for i := 0; i < listLength; i++ {
		data := self.NthData(uint(i))
		if data != nil {
			cl([]interface{}{data})
		}
	}
}

//////////////////////////////
// End GSList
////////////////////////////// }}}

// GList {{{
//////////////////////////////

// GList type
// GList type which holds C GList.
// If GC_Free is true, then GC will call g_list_free on object
// IF GC_FreeFull it true then GC will call g_list_free_full
// even if GC_Free is true/false (it is ignored).
type GList struct {
	object         *C.GList
	GC_Free        bool
	GC_FreeFull    bool
	ConversionFunc ConverterFunc
	DestroyFunc    ListClosure
}

// NewGList returns new GList with first element initialized.
// GC_Free and GC_FreeFull will hold default bool values.
func NewGList() *GList {
	gl := &GList{}
	gl.object = C.g_list_alloc()
	gl.ConversionFunc = nil
	gl.DestroyFunc = nil

	return gl
}

func NewGListFromNative(list unsafe.Pointer) *GList {
	gl := &GList{}
	gl.object = (*C.GList)(list)
	gl.ConversionFunc = nil
	gl.DestroyFunc = nil

	return gl
}

// GList finalizer
func GListFinalizer(gl *GList) {
	runtime.SetFinalizer(gl, func(gl *GSList) {
		if gl.GC_FreeFull {
			gl.FreeFull()
			return
		}

		if gl.GC_Free {
			gl.Free()
		}
	})
}

func (self *GList) Free() {
	C.g_list_free(self.object)
}

func (self *GList) FreeFull() {
	if self.DestroyFunc == nil {
		return
	}
	var numElements int = int(self.Length())

	for i := 0; i < numElements; i++ {
		el := C.g_list_nth_data(self.object, C.guint(i))
		self.DestroyFunc(unsafe.Pointer(el))
	}
	C.g_list_free(self.object)
}

func (self *GList) NthData(n uint) interface{} {
	data := C.g_list_nth_data(self.object, C.guint(n))

	if data == nil {
		return nil
	}

	if self.ConversionFunc != nil {
		return self.ConversionFunc(unsafe.Pointer(data))
	}
	return data
}

func (self *GList) Length() uint {
	return uint(C.g_list_length(self.object))
}

func (self *GList) Foreach(f interface{}, data ...interface{}) {
	// Create id and closure
	cl, _ := gobject.CreateCustomClosure(f, data...)
	listLength := int(self.Length())

	for i := 0; i < listLength; i++ {
		data := self.NthData(uint(i))
		if data != nil {
			cl([]interface{}{data})
		}
	}
}
//////////////////////////////
// End GList
////////////////////////////// }}}

func GTimeoutAddFull(priority int, interval uint, callback interface{}, data ...interface{}) {
	cl, id := gobject.CreateCustomClosure(callback, data...)
	_closures[id] = cl
	C._g_timeout_add_full(C.gint(priority), C.guint(interval), C.gint64(id))
}

func GIdleAddFull(priority int, callback interface{}, data ...interface{}) {
	cl, id := gobject.CreateCustomClosure(callback, data...)
	_closures[id] = cl
	C._g_idle_add_full(C.gint(priority), C.gint64(id))
}

// Exported functions
//export _g_source_func
func _g_source_func(user_data unsafe.Pointer) C.gboolean {
	id := *((*C.gint64)(user_data))
	var res bool

	if f, ok := _closures[int64(id)]; ok {
		res = f([]interface{}{})
	}
	b := gobject.GBool(res)
	defer b.Free()
	return *((*C.gboolean)(b.GetPtr()))
}

//export _g_destroy_notify
func _g_destroy_notify(user_data unsafe.Pointer) {
	id := *((*C.gint64)(user_data))
	if _, ok := _closures[int64(id)]; ok {
		delete(_closures, int64(id))
	}
	C.free(user_data)
}

var GPriority gPriority

type gPriority struct {
	HIGH         int
	DEFAULT      int
	HIGH_IDLE    int
	DEFAULT_IDLE int
	LOW          int
}

func init() {
	_closures = make(map[int64]gobject.ClosureFunc)

	// Initialize GPriority struct
	GPriority.HIGH = -100
	GPriority.DEFAULT = 0
	GPriority.HIGH_IDLE = 100
	GPriority.DEFAULT_IDLE = 200
	GPriority.LOW = 300
}
<commit_msg>Added ToNative method to GSList and GList.<commit_after>package glib

/*
#include <glib-object.h>
#include <stdlib.h>

extern gboolean _g_source_func(gpointer user_data);
extern void _g_destroy_notify(gpointer user_data);

static void _g_timeout_add_full(gint priority, guint interval, gint64 id) {
	gint64* uid = (gint64*)malloc(sizeof(gint64));
	*uid = id;
	g_timeout_add_full(priority, interval, _g_source_func, (gpointer)uid, _g_destroy_notify);
}

static void _g_idle_add_full(gint priority, gint64 id) {
	gint64* uid = (gint64*)malloc(sizeof(gint64));
	*uid = id;
	g_idle_add_full(priority, _g_source_func, (gpointer)uid, _g_destroy_notify);
}

*/
// #cgo pkg-config: gobject-2.0
import "C"
import "unsafe"
import "runtime"
//import "reflect"
import "github.com/norisatir/go-gtk3/gobject"

type ListClosure func(unsafe.Pointer)
type ConverterFunc func(unsafe.Pointer) interface{}

var _closures map[int64]gobject.ClosureFunc

// GSList {{{
//////////////////////////////

// GSList type
// GSList type which holds C GSList.
// If GC_Free is true, then GC will call g_slist_free on object
// IF GC_FreeFull it true then GC will call g_slist_free_full
// even if GC_Free is true/false (it is ignored).
type GSList struct {
	object         *C.GSList
	GC_Free        bool
	GC_FreeFull    bool
	ConversionFunc ConverterFunc
	DestroyFunc    ListClosure
}

// NewGSList returns new GSList with first element initialized.
// GC_Free and GC_FreeFull will hold default bool values.
func NewGSList() *GSList {
	gl := &GSList{}
	gl.object = nil
	gl.ConversionFunc = nil
	gl.DestroyFunc = nil

	return gl
}

func NewGSListFromNative(list unsafe.Pointer) *GSList {
	gl := &GSList{}
	gl.object = (*C.GSList)(list)
	gl.ConversionFunc = nil
	gl.DestroyFunc = nil

	return gl
}

// GSList finalizer
func GSListFinalizer(gsl *GSList) {
	runtime.SetFinalizer(gsl, func(gsl *GSList) {
		if gsl.GC_FreeFull {
			gsl.FreeFull()
			return
		}

		if gsl.GC_Free {
			gsl.Free()
		}
	})
}

func (self *GSList) ToNative() unsafe.Pointer {
	return unsafe.Pointer(self.object)
}

func (self *GSList) Free() {
	C.g_slist_free(self.object)
}

func (self *GSList) FreeFull() {
	if self.DestroyFunc == nil {
		return
	}
	var numElements int = int(self.Length())

	for i := 0; i < numElements; i++ {
		el := C.g_slist_nth_data(self.object, C.guint(i))
		self.DestroyFunc(unsafe.Pointer(el))
	}
	self.Free()
}

func (self *GSList) NthData(n uint) interface{} {
	data := C.g_slist_nth_data(self.object, C.guint(n))

	if data == nil {
		return nil
	}

	if self.ConversionFunc != nil {
		return self.ConversionFunc(unsafe.Pointer(data))
	}
	return data
}

func (self *GSList) Length() uint {
	return uint(C.g_slist_length(self.object))
}

func (self *GSList) Foreach(f interface{}, data ...interface{}) {
	// Create id and closure
	cl, _ := gobject.CreateCustomClosure(f, data...)
	listLength := int(self.Length())

	for i := 0; i < listLength; i++ {
		data := self.NthData(uint(i))
		if data != nil {
			cl([]interface{}{data})
		}
	}
}

//////////////////////////////
// End GSList
////////////////////////////// }}}

// GList {{{
//////////////////////////////

// GList type
// GList type which holds C GList.
// If GC_Free is true, then GC will call g_list_free on object
// IF GC_FreeFull it true then GC will call g_list_free_full
// even if GC_Free is true/false (it is ignored).
type GList struct {
	object         *C.GList
	GC_Free        bool
	GC_FreeFull    bool
	ConversionFunc ConverterFunc
	DestroyFunc    ListClosure
}

// NewGList returns new GList with first element initialized.
// GC_Free and GC_FreeFull will hold default bool values.
func NewGList() *GList {
	gl := &GList{}
	gl.object = nil
	gl.ConversionFunc = nil
	gl.DestroyFunc = nil

	return gl
}

func NewGListFromNative(list unsafe.Pointer) *GList {
	gl := &GList{}
	gl.object = (*C.GList)(list)
	gl.ConversionFunc = nil
	gl.DestroyFunc = nil

	return gl
}

// GList finalizer
func GListFinalizer(gl *GList) {
	runtime.SetFinalizer(gl, func(gl *GSList) {
		if gl.GC_FreeFull {
			gl.FreeFull()
			return
		}

		if gl.GC_Free {
			gl.Free()
		}
	})
}

func (self *GList) ToNative() unsafe.Pointer {
	return unsafe.Pointer(self.object)
}

func (self *GList) Free() {
	C.g_list_free(self.object)
}

func (self *GList) FreeFull() {
	if self.DestroyFunc == nil {
		return
	}
	var numElements int = int(self.Length())

	for i := 0; i < numElements; i++ {
		el := C.g_list_nth_data(self.object, C.guint(i))
		self.DestroyFunc(unsafe.Pointer(el))
	}
	self.Free()
}

func (self *GList) NthData(n uint) interface{} {
	data := C.g_list_nth_data(self.object, C.guint(n))

	if data == nil {
		return nil
	}

	if self.ConversionFunc != nil {
		return self.ConversionFunc(unsafe.Pointer(data))
	}
	return data
}

func (self *GList) Length() uint {
	return uint(C.g_list_length(self.object))
}

func (self *GList) Foreach(f interface{}, data ...interface{}) {
	// Create id and closure
	cl, _ := gobject.CreateCustomClosure(f, data...)
	listLength := int(self.Length())

	for i := 0; i < listLength; i++ {
		data := self.NthData(uint(i))
		if data != nil {
			cl([]interface{}{data})
		}
	}
}
//////////////////////////////
// End GList
////////////////////////////// }}}

func GTimeoutAddFull(priority int, interval uint, callback interface{}, data ...interface{}) {
	cl, id := gobject.CreateCustomClosure(callback, data...)
	_closures[id] = cl
	C._g_timeout_add_full(C.gint(priority), C.guint(interval), C.gint64(id))
}

func GIdleAddFull(priority int, callback interface{}, data ...interface{}) {
	cl, id := gobject.CreateCustomClosure(callback, data...)
	_closures[id] = cl
	C._g_idle_add_full(C.gint(priority), C.gint64(id))
}

// Exported functions
//export _g_source_func
func _g_source_func(user_data unsafe.Pointer) C.gboolean {
	id := *((*C.gint64)(user_data))
	var res bool

	if f, ok := _closures[int64(id)]; ok {
		res = f([]interface{}{})
	}
	b := gobject.GBool(res)
	defer b.Free()
	return *((*C.gboolean)(b.GetPtr()))
}

//export _g_destroy_notify
func _g_destroy_notify(user_data unsafe.Pointer) {
	id := *((*C.gint64)(user_data))
	if _, ok := _closures[int64(id)]; ok {
		delete(_closures, int64(id))
	}
	C.free(user_data)
}

var GPriority gPriority

type gPriority struct {
	HIGH         int
	DEFAULT      int
	HIGH_IDLE    int
	DEFAULT_IDLE int
	LOW          int
}

func init() {
	_closures = make(map[int64]gobject.ClosureFunc)

	// Initialize GPriority struct
	GPriority.HIGH = -100
	GPriority.DEFAULT = 0
	GPriority.HIGH_IDLE = 100
	GPriority.DEFAULT_IDLE = 200
	GPriority.LOW = 300
}
<|endoftext|>


<commit_before>/*
Get all colors for 255-colors terminal:
	gommand 'for i := 0; i < 256; i++ {fmt.Println(i, ansi.ColorCode(strconv.Itoa(i)) + "String" + ansi.ColorCode("reset"))}'
*/
package main

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

	"github.com/mgutz/ansi"
	"golang.org/x/tools/cover"
)

const usageMessage = `go-carpet - show coverage for Go source files

usage: go-carpet [dirs]`

func getDirsWithTests(roots ...string) []string {
	if len(roots) == 0 {
		roots = []string{"."}
	}

	dirs := map[string]struct{}{}
	for _, root := range roots {
		filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
			if strings.HasSuffix(path, "_test.go") {
				dirs[filepath.Dir(path)] = struct{}{}
			}
			return nil
		})
	}

	result := make([]string, 0, len(dirs))
	for dir := range dirs {
		result = append(result, "./"+dir)
	}
	return result
}

func readFile(fileName string) (result []byte, err error) {
	fileReader, err := os.Open(fileName)
	if err != nil {
		return result, err
	}
	defer fileReader.Close()

	result, err = ioutil.ReadAll(fileReader)
	return result, err
}

func printCoverForDir(path string, coverFileName string, stdOut io.Writer) {
	osExec := exec.Command("go", "test", "-coverprofile="+coverFileName, "-covermode=count", path)
	osExec.Stderr = os.Stderr
	err := osExec.Run()
	if err != nil {
		log.Fatalf("exec go test: %s", err)
	}

	coverProfile, err := cover.ParseProfiles(coverFileName)
	if err != nil {
		log.Fatal(err)
	}

	for _, fileProfile := range coverProfile {
		fileName := ""
		if strings.HasPrefix(fileProfile.FileName, "_") {
			// absolute path
			fileName = strings.TrimLeft(fileProfile.FileName, "_")
		} else {
			// file in GOPATH
			fileName = os.Getenv("GOPATH") + "/src/" + fileProfile.FileName
		}
		if _, err := os.Stat(fileName); os.IsNotExist(err) {
			fmt.Printf("File '%s' is not exists\n", fileName)
			continue
		}

		fileBytes, err := readFile(fileName)
		if err != nil {
			log.Fatal(err)
		}

		fileNameDisplay := fileProfile.FileName
		stdOut.Write([]byte(ansi.ColorCode("yellow") + fileNameDisplay + ansi.ColorCode("reset") + "\n" +
			ansi.ColorCode("black+h") + strings.Repeat("~", len(fileNameDisplay)) + ansi.ColorCode("reset") + "\n"))

		boundaries := fileProfile.Boundaries(fileBytes)
		curOffset := 0
		for _, boundary := range boundaries {
			if boundary.Offset > curOffset {
				stdOut.Write(fileBytes[curOffset:boundary.Offset])
			}
			switch {
			case boundary.Start && boundary.Count > 0:
				stdOut.Write([]byte(ansi.ColorCode("green")))
			case boundary.Start && boundary.Count == 0:
				stdOut.Write([]byte(ansi.ColorCode("red")))
			case !boundary.Start:
				stdOut.Write([]byte(ansi.ColorCode("reset")))
			}

			curOffset = boundary.Offset
		}
		if curOffset < len(fileBytes) {
			stdOut.Write(fileBytes[curOffset:len(fileBytes)])
		}
		stdOut.Write([]byte("\n"))
	}
}

func main() {
	flag.Usage = func() {
		fmt.Println(usageMessage)
		flag.PrintDefaults()
		os.Exit(0)
	}
	flag.Parse()
	testDirs := flag.Args()

	tmpDir, err := ioutil.TempDir("", "go-carpet-")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(tmpDir)

	coverFileName := filepath.Join(tmpDir, "coverage.out")
	stdOut := getColorWriter()

	if len(testDirs) > 0 {
		testDirs = getDirsWithTests(testDirs...)
	} else {
		testDirs = getDirsWithTests(".")
	}
	for _, path := range testDirs {
		printCoverForDir(path, coverFileName, stdOut)
	}
}
<commit_msg>Refactoring printCoverForDir()<commit_after>/*
Get all colors for 255-colors terminal:
	gommand 'for i := 0; i < 256; i++ {fmt.Println(i, ansi.ColorCode(strconv.Itoa(i)) + "String" + ansi.ColorCode("reset"))}'
*/
package main

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

	"github.com/mgutz/ansi"
	"golang.org/x/tools/cover"
)

const usageMessage = `go-carpet - show coverage for Go source files

usage: go-carpet [dirs]`

func getDirsWithTests(roots ...string) []string {
	if len(roots) == 0 {
		roots = []string{"."}
	}

	dirs := map[string]struct{}{}
	for _, root := range roots {
		filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
			if strings.HasSuffix(path, "_test.go") {
				dirs[filepath.Dir(path)] = struct{}{}
			}
			return nil
		})
	}

	result := make([]string, 0, len(dirs))
	for dir := range dirs {
		result = append(result, "./"+dir)
	}
	return result
}

func readFile(fileName string) (result []byte, err error) {
	fileReader, err := os.Open(fileName)
	if err != nil {
		return result, err
	}
	defer fileReader.Close()

	result, err = ioutil.ReadAll(fileReader)
	return result, err
}

func getCoverForDir(path string, coverFileName string) (result []byte, err error) {
	osExec := exec.Command("go", "test", "-coverprofile="+coverFileName, "-covermode=count", path)
	osExec.Stderr = os.Stderr
	err = osExec.Run()
	if err != nil {
		return result, err
	}

	coverProfile, err := cover.ParseProfiles(coverFileName)
	if err != nil {
		return result, err
	}

	for _, fileProfile := range coverProfile {
		fileName := ""
		if strings.HasPrefix(fileProfile.FileName, "_") {
			// absolute path
			fileName = strings.TrimLeft(fileProfile.FileName, "_")
		} else {
			// file in GOPATH
			fileName = os.Getenv("GOPATH") + "/src/" + fileProfile.FileName
		}
		if _, err := os.Stat(fileName); os.IsNotExist(err) {
			fmt.Printf("File '%s' is not exists\n", fileName)
			continue
		}

		fileBytes, err := readFile(fileName)
		if err != nil {
			return result, err
		}

		fileNameDisplay := fileProfile.FileName

		result = append(result, []byte(ansi.ColorCode("yellow")+fileNameDisplay+ansi.ColorCode("reset")+"\n"+
			ansi.ColorCode("black+h")+strings.Repeat("~", len(fileNameDisplay))+ansi.ColorCode("reset")+"\n")...)

		boundaries := fileProfile.Boundaries(fileBytes)
		curOffset := 0
		for _, boundary := range boundaries {
			if boundary.Offset > curOffset {
				result = append(result, fileBytes[curOffset:boundary.Offset]...)
			}
			switch {
			case boundary.Start && boundary.Count > 0:
				result = append(result, []byte(ansi.ColorCode("green"))...)
			case boundary.Start && boundary.Count == 0:
				result = append(result, []byte(ansi.ColorCode("red"))...)
			case !boundary.Start:
				result = append(result, []byte(ansi.ColorCode("reset"))...)
			}

			curOffset = boundary.Offset
		}
		if curOffset < len(fileBytes) {
			result = append(result, fileBytes[curOffset:len(fileBytes)]...)
		}
		result = append(result, []byte("\n")...)
	}

	return result, err
}

func main() {
	flag.Usage = func() {
		fmt.Println(usageMessage)
		flag.PrintDefaults()
		os.Exit(0)
	}
	flag.Parse()
	testDirs := flag.Args()

	tmpDir, err := ioutil.TempDir("", "go-carpet-")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(tmpDir)

	coverFileName := filepath.Join(tmpDir, "coverage.out")
	stdOut := getColorWriter()

	if len(testDirs) > 0 {
		testDirs = getDirsWithTests(testDirs...)
	} else {
		testDirs = getDirsWithTests(".")
	}
	for _, path := range testDirs {
		coverInBytes, err := getCoverForDir(path, coverFileName)
		if err != nil {
			log.Print(err)
		}
		stdOut.Write(coverInBytes)
	}
}
<|endoftext|>


<commit_before>package sxchange

import (
	"context"
	"errors"
	"fmt"
	"io"
	"log"
	"net"
	"sync"
	"time"
	"unsafe"
)

const (
	verHI = 1
	verLO = 0
)

// CB type for callback function for each type of transfered data
type CB func([]byte, *Connection)

// DataTypeCB describes
type DataTypeCB struct {
	SizeBytes int8  // -1 for fixed size, 0 for no data (ping?), 1 for 0-255 bytes, 2 for 0-65535 bytes...
	FixedSize int32 // if some struct has fixed fize no other header needed
	Callback  CB    // which function to run after data received
}

// Connection informaion both for client or server
type Connection struct {
	conn         *net.TCPConn         // real connection
	writeMutex   sync.Mutex           // we need to lock on write operations
	Types        map[uint8]DataTypeCB // map of type->params&callback
	KeepAlive    time.Duration        // tcp keep-alive
	ReadTimeout  time.Duration        // we need to receive new message at least once per this duration
	WriteTimeout time.Duration        // maximal duration for every write operation
	MaxSize      uint32               // maximum number of bytes for one record/message
	Ctx          context.Context      // context for some values like server id
	CloseChan    chan interface{}     // channel for closing incoming messages circle
}

const (
	initialPacketSize = 1292 // we need to compare it manualy to be sure that compiler doesn't change aligment!
)

type initialPacket struct {
	Header    [8]uint8 // sxchngXY where X.Y is version of protocol
	MaxSize   uint32
	SizeBytes [256]int8
	FixedSize [256]int32
}

func readAll(conn *net.TCPConn, buf []byte, size int, timeout time.Duration) error {

	totalDeadline := time.Now().Add(timeout)
	conn.SetReadDeadline(totalDeadline)
	i, err := io.ReadFull(conn, buf[:size])
	if nil != err {
		return err
	}
	if i != size {
		return errors.New("Partial read")
	}

	return nil
}

func writeAll(conn *net.TCPConn, buf []byte, size int, timeout time.Duration) error {
	totalDeadline := time.Now().Add(timeout)
	conn.SetWriteDeadline(totalDeadline)
	i, err := conn.Write(buf[:size])

	if nil != err {
		return err
	}
	if i != size {
		return errors.New("Partial write")
	}

	return nil
}

func (c *Connection) initConnection() error {
	if c.KeepAlive != 0 {
		c.conn.SetKeepAlivePeriod(c.KeepAlive)
		c.conn.SetKeepAlive(true)
	}

	// initial packets exchange
	initial := c.prepareInitialPacket()
	initialBuf := (*[initialPacketSize]byte)(unsafe.Pointer(&initial))[:]
	received := initialPacket{}
	receivedBuf := (*[initialPacketSize]byte)(unsafe.Pointer(&received))[:]

	// send out version
	err := writeAll(c.conn, initialBuf, initialPacketSize, c.WriteTimeout)
	if nil != err {
		return err
	}

	err = readAll(c.conn, receivedBuf, initialPacketSize, c.ReadTimeout)
	if nil != err {
		return err
	}

	if received.Header != initial.Header {
		return errors.New("HS error - different protocol version")
	}

	if received.MaxSize != initial.MaxSize {
		return errors.New("HS error - different message maximal size")
	}

	if (received.FixedSize != initial.FixedSize) || (received.MaxSize != received.MaxSize) {
		return errors.New("HS error - different set of datatypes")
	}

	return nil
}

// internal run function
func (c *Connection) run() error {

	defer c.conn.Close()

	var (
		sbuf [4]byte
		t    [1]byte
		msg  = make([]byte, 0, c.MaxSize)
	)

	for {

		select {
		case <-c.CloseChan:
			return nil
		default:
		}

		c.conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
		i, err := c.conn.Read(t[:])
		if nil != err {
			return err
		}
		if 0 == i { // TODO: check if this is an error?..
			continue
		}

		dt, ok := c.Types[t[0]]

		if !ok {
			return fmt.Errorf("Structure type %d is not defined", t[0])
		}

		var size2read int
		if dt.SizeBytes > 0 {
			err = readAll(c.conn, sbuf[0:dt.SizeBytes], int(dt.SizeBytes), c.ReadTimeout)
			if nil != err {
				return err
			}
		}

		switch dt.SizeBytes {
		case -1:
			size2read = int(dt.FixedSize)
		case 0:
			size2read = 0
		case 1:
			size2read = int(sbuf[0])
		case 2:
			size2read = int(sbuf[0]) | (int(sbuf[1]) << 8)
		case 3:
			size2read = int(sbuf[0]) | (int(sbuf[1]) << 8) | (int(sbuf[2]) << 16)
		default:
			return fmt.Errorf("Structure type %d has invalid SizeBytes setting (%d)", t[0], dt.SizeBytes)
		}

		err = readAll(c.conn, msg, size2read, c.ReadTimeout)
		if nil != err {
			return err
		}

		// one more check on done channel - we don't want to call callback after it has been closed
		select {
		case <-c.CloseChan:
			return nil
		default:
		}

		// we need to allow types that only can be send by one of the side, but also defined
		if nil != dt.Callback {
			dt.Callback(msg[0:size2read], c)
		}
	}
}

// WriteMsg creates header and then writes msg buffer via TCP connection
func (c *Connection) WriteMsg(msgType uint8, msg []byte) error {

	dt, ok := c.Types[msgType]
	if !ok {
		return fmt.Errorf("Unknown msg type %d", msgType)
	}

	header := [5]byte{}
	header[0] = msgType

	size2write := 0
	headerSize := 1

	switch dt.SizeBytes {
	case -1:
		size2write = int(dt.FixedSize)
	case 0:
		size2write = 0
	case 1:
		if len(msg) > 255 {
			return fmt.Errorf("Structure type %d has 1-byte size header but %d bytes givven", msgType, len(msg))
		}
		header[1] = byte(len(msg))
		size2write = len(msg)
		headerSize = 2
	case 2:
		if len(msg) > 255*255 {
			return fmt.Errorf("Structure type %d has 2-byte size header but %d bytes givven", msgType, len(msg))
		}
		header[1] = byte(len(msg) & 0xff)
		header[2] = byte((len(msg) & 0xff00) >> 8)
		size2write = len(msg)
		headerSize = 3

	case 3:
		if len(msg) > 255*255*255 {
			return fmt.Errorf("Structure type %d has 2-byte size header but %d bytes givven", msgType, len(msg))
		}
		header[1] = byte(len(msg) & 0xff)
		header[2] = byte((len(msg) & 0xff00) >> 8)
		header[3] = byte((len(msg) & 0xff0000) >> 16)
		size2write = len(msg)
		headerSize = 4

	default:
		return fmt.Errorf("Structure type %d has invalid SizeBytes setting (%d)", msgType, dt.SizeBytes)
	}

	if size2write > len(msg) {
		return fmt.Errorf("Unable to write %d bytes for structure %d, have only %d in buffer", msgType, size2write, len(msg))
	}

	c.writeMutex.Lock()
	defer c.writeMutex.Unlock()

	err := writeAll(c.conn, header[:], headerSize, c.WriteTimeout)
	if nil != err {
		return err
	}

	err = writeAll(c.conn, msg, size2write, c.WriteTimeout)
	if nil != err {
		return err
	}

	return nil
}

// Remote address retrive
func (c *Connection) Remote() net.Addr {
	if nil == c.conn {
		return nil
	}

	return c.conn.RemoteAddr()
}

func (c *Connection) prepareInitialPacket() initialPacket {
	result := initialPacket{MaxSize: c.MaxSize, Header: [8]byte{'s', 'x', 'c', 'h', 'n', 'g', verHI, verLO}}

	for i := 0; i < 256; i++ {
		result.FixedSize[i] = c.Types[uint8(i)].FixedSize
		result.SizeBytes[i] = c.Types[uint8(i)].SizeBytes
	}

	return result
}

func init() {
	if initialPacketSize != unsafe.Sizeof(initialPacket{}) {
		log.Fatalln("Golang uses different aligment withing structure, please modify sxchnge code!")
	}
}
<commit_msg>Add checksums for data of messages<commit_after>package sxchange

import (
	"context"
	"errors"
	"fmt"
	"hash/crc32"
	"io"
	"log"
	"net"
	"sync"
	"time"
	"unsafe"
)

const (
	verHI = 1
	verLO = 1
)

var (
	crc32q = crc32.MakeTable(crc32.Koopman)
)

// CB type for callback function for each type of transfered data
type CB func([]byte, *Connection)

// DataTypeCB describes
type DataTypeCB struct {
	SizeBytes int8  // -1 for fixed size, 0 for no data (ping?), 1 for 0-255 bytes, 2 for 0-65535 bytes...
	FixedSize int32 // if some struct has fixed fize no other header needed
	Callback  CB    // which function to run after data received
}

// Connection informaion both for client or server
type Connection struct {
	conn         *net.TCPConn         // real connection
	writeMutex   sync.Mutex           // we need to lock on write operations
	Types        map[uint8]DataTypeCB // map of type->params&callback
	KeepAlive    time.Duration        // tcp keep-alive
	ReadTimeout  time.Duration        // we need to receive new message at least once per this duration
	WriteTimeout time.Duration        // maximal duration for every write operation
	MaxSize      uint32               // maximum number of bytes for one record/message
	Ctx          context.Context      // context for some values like server id
	CloseChan    chan interface{}     // channel for closing incoming messages circle
}

const (
	initialPacketSize = 1292 // we need to compare it manualy to be sure that compiler doesn't change aligment!
)

type initialPacket struct {
	Header    [8]uint8 // sxchngXY where X.Y is version of protocol
	MaxSize   uint32
	SizeBytes [256]int8
	FixedSize [256]int32
}

func readAll(conn *net.TCPConn, buf []byte, size int, timeout time.Duration) error {

	totalDeadline := time.Now().Add(timeout)
	conn.SetReadDeadline(totalDeadline)
	i, err := io.ReadFull(conn, buf[:size])
	if nil != err {
		return err
	}
	if i != size {
		return errors.New("Partial read")
	}

	return nil
}

func writeAll(conn *net.TCPConn, buf []byte, size int, timeout time.Duration) error {
	totalDeadline := time.Now().Add(timeout)
	conn.SetWriteDeadline(totalDeadline)
	i, err := conn.Write(buf[:size])

	if nil != err {
		return err
	}
	if i != size {
		return errors.New("Partial write")
	}

	return nil
}

func (c *Connection) initConnection() error {
	if c.KeepAlive != 0 {
		c.conn.SetKeepAlivePeriod(c.KeepAlive)
		c.conn.SetKeepAlive(true)
	}

	// initial packets exchange
	initial := c.prepareInitialPacket()
	initialBuf := (*[initialPacketSize]byte)(unsafe.Pointer(&initial))[:]
	received := initialPacket{}
	receivedBuf := (*[initialPacketSize]byte)(unsafe.Pointer(&received))[:]

	// send out version
	err := writeAll(c.conn, initialBuf, initialPacketSize, c.WriteTimeout)
	if nil != err {
		return err
	}

	err = readAll(c.conn, receivedBuf, initialPacketSize, c.ReadTimeout)
	if nil != err {
		return err
	}

	if received.Header != initial.Header {
		return errors.New("HS error - different protocol version")
	}

	if received.MaxSize != initial.MaxSize {
		return errors.New("HS error - different message maximal size")
	}

	if (received.FixedSize != initial.FixedSize) || (received.MaxSize != received.MaxSize) {
		return errors.New("HS error - different set of datatypes")
	}

	return nil
}

// internal run function
func (c *Connection) run() error {

	defer c.conn.Close()

	var (
		sbuf [4]byte
		t    [1]byte
		msg  = make([]byte, 0, c.MaxSize)
		crcI uint32
		crcB = (*[4]byte)(unsafe.Pointer(&crcI))
	)

	for {

		select {
		case <-c.CloseChan:
			return nil
		default:
		}

		c.conn.SetReadDeadline(time.Now().Add(c.ReadTimeout))
		i, err := c.conn.Read(t[:])
		if nil != err {
			return err
		}
		if 0 == i { // TODO: check if this is an error?..
			continue
		}

		dt, ok := c.Types[t[0]]

		if !ok {
			return fmt.Errorf("Structure type %d is not defined", t[0])
		}

		var size2read int
		if dt.SizeBytes > 0 {
			err = readAll(c.conn, sbuf[0:dt.SizeBytes], int(dt.SizeBytes), c.ReadTimeout)
			if nil != err {
				return err
			}
		}

		switch dt.SizeBytes {
		case -1:
			size2read = int(dt.FixedSize)
		case 0:
			size2read = 0
		case 1:
			size2read = int(sbuf[0])
		case 2:
			size2read = int(sbuf[0]) | (int(sbuf[1]) << 8)
		case 3:
			size2read = int(sbuf[0]) | (int(sbuf[1]) << 8) | (int(sbuf[2]) << 16)
		default:
			return fmt.Errorf("Structure type %d has invalid SizeBytes setting (%d)", t[0], dt.SizeBytes)
		}

		err = readAll(c.conn, msg, size2read, c.ReadTimeout)
		if nil != err {
			return err
		}

		// one more check on done channel - we don't want to call callback after it has been closed
		select {
		case <-c.CloseChan:
			return nil
		default:
		}

		if 0 != size2read {
			err = readAll(c.conn, (*crcB)[:], 4, c.ReadTimeout)
			if nil != err {
				return err
			}
			if crc32.Checksum(msg[0:size2read], crc32q) != crcI {
				return errors.New("crc failed on read")
			}
		}

		// we need to allow types that only can be send by one of the side, but also defined
		if nil != dt.Callback {
			dt.Callback(msg[0:size2read], c)
		}
	}
}

// WriteMsg creates header and then writes msg buffer via TCP connection
func (c *Connection) WriteMsg(msgType uint8, msg []byte) error {

	dt, ok := c.Types[msgType]
	if !ok {
		return fmt.Errorf("Unknown msg type %d", msgType)
	}

	var (
		crcI uint32
		crcB = (*[4]byte)(unsafe.Pointer(&crcI))
	)

	header := [5]byte{}
	header[0] = msgType

	size2write := 0
	headerSize := 1

	switch dt.SizeBytes {
	case -1:
		size2write = int(dt.FixedSize)
	case 0:
		size2write = 0
	case 1:
		if len(msg) > 255 {
			return fmt.Errorf("Structure type %d has 1-byte size header but %d bytes givven", msgType, len(msg))
		}
		header[1] = byte(len(msg))
		size2write = len(msg)
		headerSize = 2
	case 2:
		if len(msg) > 255*255 {
			return fmt.Errorf("Structure type %d has 2-byte size header but %d bytes givven", msgType, len(msg))
		}
		header[1] = byte(len(msg) & 0xff)
		header[2] = byte((len(msg) & 0xff00) >> 8)
		size2write = len(msg)
		headerSize = 3

	case 3:
		if len(msg) > 255*255*255 {
			return fmt.Errorf("Structure type %d has 2-byte size header but %d bytes givven", msgType, len(msg))
		}
		header[1] = byte(len(msg) & 0xff)
		header[2] = byte((len(msg) & 0xff00) >> 8)
		header[3] = byte((len(msg) & 0xff0000) >> 16)
		size2write = len(msg)
		headerSize = 4

	default:
		return fmt.Errorf("Structure type %d has invalid SizeBytes setting (%d)", msgType, dt.SizeBytes)
	}

	if size2write > len(msg) {
		return fmt.Errorf("Unable to write %d bytes for structure %d, have only %d in buffer", msgType, size2write, len(msg))
	}

	c.writeMutex.Lock()
	defer c.writeMutex.Unlock()

	err := writeAll(c.conn, header[:], headerSize, c.WriteTimeout)
	if nil != err {
		return err
	}

	err = writeAll(c.conn, msg, size2write, c.WriteTimeout)
	if nil != err {
		return err
	}

	if size2write > 0 {
		crcI = crc32.Checksum(msg[0:size2write], crc32q)
		err = writeAll(c.conn, (*crcB)[:], 4, c.WriteTimeout)
		if nil != err {
			return err
		}
	}

	return nil
}

// Remote address retrive
func (c *Connection) Remote() net.Addr {
	if nil == c.conn {
		return nil
	}

	return c.conn.RemoteAddr()
}

func (c *Connection) prepareInitialPacket() initialPacket {
	result := initialPacket{MaxSize: c.MaxSize, Header: [8]byte{'s', 'x', 'c', 'h', 'n', 'g', verHI, verLO}}

	for i := 0; i < 256; i++ {
		result.FixedSize[i] = c.Types[uint8(i)].FixedSize
		result.SizeBytes[i] = c.Types[uint8(i)].SizeBytes
	}

	return result
}

func init() {
	if initialPacketSize != unsafe.Sizeof(initialPacket{}) {
		log.Fatalln("Golang uses different aligment withing structure, please modify sxchnge code!")
	}
}
<|endoftext|>


<commit_before>package mosaic

// #include <mosaic/mosaic.h>
import "C"
import "syscall"

// Mosaic is a type holding a reference to a mosaic
type Mosaic struct {
	m *C.struct_mosaic
}

// Volume is a type holding a reference to a volume
type Volume struct {
	v *C.struct_volume
}

// Open opens a mosaic
func Open(name string, flags int) (m Mosaic, e error) {
	cname := C.CString(name)
	defer cfree(cname)

	e = nil
	m.m = C.mosaic_open(cname, C.int(flags))
	if m.m == nil {
		e = lastError()
	}

	return
}

// Close closes a mosaic
func (m *Mosaic) Close() {
	C.mosaic_close(m.m)
}

// Mount mounts a mosaic
func (m *Mosaic) Mount(path string, flags int) error {
	cpath := C.CString(path)
	defer cfree(cpath)

	ret := C.mosaic_mount(m.m, cpath, C.int(flags))
	if ret == 0 {
		return nil
	}

	return lastError()
}

// Umount umounts a mosaic
func (m *Mosaic) Umount(path string) error {
	return syscall.Unmount(path, 0)
}
<commit_msg>go: use the Mosaic struct itself, not a pointer<commit_after>package mosaic

// #include <mosaic/mosaic.h>
import "C"
import "syscall"

// Mosaic is a type holding a reference to a mosaic
type Mosaic struct {
	m *C.struct_mosaic
}

// Volume is a type holding a reference to a volume
type Volume struct {
	v *C.struct_volume
}

// Open opens a mosaic
func Open(name string, flags int) (m Mosaic, e error) {
	cname := C.CString(name)
	defer cfree(cname)

	e = nil
	m.m = C.mosaic_open(cname, C.int(flags))
	if m.m == nil {
		e = lastError()
	}

	return
}

// Close closes a mosaic
func (m Mosaic) Close() {
	C.mosaic_close(m.m)
}

// Mount mounts a mosaic
func (m Mosaic) Mount(path string, flags int) error {
	cpath := C.CString(path)
	defer cfree(cpath)

	ret := C.mosaic_mount(m.m, cpath, C.int(flags))
	if ret == 0 {
		return nil
	}

	return lastError()
}

// Umount umounts a mosaic
func (m Mosaic) Umount(path string) error {
	return syscall.Unmount(path, 0)
}
<|endoftext|>


<commit_before>package main

import (
	goopt "github.com/droundy/goopt"
	"os"
	"path"
	"fmt"
	"regexp"
	"bytes"
)

var Pattern *regexp.Regexp
var byteNewLine []byte = []byte("\n")

func main() {
	goopt.Description = func() string {
		return "Go search and replace in files"
	}
	goopt.Version = "0.1"
	goopt.Parse(nil)

	if len(goopt.Args) == 0 {
		println(goopt.Usage())
		return
	}

	var err os.Error
	Pattern, err = regexp.Compile(goopt.Args[0])
	errhandle(err)

	searchFiles()
}

func errhandle(err os.Error) {
	if err == nil {
		return
	}
	fmt.Fprintf(os.Stderr, "ERR %s\n", err)
	os.Exit(1)
}

type Visitor struct{}

func (v *Visitor) VisitDir(p string, fi *os.FileInfo) bool {
	if fi.Name == ".hg" {
		return false
	}
	return true
}

func (v *Visitor) VisitFile(p string, fi *os.FileInfo) {
	if fi.Size >= 1024*1024*10 {
		fmt.Fprintf(os.Stderr, "Skipping %s, too big: %d\n", p, fi.Size)
		return
	}
	f, err := os.Open(p, os.O_RDONLY, 0666)
	errhandle(err)

	content := make([]byte, fi.Size)
	n, err := f.Read(content)
	errhandle(err)
	if int64(n) != fi.Size {
		panic(fmt.Sprintf("Not whole file was read, only %d from %d",
			n, fi.Size))
	}

	searchFile(p, content)

	f.Close()
}

func searchFile(p string, content []byte) {
	var linenum int
	last := 0
	hadOutput := false
	binary := false

	if bytes.IndexByte(content, 0) != -1 {
		binary = true
	}

	for _, bounds := range Pattern.FindAllIndex(content, -1) {
		if binary {
			fmt.Printf("Binary file %s matches\n", p)
			hadOutput = true
			break
		}

		if !hadOutput {
			fmt.Printf("%s:\n", p)
			hadOutput = true
		}

		linenum = bytes.Count(content[last:bounds[0]], byteNewLine)
		last = bounds[0]
		begin, end := beginend(content, bounds[0], bounds[1])

		fmt.Printf("%d:%s\n", linenum, content[begin:end])
	}

	if hadOutput {
		println()
	}
}

// Given a []byte, start and finish of some inner slice, will find nearest
// newlines on both ends of this slice
func beginend(s []byte, start int, finish int) (begin int, end int) {
	begin = 0
	end = len(s)

	for i := start; i >= 0; i-- {
		if s[i] == byteNewLine[0] {
			// skip newline itself
			begin = i + 1
			break
		}
	}

	for i := finish; i < len(s); i++ {
		if s[i] == byteNewLine[0] {
			end = i
			break
		}
	}

	return
}

func searchFiles() {
	v := &Visitor{}

	errors := make(chan os.Error, 64)

	path.Walk(".", v, errors)

	select {
	case err := <-errors:
		errhandle(err)
	default:
	}
}
<commit_msg>improve error reporting a bit, fix line counter<commit_after>package main

import (
	goopt "github.com/droundy/goopt"
	"os"
	"path"
	"fmt"
	"regexp"
	"bytes"
)

var Pattern *regexp.Regexp
var byteNewLine []byte = []byte("\n")

func main() {
	goopt.Description = func() string {
		return "Go search and replace in files"
	}
	goopt.Version = "0.1"
	goopt.Parse(nil)

	if len(goopt.Args) == 0 {
		println(goopt.Usage())
		return
	}

	var err os.Error
	Pattern, err = regexp.Compile(goopt.Args[0])
	errhandle(err, "can't compile regexp %s", goopt.Args[0])

	searchFiles()
}

func errhandle(err os.Error, moreinfo string, a ...interface{}) {
	if err == nil {
		return
	}
	fmt.Fprintf(os.Stderr, "ERR %s\n%s\n", err,
		fmt.Sprintf(moreinfo, a...))
	os.Exit(1)
}

type Visitor struct{}

func (v *Visitor) VisitDir(p string, fi *os.FileInfo) bool {
	if fi.Name == ".hg" {
		return false
	}
	return true
}

func (v *Visitor) VisitFile(p string, fi *os.FileInfo) {
	if fi.Size >= 1024*1024*10 {
		fmt.Fprintf(os.Stderr, "Skipping %s, too big: %d\n", p, fi.Size)
		return
	}

	if fi.Size == 0 {
		return
	}

	f, err := os.Open(p, os.O_RDONLY, 0666)
	errhandle(err, "can't open file %s", p)

	content := make([]byte, fi.Size)
	n, err := f.Read(content)
	errhandle(err, "can't read file %s", p)
	if int64(n) != fi.Size {
		panic(fmt.Sprintf("Not whole file was read, only %d from %d",
			n, fi.Size))
	}

	searchFile(p, content)

	f.Close()
}

func searchFile(p string, content []byte) {
	linenum := 1
	last := 0
	hadOutput := false
	binary := false

	if bytes.IndexByte(content, 0) != -1 {
		binary = true
	}

	for _, bounds := range Pattern.FindAllIndex(content, -1) {
		if binary {
			fmt.Printf("Binary file %s matches\n", p)
			hadOutput = true
			break
		}

		if !hadOutput {
			fmt.Printf("%s\n", p)
			hadOutput = true
		}

		linenum += bytes.Count(content[last:bounds[0]], byteNewLine)
		last = bounds[0]
		begin, end := beginend(content, bounds[0], bounds[1])

		if content[begin] == '\r' {
			begin += 1
		}

		fmt.Printf("%d:%s\n", linenum, content[begin:end])
	}

	if hadOutput {
		println()
	}
}

// Given a []byte, start and finish of some inner slice, will find nearest
// newlines on both ends of this slice
func beginend(s []byte, start int, finish int) (begin int, end int) {
	begin = 0
	end = len(s)

	for i := start; i >= 0; i-- {
		if s[i] == byteNewLine[0] {
			// skip newline itself
			begin = i + 1
			break
		}
	}

	for i := finish; i < len(s); i++ {
		if s[i] == byteNewLine[0] {
			end = i
			break
		}
	}

	return
}

func searchFiles() {
	v := &Visitor{}

	errors := make(chan os.Error, 64)

	path.Walk(".", v, errors)

	select {
	case err := <-errors:
		errhandle(err, "some error")
	default:
	}
}
<|endoftext|>


<commit_before>package nucular

type GroupList struct {
	w   *Window
	num int

	idx               int
	scrollbary        int
	done              bool
	first             bool
	skippedLineHeight int
}

// GroupListStart starts a scrollable list of <num> rows of <height> height
func GroupListStart(w *Window, num int, name string, flags WindowFlags) (GroupList, *Window) {
	var gl GroupList
	gl.w = w.GroupBegin(name, flags)
	gl.num = num
	gl.idx = -1
	if gl.w != nil {
		gl.scrollbary = gl.w.Scrollbar.Y
	}

	return gl, gl.w
}

func (gl *GroupList) Next() bool {
	if gl.w == nil {
		return false
	}
	if gl.skippedLineHeight > 0 && gl.idx >= 0 {
		if _, below := gl.w.Invisible(); below {
			n := gl.num - gl.idx
			gl.idx = gl.num
			gl.empty(n)
		}
	}
	gl.idx++
	if gl.idx >= gl.num {
		if !gl.done {
			gl.done = true
			if gl.scrollbary != gl.w.Scrollbar.Y {
				gl.w.Scrollbar.Y = gl.scrollbary
				gl.w.Master().Changed()
			}
			gl.w.GroupEnd()
		}
		return false
	}
	return true
}

func (gl *GroupList) SkipToVisible(lineheight int) {
	if gl.w == nil {
		return
	}
	gl.SkipToVisibleScaled(gl.w.ctx.scale(lineheight))
}

func (gl *GroupList) SkipToVisibleScaled(lineheight int) {
	if gl.w == nil {
		return
	}
	skip := gl.w.Scrollbar.Y/(lineheight+gl.w.style().Spacing.Y) - 2
	if maxskip := gl.num - 3; skip > maxskip {
		skip = maxskip
	}
	if skip < 0 {
		skip = 0
	}
	gl.skippedLineHeight = lineheight
	gl.empty(skip)
	gl.idx = skip - 1
}

func (gl *GroupList) empty(n int) {
	if n <= 0 {
		return
	}
	gl.w.RowScaled(n*gl.skippedLineHeight + (n-1)*gl.w.style().Spacing.Y).Dynamic(1)
	gl.w.Label("More...", "LC")
}

func (gl *GroupList) Index() int {
	return gl.idx
}

func (gl *GroupList) Center() {
	if above, below := gl.w.Invisible(); above || below {
		gl.scrollbary = gl.w.At().Y - gl.w.Bounds.H/2
		if gl.scrollbary < 0 {
			gl.scrollbary = 0
		}
	}
}
<commit_msg>Remove "first" bool<commit_after>package nucular

type GroupList struct {
	w   *Window
	num int

	idx               int
	scrollbary        int
	done              bool
	skippedLineHeight int
}

// GroupListStart starts a scrollable list of <num> rows of <height> height
func GroupListStart(w *Window, num int, name string, flags WindowFlags) (GroupList, *Window) {
	var gl GroupList
	gl.w = w.GroupBegin(name, flags)
	gl.num = num
	gl.idx = -1
	if gl.w != nil {
		gl.scrollbary = gl.w.Scrollbar.Y
	}

	return gl, gl.w
}

func (gl *GroupList) Next() bool {
	if gl.w == nil {
		return false
	}
	if gl.skippedLineHeight > 0 && gl.idx >= 0 {
		if _, below := gl.w.Invisible(); below {
			n := gl.num - gl.idx
			gl.idx = gl.num
			gl.empty(n)
		}
	}
	gl.idx++
	if gl.idx >= gl.num {
		if !gl.done {
			gl.done = true
			if gl.scrollbary != gl.w.Scrollbar.Y {
				gl.w.Scrollbar.Y = gl.scrollbary
				gl.w.Master().Changed()
			}
			gl.w.GroupEnd()
		}
		return false
	}
	return true
}

func (gl *GroupList) SkipToVisible(lineheight int) {
	if gl.w == nil {
		return
	}
	gl.SkipToVisibleScaled(gl.w.ctx.scale(lineheight))
}

func (gl *GroupList) SkipToVisibleScaled(lineheight int) {
	if gl.w == nil {
		return
	}
	skip := gl.w.Scrollbar.Y/(lineheight+gl.w.style().Spacing.Y) - 2
	if maxskip := gl.num - 3; skip > maxskip {
		skip = maxskip
	}
	if skip < 0 {
		skip = 0
	}
	gl.skippedLineHeight = lineheight
	gl.empty(skip)
	gl.idx = skip - 1
}

func (gl *GroupList) empty(n int) {
	if n <= 0 {
		return
	}
	gl.w.RowScaled(n*gl.skippedLineHeight + (n-1)*gl.w.style().Spacing.Y).Dynamic(1)
	gl.w.Label("More...", "LC")
}

func (gl *GroupList) Index() int {
	return gl.idx
}

func (gl *GroupList) Center() {
	if above, below := gl.w.Invisible(); above || below {
		gl.scrollbary = gl.w.At().Y - gl.w.Bounds.H/2
		if gl.scrollbary < 0 {
			gl.scrollbary = 0
		}
	}
}
<|endoftext|>


<commit_before>package sandwich

import (
	"compress/gzip"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestGzip(t *testing.T) {
	greet := func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get(headerAcceptEncoding) != "gzip" {
			t.Error("Expected gzip to be accepted: ", r.Header)
		}
		fmt.Fprintf(w, "Hi there!")
	}
	handler := Gzip(New()).With(greet)

	resp := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/", nil)
	req.Header.Add(headerAcceptEncoding, "gzip")
	handler.ServeHTTP(resp, req)

	if resp.Header().Get(headerContentEncoding) != "gzip" {
		t.Errorf("Not gzip'd? Content-encoding: %q", resp.Header())
	}

	if resp.Header().Get(headerContentLength) != "" {
		t.Errorf("Not supposed to include content-length: %q", resp.Header())
	}

	r, err := gzip.NewReader(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	defer r.Close()
	if body, err := ioutil.ReadAll(r); err != nil {
		t.Fatal(err)
	} else if string(body) != "Hi there!" {
		t.Errorf("Wrong response: %q", string(body))
	}
}
<commit_msg>Add test that validates gzip'ing is skipped when not accepted.<commit_after>package sandwich

import (
	"compress/gzip"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestGzip(t *testing.T) {
	greet := func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hi there!")
	}
	handler := Gzip(New()).With(greet)

	resp := httptest.NewRecorder()
	req, _ := http.NewRequest("GET", "/", nil)
	req.Header.Add(headerAcceptEncoding, "gzip")
	handler.ServeHTTP(resp, req)

	if resp.Header().Get(headerContentEncoding) != "gzip" {
		t.Errorf("Not gzip'd? Content-encoding: %q", resp.Header())
	}

	if resp.Header().Get(headerContentLength) != "" {
		t.Errorf("Not supposed to include content-length: %q", resp.Header())
	}

	r, err := gzip.NewReader(resp.Body)
	if err != nil {
		t.Fatal(err)
	}
	defer r.Close()
	if body, err := ioutil.ReadAll(r); err != nil {
		t.Fatal(err)
	} else if string(body) != "Hi there!" {
		t.Errorf("Wrong response: %q", string(body))
	}

	// Also, test without the accept header and make sure it's NOT gzip'd.
	resp = httptest.NewRecorder()
	req, _ = http.NewRequest("GET", "/", nil)
	handler.ServeHTTP(resp, req)
	if resp.Header().Get(headerContentEncoding) == "gzip" {
		t.Errorf("Unexpectedly gzip'd: Content-encoding: %q", resp.Header())
	}
	if resp.Body.String() != "Hi there!" {
		t.Errorf("Wrong response: %q", resp.Body.String())
	}
}
<|endoftext|>


<commit_before>package obj

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"io"

	"github.com/Azure/azure-sdk-for-go/storage"
)

type microsoftClient struct {
	blobClient storage.BlobStorageClient
	container  string
}

func newMicrosoftClient(container string, accountName string, accountKey string) (*microsoftClient, error) {
	client, err := storage.NewBasicClient(
		accountName,
		accountKey,
	)
	if err != nil {
		return nil, err
	}

	return &microsoftClient{
		blobClient: client.GetBlobService(),
		container:  container,
	}, nil
}

func (c *microsoftClient) Writer(name string) (io.WriteCloser, error) {
	writer, err := newMicrosoftWriter(c, name)
	if err != nil {
		return nil, err
	}
	return newBackoffWriteCloser(c, writer), nil
}

func (c *microsoftClient) Reader(name string, offset uint64, size uint64) (io.ReadCloser, error) {
	reader, err := c.blobClient.GetBlobRange(c.container, name, byteRange(offset, size), nil)

	if err != nil {
		return nil, err
	}
	return newBackoffReadCloser(c, reader), nil
}

func (c *microsoftClient) Delete(name string) error {
	return c.blobClient.DeleteBlob(c.container, name, nil)
}

func (c *microsoftClient) Walk(name string, fn func(name string) error) error {
	blobList, err := c.blobClient.ListBlobs(c.container, storage.ListBlobsParameters{Prefix: name})
	if err != nil {
		return err
	}

	for _, file := range blobList.Blobs {
		if err := fn(file.Name); err != nil {
			return err
		}
	}
	return nil
}

func (c *microsoftClient) Exists(name string) bool {
	exists, _ := c.blobClient.BlobExists(c.container, name)
	return exists
}

func (c *microsoftClient) isRetryable(err error) (ret bool) {
	microsoftErr, ok := err.(storage.AzureStorageServiceError)
	if !ok {
		return false
	}
	return microsoftErr.StatusCode >= 500
}

func (c *microsoftClient) IsNotExist(err error) bool {
	microsoftErr, ok := err.(storage.AzureStorageServiceError)
	if !ok {
		return false
	}
	return microsoftErr.StatusCode == 404
}

func (c *microsoftClient) IsIgnorable(err error) bool {
	return false
}

type microsoftWriter struct {
	container  string
	blob       string
	blobClient storage.BlobStorageClient
}

func newMicrosoftWriter(client *microsoftClient, name string) (*microsoftWriter, error) {
	// create container
	_, err := client.blobClient.CreateContainerIfNotExists(client.container, storage.ContainerAccessTypePrivate)
	if err != nil {
		return nil, err
	}

	// check blob existence
	exists, err := client.blobClient.BlobExists(client.container, name)
	if exists {
		err = errors.New(name + " blob already exists")
	}
	if err != nil {
		return nil, err
	}

	// create blob
	err = client.blobClient.CreateBlockBlob(client.container, name)
	if err != nil {
		return nil, err
	}

	return &microsoftWriter{
		container:  client.container,
		blob:       name,
		blobClient: client.blobClient,
	}, nil
}

func (w *microsoftWriter) Write(b []byte) (int, error) {
	blockList, err := w.blobClient.GetBlockList(w.container, w.blob, storage.BlockListTypeAll)
	if err != nil {
		return 0, err
	}

	blocksLen := len(blockList.CommittedBlocks)
	amendList := []storage.Block{}
	for _, v := range blockList.CommittedBlocks {
		amendList = append(amendList, storage.Block{v.Name, storage.BlockStatusCommitted})
	}

	var chunkSize = storage.MaxBlobBlockSize
	inputSourceReader := bytes.NewReader(b)
	chunk := make([]byte, chunkSize)
	for {
		n, err := inputSourceReader.Read(chunk)
		if err == io.EOF {
			break
		}
		if err != nil {
			return 0, err
		}

		blockID := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%011d\n", blocksLen)))
		data := chunk[:n]
		err = w.blobClient.PutBlock(w.container, w.blob, blockID, data)
		if err != nil {
			return 0, err
		}
		// add current uncommitted block to temporary block list
		amendList = append(amendList, storage.Block{blockID, storage.BlockStatusUncommitted})
		blocksLen++
	}

	// update block list to blob committed block list.
	err = w.blobClient.PutBlockList(w.container, w.blob, amendList)
	if err != nil {
		return 0, err
	}
	return len(b), nil
}

func (w *microsoftWriter) Close() error {
	return nil
}
<commit_msg>Use GetBlob instead of GetBlobRange when no range.<commit_after>package obj

import (
	"bytes"
	"encoding/base64"
	"errors"
	"fmt"
	"io"

	"github.com/Azure/azure-sdk-for-go/storage"
)

type microsoftClient struct {
	blobClient storage.BlobStorageClient
	container  string
}

func newMicrosoftClient(container string, accountName string, accountKey string) (*microsoftClient, error) {
	client, err := storage.NewBasicClient(
		accountName,
		accountKey,
	)
	if err != nil {
		return nil, err
	}

	return &microsoftClient{
		blobClient: client.GetBlobService(),
		container:  container,
	}, nil
}

func (c *microsoftClient) Writer(name string) (io.WriteCloser, error) {
	writer, err := newMicrosoftWriter(c, name)
	if err != nil {
		return nil, err
	}
	return newBackoffWriteCloser(c, writer), nil
}

func (c *microsoftClient) Reader(name string, offset uint64, size uint64) (io.ReadCloser, error) {
	byteRange := byteRange(offset, size)
	var reader io.ReadCloser
	var err error
	if byteRange == "" {
		reader, err = c.blobClient.GetBlob(c.container, name)
	} else {
		reader, err = c.blobClient.GetBlobRange(c.container, name, byteRange, nil)
	}

	if err != nil {
		return nil, err
	}
	return newBackoffReadCloser(c, reader), nil
}

func (c *microsoftClient) Delete(name string) error {
	return c.blobClient.DeleteBlob(c.container, name, nil)
}

func (c *microsoftClient) Walk(name string, fn func(name string) error) error {
	blobList, err := c.blobClient.ListBlobs(c.container, storage.ListBlobsParameters{Prefix: name})
	if err != nil {
		return err
	}

	for _, file := range blobList.Blobs {
		if err := fn(file.Name); err != nil {
			return err
		}
	}
	return nil
}

func (c *microsoftClient) Exists(name string) bool {
	exists, _ := c.blobClient.BlobExists(c.container, name)
	return exists
}

func (c *microsoftClient) isRetryable(err error) (ret bool) {
	microsoftErr, ok := err.(storage.AzureStorageServiceError)
	if !ok {
		return false
	}
	return microsoftErr.StatusCode >= 500
}

func (c *microsoftClient) IsNotExist(err error) bool {
	microsoftErr, ok := err.(storage.AzureStorageServiceError)
	if !ok {
		return false
	}
	return microsoftErr.StatusCode == 404
}

func (c *microsoftClient) IsIgnorable(err error) bool {
	return false
}

type microsoftWriter struct {
	container  string
	blob       string
	blobClient storage.BlobStorageClient
}

func newMicrosoftWriter(client *microsoftClient, name string) (*microsoftWriter, error) {
	// create container
	_, err := client.blobClient.CreateContainerIfNotExists(client.container, storage.ContainerAccessTypePrivate)
	if err != nil {
		return nil, err
	}

	// check blob existence
	exists, err := client.blobClient.BlobExists(client.container, name)
	if exists {
		err = errors.New(name + " blob already exists")
	}
	if err != nil {
		return nil, err
	}

	// create blob
	err = client.blobClient.CreateBlockBlob(client.container, name)
	if err != nil {
		return nil, err
	}

	return &microsoftWriter{
		container:  client.container,
		blob:       name,
		blobClient: client.blobClient,
	}, nil
}

func (w *microsoftWriter) Write(b []byte) (int, error) {
	blockList, err := w.blobClient.GetBlockList(w.container, w.blob, storage.BlockListTypeAll)
	if err != nil {
		return 0, err
	}

	blocksLen := len(blockList.CommittedBlocks)
	amendList := []storage.Block{}
	for _, v := range blockList.CommittedBlocks {
		amendList = append(amendList, storage.Block{v.Name, storage.BlockStatusCommitted})
	}

	var chunkSize = storage.MaxBlobBlockSize
	inputSourceReader := bytes.NewReader(b)
	chunk := make([]byte, chunkSize)
	for {
		n, err := inputSourceReader.Read(chunk)
		if err == io.EOF {
			break
		}
		if err != nil {
			return 0, err
		}

		blockID := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%011d\n", blocksLen)))
		data := chunk[:n]
		err = w.blobClient.PutBlock(w.container, w.blob, blockID, data)
		if err != nil {
			return 0, err
		}
		// add current uncommitted block to temporary block list
		amendList = append(amendList, storage.Block{blockID, storage.BlockStatusUncommitted})
		blocksLen++
	}

	// update block list to blob committed block list.
	err = w.blobClient.PutBlockList(w.container, w.blob, amendList)
	if err != nil {
		return 0, err
	}
	return len(b), nil
}

func (w *microsoftWriter) Close() error {
	return nil
}
<|endoftext|>


<commit_before>// Tideland Go CouchDB Client - Find - Selector
//
// Copyright (C) 2016-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.

package find

//--------------------
// IMPORTS
//--------------------

import (
	"encoding/json"
	"strings"
)

//--------------------
// CONSTANTS
//--------------------

// CombinationOperator sets how to combine multiple selectors.
type CombinationOperator int

const (
	CombineAnd CombinationOperator = iota + 1
	CombineOr
	CombineNone
)

//--------------------
// FIND SELECTOR
//--------------------

// Selector contains one or more conditions to find documents.
type Selector interface {
	// Equal checks if the field is equal to the argument.
	Equal(field string, argument interface{}) Selector

	// In checks if the field is in the arguments.
	In(field string, arguments ...interface{}) Selector

	// GreaterThan checks if the field is greater than the argument.
	GreaterThan(field, argument interface{})

	// Marshaler allows to write a selector in its JSON encoding.
	json.Marshaler
}

// selector implements Selector.
type selector struct {
	field     string
	operator  string
	arguments []interface{}
}

// NewSelector creates a selector based on the given
// combination operator.
func NewSelector(co CombinationOperator, selectors ...Selector) Selector {
	// Get combination operator.
	ops := map[CombinationOperator]string{
		CombineAnd:  "$and",
		CombineOr:   "$or",
		CombineNone: "$nor",
	}
	op, ok := ops[co]
	if !ok {
		op = "$and"
	}
	// Create selector.
	s := &selector{
		operator: op,
	}
	for _, subselector := range selectors {
		s.arguments = append(s.arguments, subselector)
	}
	return s
}

// Equal implements Selector.
func (s *selector) Equal(field string, argument interface{}) Selector {
	s.arguments = append(s.arguments, &selector{
		field:     field,
		operator:  "$eq",
		arguments: []interface{}{argument},
	})
	return s
}

// In implements Selector.
func (s *selector) In(field string, arguments ...interface{}) Selector {
	s.arguments = append(s.arguments, &selector{
		field:     field,
		operator:  "$in",
		arguments: arguments,
	})
	return s
}

// GreaterThan implements Selector.
func (s *selector) GreaterThan(field string, argument interface{}) Selector {
	s.arguments = append(s.arguments, &selector{
		field:     field,
		operator:  "$gt",
		arguments: []interface{}{argument},
	})
	return s
}

// MarshalJSON implements json.Marshaler.
func (s *selector) MarshalJSON() ([]byte, error) {
	// First operator and argument(s).
	var jArguments []string
	var jArgument string
	for _, argument := range s.arguments {
		b, err := json.Marshal(argument)
		if err != nil {
			return nil, err
		}
		jArguments = append(jArguments, string(b))
	}
	if len(jArguments) == 1 {
		jArgument = jArguments[0]
	} else {
		jArgument = "[" + strings.Join(jArguments, ",") + "]"
	}
	jOperatorArgument := "{\"" + s.operator + "\":" + jArgument + "}"
	if s.field == "" {
		return []byte(jOperatorArgument), nil
	}
	jField := "{\"" + s.field + "\":" + jOperatorArgument + "}"
	return []byte(jField), nil
}

// EOF
<commit_msg>Made selector.MarshalJSON() smarter<commit_after>// Tideland Go CouchDB Client - Find - Selector
//
// Copyright (C) 2016-2017 Frank Mueller / Tideland / Oldenburg / Germany
//
// All rights reserved. Use of this source code is governed
// by the new BSD license.

package find

//--------------------
// IMPORTS
//--------------------

import (
	"bytes"
	"encoding/json"
	"fmt"
)

//--------------------
// CONSTANTS
//--------------------

// CombinationOperator sets how to combine multiple selectors.
type CombinationOperator int

const (
	CombineAnd CombinationOperator = iota + 1
	CombineOr
	CombineNot
	CombineNone
)

//--------------------
// FIND SELECTOR
//--------------------

// Selector contains one or more conditions to find documents.
type Selector interface {
	// Equal checks if the field is equal to the argument.
	Equal(field string, argument interface{}) Selector

	// In checks if the field is in the arguments.
	In(field string, arguments ...interface{}) Selector

	// All checks if the field is an array and contains all the arguments.
	All(field string, arguments ...interface{}) Selector

	// GreaterThan checks if the field is greater than the argument.
	GreaterThan(field string, argument interface{}) Selector

	// Marshaler allows to write a selector in its JSON encoding.
	json.Marshaler
}

// selector implements Selector.
type selector struct {
	field     string
	operator  string
	arguments []interface{}
}

// NewSelector creates a selector based on the given
// combination operator.
func NewSelector(co CombinationOperator, selectors ...Selector) Selector {
	// Get combination operator.
	ops := map[CombinationOperator]string{
		CombineAnd:  "$and",
		CombineOr:   "$or",
		CombineNot:  "$not",
		CombineNone: "$nor",
	}
	op, ok := ops[co]
	if !ok {
		op = "$and"
	}
	// Create selector.
	s := &selector{
		operator: op,
	}
	for _, subselector := range selectors {
		s.arguments = append(s.arguments, subselector)
	}
	return s
}

// Equal implements Selector.
func (s *selector) Equal(field string, argument interface{}) Selector {
	s.arguments = append(s.arguments, &selector{
		field:     field,
		operator:  "$eq",
		arguments: []interface{}{argument},
	})
	return s
}

// In implements Selector.
func (s *selector) In(field string, arguments ...interface{}) Selector {
	s.arguments = append(s.arguments, &selector{
		field:     field,
		operator:  "$in",
		arguments: arguments,
	})
	return s
}

// All implements Selector.
func (s *selector) All(field string, arguments ...interface{}) Selector {
	s.arguments = append(s.arguments, &selector{
		field:     field,
		operator:  "$all",
		arguments: arguments,
	})
	return s
}

// GreaterThan implements Selector.
func (s *selector) GreaterThan(field string, argument interface{}) Selector {
	s.arguments = append(s.arguments, &selector{
		field:     field,
		operator:  "$gt",
		arguments: []interface{}{argument},
	})
	return s
}

// MarshalJSON implements json.Marshaler.
func (s *selector) MarshalJSON() ([]byte, error) {
	var sbuf bytes.Buffer
	var jargs [][]byte
	var jargslen int

	for _, argument := range s.arguments {
		jarg, err := json.Marshal(argument)
		if err != nil {
			return nil, err
		}
		jargs = append(jargs, jarg)
	}
	jargslen = len(jargs)

	// Prepend with field if needed.
	if s.field != "" {
		fmt.Fprintf(&sbuf, "{%q:", s.field)
	}
	// Now operator and argument8s).
	fmt.Fprintf(&sbuf, "{%q:", s.operator)
	if jargslen > 1 {
		fmt.Fprintf(&sbuf, "[")
	}
	for i, jarg := range jargs {
		fmt.Fprintf(&sbuf, "%s", jarg)
		if i < jargslen-1 {
			fmt.Fprint(&sbuf, ",")
		}
	}
	if jargslen > 1 {
		fmt.Fprint(&sbuf, "]")
	}
	fmt.Fprint(&sbuf, "}")
	// Append closing brace if field has been prepended.
	if s.field != "" {
		fmt.Fprint(&sbuf, "}")
	}

	return sbuf.Bytes(), nil
}

// EOF
<|endoftext|>


<commit_before>package flickr

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"math/rand"
	"net/url"
	"time"
)

type Request struct {
	Url    string
	Method string
	Args   url.Values
}

func NewRequest(url string, method string, args url.Values) *Request {
	r := Request{url, method, args}

	return &r
}

func getSigningBaseString(request *Request) string {
	request_url := url.QueryEscape(request.Url)
	query := url.QueryEscape(request.Args.Encode())

	return fmt.Sprintf("%s&%s&%s", request.Method, request_url, query)
}

func Sign(request *Request, consumer_secret string, token_secret string) string {
	key := fmt.Sprintf("%s&%s", url.QueryEscape(consumer_secret), url.QueryEscape(token_secret))
	base_string := getSigningBaseString(request)

	mac := hmac.New(sha1.New, []byte(key))
	mac.Write([]byte(base_string))

	ret := base64.StdEncoding.EncodeToString(mac.Sum(nil))

	return ret
}

func generateNonce() string {
	rand.Seed(time.Now().UTC().UnixNano())
	var letters = []rune("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ")
	b := make([]rune, 8)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

func getDefaultArgs() url.Values {
	args := url.Values{}
	args.Add("oauth_version", "1.0")
	args.Add("oauth_signature_method", "HMAC-SHA1")
	args.Add("oauth_nonce", generateNonce())
	args.Add("oauth_timestamp", fmt.Sprintf("%d", time.Now().Unix()))

	return args
}

func GetRequestToken(api_key string, api_secret string) {
	base_url := "https://www.flickr.com/services/oauth/request_token"

	args := getDefaultArgs()
	args.Add("oauth_consumer_key", api_key)
	args.Add("oauth_callback", "oob")

	request := NewRequest(base_url, "GET", args)
	// we don't have token secret at this stage, pass an empty string
	signature := Sign(request, api_secret, "")
	request.Args.Add("oauth_signature", url.QueryEscape(signature))

	api_url := fmt.Sprintf("%s?%s", base_url, request.Args.Encode())
	fmt.Println(api_url)
}
<commit_msg>do not urlencode twice<commit_after>package flickr

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"math/rand"
	"net/url"
	"time"
)

type Request struct {
	Url    string
	Method string
	Args   url.Values
}

func NewRequest(url string, method string, args url.Values) *Request {
	r := Request{url, method, args}

	return &r
}

func getSigningBaseString(request *Request) string {
	request_url := url.QueryEscape(request.Url)
	query := url.QueryEscape(request.Args.Encode())

	return fmt.Sprintf("%s&%s&%s", request.Method, request_url, query)
}

func Sign(request *Request, consumer_secret string, token_secret string) string {
	key := fmt.Sprintf("%s&%s", url.QueryEscape(consumer_secret), url.QueryEscape(token_secret))
	base_string := getSigningBaseString(request)

	mac := hmac.New(sha1.New, []byte(key))
	mac.Write([]byte(base_string))

	ret := base64.StdEncoding.EncodeToString(mac.Sum(nil))

	return ret
}

func generateNonce() string {
	rand.Seed(time.Now().UTC().UnixNano())
	var letters = []rune("123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ")
	b := make([]rune, 8)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}

func getDefaultArgs() url.Values {
	args := url.Values{}
	args.Add("oauth_version", "1.0")
	args.Add("oauth_signature_method", "HMAC-SHA1")
	args.Add("oauth_nonce", generateNonce())
	args.Add("oauth_timestamp", fmt.Sprintf("%d", time.Now().Unix()))

	return args
}

func GetRequestToken(api_key string, api_secret string) {
	base_url := "https://www.flickr.com/services/oauth/request_token"

	args := getDefaultArgs()
	args.Add("oauth_consumer_key", api_key)
	args.Add("oauth_callback", "oob")

	request := NewRequest(base_url, "GET", args)
	// we don't have token secret at this stage, pass an empty string
	request.Args.Add("oauth_signature", Sign(request, api_secret, ""))

	api_url := fmt.Sprintf("%s?%s", base_url, request.Args.Encode())
	fmt.Println(api_url)
}
<|endoftext|>