<commit_before>package main

import (
	"fmt"
	"github.com/mitchellh/copystructure"
	"strings"
)

const version1 = "2015-07-25"
const version2 = "2015-12-19"
const version3 = "2016-07-29"

func GenerateAnswers(delta *MetadataDelta) (Versions, error) {
	// 1. generate interim data
	s := len(delta.Data)
	interim := &Interim{
		UUIDToService:                   make(map[string]map[string]interface{}, s),
		UUIDToContainer:                 make(map[string]map[string]interface{}, s),
		UUIDToStack:                     make(map[string]map[string]interface{}, s),
		UUIDToHost:                      make(map[string]map[string]interface{}, s),
		StackUUIDToServicesUUID:         make(map[string][]string, s),
		ServiceUUIDNameToContainersUUID: make(map[string][]string, s),
		ContainerUUIDToContainerLink:    make(map[string]map[string]interface{}, s),
		ServiceUUIDToServiceLink:        make(map[string]map[string]interface{}, s),
		Networks:                        []interface{}{},
		Default:                         make(map[string]interface{}, s),
	}

	for _, o := range delta.Data {
		processMetadataObject(o, interim)
	}
	// 2. Generate versions from temp data
	versions, err := generateVersions(interim)
	if err != nil {
		return nil, err
	}
	return versions, nil
}

func generateVersions(interim *Interim) (Versions, error) {
	versions := make(map[string]Answers)
	vs := []string{version1, version2, version3}
	for _, v := range vs {
		versionedData, err := applyVersionToData(*interim, v)
		if err != nil {
			return nil, err
		}
		addToVersions(versions, v, versionedData)
	}
	//tag the latest
	versions["latest"] = versions[version3]
	return versions, nil
}

func addToVersions(versions Versions, version string, versionedData *Interim) {
	answers := make(map[string]interface{})
	defaultAnswers := addDefaultToAnswers(answers, versionedData)
	addClientToAnswers(answers, defaultAnswers, versionedData)
	versions[version] = answers
}

func addClientToAnswers(answers Answers, defaultAnswers map[string]interface{}, versionedData *Interim) {
	for _, c := range versionedData.UUIDToContainer {
		if c["primary_ip"] == nil {
			continue
		}
		clientAnswers := make(map[string]interface{})
		self := make(map[string]interface{})
		self["container"] = c
		if c["stack_uuid"] != nil {
			self["stack"] = versionedData.UUIDToStack[c["stack_uuid"].(string)]
			self["service"] = versionedData.UUIDToService[getServiceUUID(c["service_uuid"].(string), c["service_name"].(string))]
		}
		if c["host_uuid"] != nil {
			self["host"] = versionedData.UUIDToHost[c["host_uuid"].(string)]
		}
		clientAnswers["self"] = self
		mergeDefaults(clientAnswers, defaultAnswers)
		answers[c["primary_ip"].(string)] = clientAnswers
	}
}

func mergeDefaults(clientAnswers map[string]interface{}, defaultAnswers map[string]interface{}) {
	for k, v := range defaultAnswers {
		_, exists := clientAnswers[k]
		if !exists {
			clientAnswers[k] = v
		}
	}
}

func addDefaultToAnswers(answers Answers, versionedData *Interim) map[string]interface{} {
	defaultAnswers := make(map[string]interface{})
	var containers []interface{}
	for _, c := range versionedData.UUIDToContainer {
		if _, ok := defaultAnswers["containers"]; ok {
			containers = defaultAnswers["containers"].([]interface{})
		}
		containers = append(containers, c)
	}
	defaultAnswers["containers"] = containers

	var stacks []interface{}
	for _, s := range versionedData.UUIDToStack {
		if _, ok := defaultAnswers["stacks"]; ok {
			stacks = defaultAnswers["stacks"].([]interface{})
		}
		stacks = append(stacks, s)
	}
	defaultAnswers["stacks"] = stacks

	var services []interface{}
	for _, s := range versionedData.UUIDToService {
		if _, ok := defaultAnswers["services"]; ok {
			services = defaultAnswers["services"].([]interface{})
		}
		services = append(services, s)
	}
	defaultAnswers["services"] = services

	var hosts []interface{}
	for _, h := range versionedData.UUIDToHost {
		if _, ok := defaultAnswers["hosts"]; ok {
			hosts = defaultAnswers["hosts"].([]interface{})
		}
		hosts = append(hosts, h)
	}
	defaultAnswers["hosts"] = hosts
	defaultAnswers["networks"] = versionedData.Networks

	if val, ok := versionedData.Default["version"]; ok {
		defaultAnswers["version"] = val
	}

	if selfVal, ok := versionedData.Default["self"]; ok {
		self := selfVal.(map[string]interface{})
		if hostVal, ok := self["host"]; ok {
			host := hostVal.(map[string]interface{})
			self["host"] = versionedData.UUIDToHost[host["uuid"].(string)]
		}
		defaultAnswers["self"] = self
	}

	answers[DEFAULT_KEY] = defaultAnswers
	return defaultAnswers
}

func applyVersionToData(orig Interim, version string) (*Interim, error) {
	copied, err := copystructure.Copy(orig)
	if err != nil {
		return nil, err
	}
	modified := copied.(Interim)
	// 1. Process containers
	for _, c := range modified.UUIDToContainer {
		switch version {
		case version3:
			if c["name"] != nil {
				c["name"] = strings.ToLower(c["name"].(string))
			}
			if c["service_name"] != nil {
				c["service_name"] = strings.ToLower(c["service_name"].(string))
			}
			if c["stack_name"] != nil {
				c["stack_name"] = strings.ToLower(c["stack_name"].(string))
			}
			if _, ok := c["ports"]; ok {
				// set port ip to 0.0.0.0 if not specified
				originalPorts := c["ports"].([]interface{})
				var newPorts []interface{}
				for _, p := range originalPorts {
					port := p.(string)
					splitted := strings.Split(port, ":")
					if len(splitted) == 3 {
						newPorts = append(newPorts, port)
					} else {
						port = fmt.Sprintf("0.0.0.0:%s", port)
						newPorts = append(newPorts, port)
					}
				}
				c["ports"] = newPorts
			}

		default:
			if _, ok := c["ports"]; ok {
				originalPorts := c["ports"].([]interface{})
				// set port ip to host's ip if not specified
				if len(originalPorts) > 0 {
					var newPorts []interface{}
					for _, p := range originalPorts {
						port := p.(string)
						splitted := strings.Split(port, ":")
						if len(splitted) == 3 && splitted[0] != "0.0.0.0" {
							newPorts = append(newPorts, port)
						} else {
							if len(splitted) == 3 {
								port = fmt.Sprintf("%s%s", c["host_ip"], strings.TrimPrefix(port, "0.0.0.0"))
							} else {
								port = fmt.Sprintf("%s:%s", c["host_ip"], port)
							}

							newPorts = append(newPorts, port)
						}
					}
					c["ports"] = newPorts
				}
			}
		}
		c["links"] = modified.ContainerUUIDToContainerLink[c["uuid"].(string)]
		//delete helper field (needed for the port)
		delete(c, "host_ip")
	}

	// 2. Process services
	for _, s := range modified.UUIDToService {
		sUUID := getServiceUUID(s["uuid"].(string), s["name"].(string))

		stackUUID := s["stack_uuid"].(string)
		// add itself to the stack list
		var svcUUIDs []string
		if _, ok := modified.StackUUIDToServicesUUID[stackUUID]; ok {
			svcUUIDs = modified.StackUUIDToServicesUUID[stackUUID]
		}
		svcUUIDs = append(svcUUIDs, getServiceUUID(s["uuid"].(string), s["name"].(string)))
		modified.StackUUIDToServicesUUID[stackUUID] = svcUUIDs
		var cs []interface{}
		var cNames []interface{}
		cUUIDs := modified.ServiceUUIDNameToContainersUUID[sUUID]
		if cUUIDs != nil {
			for _, cUUID := range cUUIDs {
				if c, ok := modified.UUIDToContainer[cUUID]; ok {
					cs = append(cs, c)
					cNames = append(cNames, c["name"].(string))
				}
			}
		}
		// add service links
		s["links"] = modified.ServiceUUIDToServiceLink[s["uuid"].(string)]
		switch version {
		case version1:
			s["containers"] = cNames
		case version2:
			s["containers"] = cs
		case version3:
			s["containers"] = cs
			s["name"] = strings.ToLower(s["name"].(string))
			s["stack_name"] = strings.ToLower(s["stack_name"].(string))
			s["primary_service_name"] = strings.ToLower(s["primary_service_name"].(string))
			if s["sidekicks"] != nil {
				sidekicks := s["sidekicks"].([]interface{})
				var lowercased []interface{}
				for _, sidekick := range sidekicks {
					lowercased = append(lowercased, strings.ToLower(sidekick.(string)))
				}
				s["sidekicks"] = lowercased
			}
			if s["links"] != nil {
				links := s["links"].(map[string]interface{})
				lowercased := make(map[string]interface{})
				for key, value := range links {
					lowercased[strings.ToLower(key)] = value
				}
				s["links"] = lowercased
			}
		}

		// populate stack/service info on container
		if cUUIDs != nil {
			for _, cUUID := range cUUIDs {
				if _, ok := modified.UUIDToContainer[cUUID]; ok {
					modified.UUIDToContainer[cUUID]["service_name"] = s["name"]
					modified.UUIDToContainer[cUUID]["service_uuid"] = s["uuid"]
					modified.UUIDToContainer[cUUID]["stack_name"] = s["stack_name"]
					modified.UUIDToContainer[cUUID]["stack_uuid"] = stackUUID
				}
			}
		}
	}

	// 3. Process stacks
	for _, s := range modified.UUIDToStack {
		var svcs []interface{}
		var svcsNames []interface{}
		svcsUUIDs := modified.StackUUIDToServicesUUID[s["uuid"].(string)]
		if svcsUUIDs != nil {
			for _, svcUUID := range svcsUUIDs {
				if svc, ok := modified.UUIDToService[svcUUID]; ok {
					svcs = append(svcs, svc)
					svcsNames = append(svcsNames, svc["name"].(string))
				}
			}
		}
		switch version {
		case version1:
			s["services"] = svcsNames
		case version2:
			s["services"] = svcs
		case version3:
			s["services"] = svcs
			s["name"] = strings.ToLower(s["name"].(string))
		}
	}

	// 4. process hosts
	for _, h := range modified.UUIDToHost {
		switch version {
		case version3:
			delete(h, "hostId")
		}
	}

	return &modified, nil
}

func processMetadataObject(o map[string]interface{}, interim *Interim) {
	if val, ok := o["metadata_kind"]; ok {
		switch val.(string) {
		case "container":
			addContainer(o, interim)
		case "stack":
			addStack(o, interim)
		case "network":
			addNetwork(o, interim)
		case "host":
			addHost(o, interim)
		case "defaultData":
			addDefault(o, interim)
		case "serviceContainerLink":
			addServiceContainerLink(o, interim)
		case "containerLink":
			addContainerLink(o, interim)
		case "serviceLink":
			addServiceLink(o, interim)
		case "service":
			addService(o, interim)
		}
	}
}

func addContainer(container map[string]interface{}, interim *Interim) {
	interim.UUIDToContainer[container["uuid"].(string)] = container
}

func addService(service map[string]interface{}, interim *Interim) {
	interim.UUIDToService[getServiceUUID(service["uuid"].(string), service["name"].(string))] = service
}

func addServiceContainerLink(link map[string]interface{}, interim *Interim) {
	UUID := getServiceUUID(link["service_uuid"].(string), link["service_name"].(string))
	var containerUUIDList []string
	if _, ok := interim.ServiceUUIDNameToContainersUUID[UUID]; ok {
		containerUUIDList = interim.ServiceUUIDNameToContainersUUID[UUID]
	}
	containerUUIDList = append(containerUUIDList, link["container_uuid"].(string))
	interim.ServiceUUIDNameToContainersUUID[UUID] = containerUUIDList
}

func addServiceLink(link map[string]interface{}, interim *Interim) {
	serviceUUID := link["service_uuid"].(string)
	links := make(map[string]interface{})
	if _, ok := interim.ServiceUUIDToServiceLink[serviceUUID]; ok {
		links = interim.ServiceUUIDToServiceLink[serviceUUID]
	}
	linkKey := link["key"].(string)
	links[linkKey] = link["value"].(string)

	interim.ServiceUUIDToServiceLink[serviceUUID] = links
}

func addContainerLink(link map[string]interface{}, interim *Interim) {
	containerUUID := link["container_uuid"].(string)
	links := make(map[string]interface{})
	if _, ok := interim.ContainerUUIDToContainerLink[containerUUID]; ok {
		links = interim.ContainerUUIDToContainerLink[containerUUID]
	}
	linkKey := link["key"].(string)
	links[linkKey] = link["value"].(string)

	interim.ContainerUUIDToContainerLink[containerUUID] = links
}

func getServiceUUID(UUID string, name string) string {
	return strings.ToLower(fmt.Sprintf("%s_%s", UUID, name))
}

func addStack(stack map[string]interface{}, interim *Interim) {
	interim.UUIDToStack[stack["uuid"].(string)] = stack
}

func addNetwork(network map[string]interface{}, interim *Interim) {
	interim.Networks = append(interim.Networks, network)
}

func addHost(host map[string]interface{}, interim *Interim) {
	interim.UUIDToHost[host["uuid"].(string)] = host
}

func addDefault(def map[string]interface{}, interim *Interim) {
	interim.Default = def
}
<commit_msg>It is faster to regenerate than it is to copy<commit_after>package main

import (
	"fmt"
	"strings"
)

const version1 = "2015-07-25"
const version2 = "2015-12-19"
const version3 = "2016-07-29"

var (
	versionList = []string{version1, version2, version3}
)

func GenerateAnswers(data []map[string]interface{}) (Versions, error) {
	versions := make(map[string]Answers)

	for _, v := range versionList {
		// 1. generate interim data
		interim := &Interim{
			UUIDToService:                   make(map[string]map[string]interface{}),
			UUIDToContainer:                 make(map[string]map[string]interface{}),
			UUIDToStack:                     make(map[string]map[string]interface{}),
			UUIDToHost:                      make(map[string]map[string]interface{}),
			StackUUIDToServicesUUID:         make(map[string][]string),
			ServiceUUIDNameToContainersUUID: make(map[string][]string),
			ContainerUUIDToContainerLink:    make(map[string]map[string]interface{}),
			ServiceUUIDToServiceLink:        make(map[string]map[string]interface{}),
			Networks:                        []interface{}{},
			Default:                         make(map[string]interface{}),
		}

		for _, o := range data {
			processMetadataObject(o, interim)
		}
		// 2. Generate versions from temp data
		if err := generateVersions(interim, v, versions); err != nil {
			return nil, err
		}
	}

	//tag the latest
	versions["latest"] = versions[version3]
	return versions, nil
}

func generateVersions(interim *Interim, version string, versions Versions) error {
	versionedData, err := applyVersionToData(*interim, version)
	if err != nil {
		return err
	}
	addToVersions(versions, version, versionedData)
	return nil
}

func addToVersions(versions Versions, version string, versionedData *Interim) {
	answers := make(map[string]interface{})
	defaultAnswers := addDefaultToAnswers(answers, versionedData)
	addClientToAnswers(answers, defaultAnswers, versionedData)
	versions[version] = answers
}

func addClientToAnswers(answers Answers, defaultAnswers map[string]interface{}, versionedData *Interim) {
	for _, c := range versionedData.UUIDToContainer {
		if c["primary_ip"] == nil {
			continue
		}
		clientAnswers := make(map[string]interface{})
		self := make(map[string]interface{})
		self["container"] = c
		if c["stack_uuid"] != nil {
			self["stack"] = versionedData.UUIDToStack[c["stack_uuid"].(string)]
			self["service"] = versionedData.UUIDToService[getServiceUUID(c["service_uuid"].(string), c["service_name"].(string))]
		}
		if c["host_uuid"] != nil {
			self["host"] = versionedData.UUIDToHost[c["host_uuid"].(string)]
		}
		clientAnswers["self"] = self
		mergeDefaults(clientAnswers, defaultAnswers)
		answers[c["primary_ip"].(string)] = clientAnswers
	}
}

func mergeDefaults(clientAnswers map[string]interface{}, defaultAnswers map[string]interface{}) {
	for k, v := range defaultAnswers {
		_, exists := clientAnswers[k]
		if !exists {
			clientAnswers[k] = v
		}
	}
}

func addDefaultToAnswers(answers Answers, versionedData *Interim) map[string]interface{} {
	defaultAnswers := make(map[string]interface{})
	var containers []interface{}
	for _, c := range versionedData.UUIDToContainer {
		if _, ok := defaultAnswers["containers"]; ok {
			containers = defaultAnswers["containers"].([]interface{})
		}
		containers = append(containers, c)
	}
	defaultAnswers["containers"] = containers

	var stacks []interface{}
	for _, s := range versionedData.UUIDToStack {
		if _, ok := defaultAnswers["stacks"]; ok {
			stacks = defaultAnswers["stacks"].([]interface{})
		}
		stacks = append(stacks, s)
	}
	defaultAnswers["stacks"] = stacks

	var services []interface{}
	for _, s := range versionedData.UUIDToService {
		if _, ok := defaultAnswers["services"]; ok {
			services = defaultAnswers["services"].([]interface{})
		}
		services = append(services, s)
	}
	defaultAnswers["services"] = services

	var hosts []interface{}
	for _, h := range versionedData.UUIDToHost {
		if _, ok := defaultAnswers["hosts"]; ok {
			hosts = defaultAnswers["hosts"].([]interface{})
		}
		hosts = append(hosts, h)
	}
	defaultAnswers["hosts"] = hosts
	defaultAnswers["networks"] = versionedData.Networks

	if val, ok := versionedData.Default["version"]; ok {
		defaultAnswers["version"] = val
	}

	if selfVal, ok := versionedData.Default["self"]; ok {
		self := selfVal.(map[string]interface{})
		if hostVal, ok := self["host"]; ok {
			host := hostVal.(map[string]interface{})
			self["host"] = versionedData.UUIDToHost[host["uuid"].(string)]
		}
		defaultAnswers["self"] = self
	}

	answers[DEFAULT_KEY] = defaultAnswers
	return defaultAnswers
}

func applyVersionToData(modified Interim, version string) (*Interim, error) {
	// 1. Process containers
	for _, c := range modified.UUIDToContainer {
		switch version {
		case version3:
			if c["name"] != nil {
				c["name"] = strings.ToLower(c["name"].(string))
			}
			if c["service_name"] != nil {
				c["service_name"] = strings.ToLower(c["service_name"].(string))
			}
			if c["stack_name"] != nil {
				c["stack_name"] = strings.ToLower(c["stack_name"].(string))
			}
			if _, ok := c["ports"]; ok {
				// set port ip to 0.0.0.0 if not specified
				originalPorts := c["ports"].([]interface{})
				var newPorts []interface{}
				for _, p := range originalPorts {
					port := p.(string)
					splitted := strings.Split(port, ":")
					if len(splitted) == 3 {
						newPorts = append(newPorts, port)
					} else {
						port = fmt.Sprintf("0.0.0.0:%s", port)
						newPorts = append(newPorts, port)
					}
				}
				c["ports"] = newPorts
			}

		default:
			if _, ok := c["ports"]; ok {
				originalPorts := c["ports"].([]interface{})
				// set port ip to host's ip if not specified
				if len(originalPorts) > 0 {
					var newPorts []interface{}
					for _, p := range originalPorts {
						port := p.(string)
						splitted := strings.Split(port, ":")
						if len(splitted) == 3 && splitted[0] != "0.0.0.0" {
							newPorts = append(newPorts, port)
						} else {
							if len(splitted) == 3 {
								port = fmt.Sprintf("%s%s", c["host_ip"], strings.TrimPrefix(port, "0.0.0.0"))
							} else {
								port = fmt.Sprintf("%s:%s", c["host_ip"], port)
							}

							newPorts = append(newPorts, port)
						}
					}
					c["ports"] = newPorts
				}
			}
		}
		c["links"] = modified.ContainerUUIDToContainerLink[c["uuid"].(string)]
		//delete helper field (needed for the port)
		delete(c, "host_ip")
	}

	// 2. Process services
	for _, s := range modified.UUIDToService {
		sUUID := getServiceUUID(s["uuid"].(string), s["name"].(string))

		stackUUID := s["stack_uuid"].(string)
		// add itself to the stack list
		var svcUUIDs []string
		if _, ok := modified.StackUUIDToServicesUUID[stackUUID]; ok {
			svcUUIDs = modified.StackUUIDToServicesUUID[stackUUID]
		}
		svcUUIDs = append(svcUUIDs, getServiceUUID(s["uuid"].(string), s["name"].(string)))
		modified.StackUUIDToServicesUUID[stackUUID] = svcUUIDs
		var cs []interface{}
		var cNames []interface{}
		cUUIDs := modified.ServiceUUIDNameToContainersUUID[sUUID]
		if cUUIDs != nil {
			for _, cUUID := range cUUIDs {
				if c, ok := modified.UUIDToContainer[cUUID]; ok {
					cs = append(cs, c)
					cNames = append(cNames, c["name"].(string))
				}
			}
		}
		// add service links
		s["links"] = modified.ServiceUUIDToServiceLink[s["uuid"].(string)]
		switch version {
		case version1:
			s["containers"] = cNames
		case version2:
			s["containers"] = cs
		case version3:
			s["containers"] = cs
			s["name"] = strings.ToLower(s["name"].(string))
			s["stack_name"] = strings.ToLower(s["stack_name"].(string))
			s["primary_service_name"] = strings.ToLower(s["primary_service_name"].(string))
			if s["sidekicks"] != nil {
				sidekicks := s["sidekicks"].([]interface{})
				var lowercased []interface{}
				for _, sidekick := range sidekicks {
					lowercased = append(lowercased, strings.ToLower(sidekick.(string)))
				}
				s["sidekicks"] = lowercased
			}
			if s["links"] != nil {
				links := s["links"].(map[string]interface{})
				lowercased := make(map[string]interface{})
				for key, value := range links {
					lowercased[strings.ToLower(key)] = value
				}
				s["links"] = lowercased
			}
		}

		// populate stack/service info on container
		if cUUIDs != nil {
			for _, cUUID := range cUUIDs {
				if _, ok := modified.UUIDToContainer[cUUID]; ok {
					modified.UUIDToContainer[cUUID]["service_name"] = s["name"]
					modified.UUIDToContainer[cUUID]["service_uuid"] = s["uuid"]
					modified.UUIDToContainer[cUUID]["stack_name"] = s["stack_name"]
					modified.UUIDToContainer[cUUID]["stack_uuid"] = stackUUID
				}
			}
		}
	}

	// 3. Process stacks
	for _, s := range modified.UUIDToStack {
		var svcs []interface{}
		var svcsNames []interface{}
		svcsUUIDs := modified.StackUUIDToServicesUUID[s["uuid"].(string)]
		if svcsUUIDs != nil {
			for _, svcUUID := range svcsUUIDs {
				if svc, ok := modified.UUIDToService[svcUUID]; ok {
					svcs = append(svcs, svc)
					svcsNames = append(svcsNames, svc["name"].(string))
				}
			}
		}
		switch version {
		case version1:
			s["services"] = svcsNames
		case version2:
			s["services"] = svcs
		case version3:
			s["services"] = svcs
			s["name"] = strings.ToLower(s["name"].(string))
		}
	}

	// 4. process hosts
	for _, h := range modified.UUIDToHost {
		switch version {
		case version3:
			delete(h, "hostId")
		}
	}

	return &modified, nil
}

func processMetadataObject(o map[string]interface{}, interim *Interim) {
	if val, ok := o["metadata_kind"]; ok {
		switch val.(string) {
		case "container":
			addContainer(o, interim)
		case "stack":
			addStack(o, interim)
		case "network":
			addNetwork(o, interim)
		case "host":
			addHost(o, interim)
		case "defaultData":
			addDefault(o, interim)
		case "serviceContainerLink":
			addServiceContainerLink(o, interim)
		case "containerLink":
			addContainerLink(o, interim)
		case "serviceLink":
			addServiceLink(o, interim)
		case "service":
			addService(o, interim)
		}
	}
}

func addContainer(container map[string]interface{}, interim *Interim) {
	interim.UUIDToContainer[container["uuid"].(string)] = container
}

func addService(service map[string]interface{}, interim *Interim) {
	interim.UUIDToService[getServiceUUID(service["uuid"].(string), service["name"].(string))] = service
}

func addServiceContainerLink(link map[string]interface{}, interim *Interim) {
	UUID := getServiceUUID(link["service_uuid"].(string), link["service_name"].(string))
	var containerUUIDList []string
	if _, ok := interim.ServiceUUIDNameToContainersUUID[UUID]; ok {
		containerUUIDList = interim.ServiceUUIDNameToContainersUUID[UUID]
	}
	containerUUIDList = append(containerUUIDList, link["container_uuid"].(string))
	interim.ServiceUUIDNameToContainersUUID[UUID] = containerUUIDList
}

func addServiceLink(link map[string]interface{}, interim *Interim) {
	serviceUUID := link["service_uuid"].(string)
	links := make(map[string]interface{})
	if _, ok := interim.ServiceUUIDToServiceLink[serviceUUID]; ok {
		links = interim.ServiceUUIDToServiceLink[serviceUUID]
	}
	linkKey := link["key"].(string)
	links[linkKey] = link["value"].(string)

	interim.ServiceUUIDToServiceLink[serviceUUID] = links
}

func addContainerLink(link map[string]interface{}, interim *Interim) {
	containerUUID := link["container_uuid"].(string)
	links := make(map[string]interface{})
	if _, ok := interim.ContainerUUIDToContainerLink[containerUUID]; ok {
		links = interim.ContainerUUIDToContainerLink[containerUUID]
	}
	linkKey := link["key"].(string)
	links[linkKey] = link["value"].(string)

	interim.ContainerUUIDToContainerLink[containerUUID] = links
}

func getServiceUUID(UUID string, name string) string {
	return strings.ToLower(fmt.Sprintf("%s_%s", UUID, name))
}

func addStack(stack map[string]interface{}, interim *Interim) {
	interim.UUIDToStack[stack["uuid"].(string)] = stack
}

func addNetwork(network map[string]interface{}, interim *Interim) {
	interim.Networks = append(interim.Networks, network)
}

func addHost(host map[string]interface{}, interim *Interim) {
	interim.UUIDToHost[host["uuid"].(string)] = host
}

func addDefault(def map[string]interface{}, interim *Interim) {
	interim.Default = def
}
<|endoftext|>


<commit_before>package gorma

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/goadesign/goa/design"
	"github.com/goadesign/goa/goagen/codegen"
	"github.com/goadesign/goa/goagen/utils"
)

// Generator is the application code generator.
type Generator struct {
	genfiles   []string // Generated files
	outDir     string   // Absolute path to output directory
	target     string   // Target package name - "models" by default
	appPkg     string   // Generated goa app package name - "app" by default
	appPkgPath string   // Generated goa app package import path
}

// Generate is the generator entry point called by the meta generator.
func Generate() (files []string, err error) {
	var outDir, target, appPkg string

	set := flag.NewFlagSet("gorma", flag.PanicOnError)
	set.String("design", "", "")
	set.StringVar(&outDir, "out", "", "")
	set.StringVar(&target, "pkg", "models", "")
	set.StringVar(&appPkg, "app", "app", "")
	set.Parse(os.Args[2:])

	appPkgPath, err := codegen.PackagePath(filepath.Join(outDir, appPkg))
	if err != nil {
		return nil, fmt.Errorf("invalid app package: %s", err)
	}
	outDir = filepath.Join(outDir, target)

	g := &Generator{outDir: outDir, target: target, appPkg: appPkg, appPkgPath: appPkgPath}

	return g.Generate(design.Design)
}

// Generate the application code, implement codegen.Generator.
func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) {
	if api == nil {
		return nil, fmt.Errorf("missing API definition, make sure design.Design is properly initialized")
	}
	go utils.Catch(nil, func() { g.Cleanup() })
	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()
	if err := os.MkdirAll(g.outDir, 0755); err != nil {
		return nil, err
	}

	if err := g.generateUserTypes(g.outDir, api); err != nil {
		return g.genfiles, err
	}
	if err := g.generateUserHelpers(g.outDir, api); err != nil {
		return g.genfiles, err
	}

	return g.genfiles, nil
}

// Cleanup removes the entire "app" directory if it was created by this generator.
func (g *Generator) Cleanup() {
	if len(g.genfiles) == 0 {
		return
	}
	//os.RemoveAll(ModelOutputDir())
	g.genfiles = nil
}

// generateUserTypes iterates through the user types and generates the data structures and
// marshaling code.
func (g *Generator) generateUserTypes(outdir string, api *design.APIDefinition) error {
	var modelname, filename string
	err := GormaDesign.IterateStores(func(store *RelationalStoreDefinition) error {
		err := store.IterateModels(func(model *RelationalModelDefinition) error {
			modelname = strings.ToLower(codegen.Goify(model.ModelName, false))

			filename = fmt.Sprintf("%s.go", modelname)
			utFile := filepath.Join(outdir, filename)
			err := os.RemoveAll(utFile)
			if err != nil {
				fmt.Println(err)
			}
			utWr, err := NewUserTypesWriter(utFile)
			if err != nil {
				panic(err) // bug
			}
			title := fmt.Sprintf("%s: Models", api.Context())
			imports := []*codegen.ImportSpec{
				codegen.SimpleImport(g.appPkgPath),
				codegen.SimpleImport("time"),
				codegen.SimpleImport("github.com/goadesign/goa"),
				codegen.SimpleImport("github.com/jinzhu/gorm"),
				codegen.SimpleImport("golang.org/x/net/context"),
				codegen.SimpleImport("golang.org/x/net/context"),
				codegen.NewImport("uuid", "github.com/satori/go.uuid"),
			}

			if model.Cached {
				imp := codegen.NewImport("cache", "github.com/patrickmn/go-cache")
				imports = append(imports, imp)
				imp = codegen.SimpleImport("strconv")
				imports = append(imports, imp)
			}
			utWr.WriteHeader(title, g.target, imports)
			data := &UserTypeTemplateData{
				APIDefinition: api,
				UserType:      model,
				DefaultPkg:    g.target,
				AppPkg:        g.appPkgPath,
			}
			err = utWr.Execute(data)
			g.genfiles = append(g.genfiles, utFile)
			if err != nil {
				fmt.Println(err)
				return err
			}
			err = utWr.FormatCode()
			if err != nil {
				fmt.Println(err)
			}
			return err
		})
		return err
	})
	return err
}

// generateUserHelpers iterates through the user types and generates the data structures and
// marshaling code.
func (g *Generator) generateUserHelpers(outdir string, api *design.APIDefinition) error {
	var modelname, filename string
	err := GormaDesign.IterateStores(func(store *RelationalStoreDefinition) error {
		err := store.IterateModels(func(model *RelationalModelDefinition) error {
			modelname = strings.ToLower(codegen.Goify(model.ModelName, false))

			filename = fmt.Sprintf("%s_helper.go", modelname)
			utFile := filepath.Join(outdir, filename)
			err := os.RemoveAll(utFile)
			if err != nil {
				fmt.Println(err)
			}
			utWr, err := NewUserHelperWriter(utFile)
			if err != nil {
				panic(err) // bug
			}
			title := fmt.Sprintf("%s: Model Helpers", api.Context())
			imports := []*codegen.ImportSpec{
				codegen.SimpleImport(g.appPkgPath),
				codegen.SimpleImport("time"),
				codegen.SimpleImport("github.com/goadesign/goa"),
				codegen.SimpleImport("github.com/jinzhu/gorm"),
				codegen.SimpleImport("golang.org/x/net/context"),
				codegen.SimpleImport("golang.org/x/net/context"),
				codegen.NewImport("uuid", "github.com/satori/go.uuid"),
			}

			if model.Cached {
				imp := codegen.NewImport("cache", "github.com/patrickmn/go-cache")
				imports = append(imports, imp)
				imp = codegen.SimpleImport("strconv")
				imports = append(imports, imp)
			}
			utWr.WriteHeader(title, g.target, imports)
			data := &UserTypeTemplateData{
				APIDefinition: api,
				UserType:      model,
				DefaultPkg:    g.target,
				AppPkg:        g.appPkgPath,
			}
			err = utWr.Execute(data)
			g.genfiles = append(g.genfiles, utFile)
			if err != nil {
				fmt.Println(err)
				return err
			}
			err = utWr.FormatCode()
			if err != nil {
				fmt.Println(err)
			}
			return err
		})
		return err
	})
	return err
}
<commit_msg>Update UUID import<commit_after>package gorma

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/goadesign/goa/design"
	"github.com/goadesign/goa/goagen/codegen"
	"github.com/goadesign/goa/goagen/utils"
)

// Generator is the application code generator.
type Generator struct {
	genfiles   []string // Generated files
	outDir     string   // Absolute path to output directory
	target     string   // Target package name - "models" by default
	appPkg     string   // Generated goa app package name - "app" by default
	appPkgPath string   // Generated goa app package import path
}

// Generate is the generator entry point called by the meta generator.
func Generate() (files []string, err error) {
	var outDir, target, appPkg string

	set := flag.NewFlagSet("gorma", flag.PanicOnError)
	set.String("design", "", "")
	set.StringVar(&outDir, "out", "", "")
	set.StringVar(&target, "pkg", "models", "")
	set.StringVar(&appPkg, "app", "app", "")
	set.Parse(os.Args[2:])

	appPkgPath, err := codegen.PackagePath(filepath.Join(outDir, appPkg))
	if err != nil {
		return nil, fmt.Errorf("invalid app package: %s", err)
	}
	outDir = filepath.Join(outDir, target)

	g := &Generator{outDir: outDir, target: target, appPkg: appPkg, appPkgPath: appPkgPath}

	return g.Generate(design.Design)
}

// Generate the application code, implement codegen.Generator.
func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) {
	if api == nil {
		return nil, fmt.Errorf("missing API definition, make sure design.Design is properly initialized")
	}
	go utils.Catch(nil, func() { g.Cleanup() })
	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()
	if err := os.MkdirAll(g.outDir, 0755); err != nil {
		return nil, err
	}

	if err := g.generateUserTypes(g.outDir, api); err != nil {
		return g.genfiles, err
	}
	if err := g.generateUserHelpers(g.outDir, api); err != nil {
		return g.genfiles, err
	}

	return g.genfiles, nil
}

// Cleanup removes the entire "app" directory if it was created by this generator.
func (g *Generator) Cleanup() {
	if len(g.genfiles) == 0 {
		return
	}
	//os.RemoveAll(ModelOutputDir())
	g.genfiles = nil
}

// generateUserTypes iterates through the user types and generates the data structures and
// marshaling code.
func (g *Generator) generateUserTypes(outdir string, api *design.APIDefinition) error {
	var modelname, filename string
	err := GormaDesign.IterateStores(func(store *RelationalStoreDefinition) error {
		err := store.IterateModels(func(model *RelationalModelDefinition) error {
			modelname = strings.ToLower(codegen.Goify(model.ModelName, false))

			filename = fmt.Sprintf("%s.go", modelname)
			utFile := filepath.Join(outdir, filename)
			err := os.RemoveAll(utFile)
			if err != nil {
				fmt.Println(err)
			}
			utWr, err := NewUserTypesWriter(utFile)
			if err != nil {
				panic(err) // bug
			}
			title := fmt.Sprintf("%s: Models", api.Context())
			imports := []*codegen.ImportSpec{
				codegen.SimpleImport(g.appPkgPath),
				codegen.SimpleImport("time"),
				codegen.SimpleImport("github.com/goadesign/goa"),
				codegen.SimpleImport("github.com/jinzhu/gorm"),
				codegen.SimpleImport("golang.org/x/net/context"),
				codegen.SimpleImport("golang.org/x/net/context"),
				codegen.SimpleImport("github.com/goadesign/goa/uuid"),
			}

			if model.Cached {
				imp := codegen.NewImport("cache", "github.com/patrickmn/go-cache")
				imports = append(imports, imp)
				imp = codegen.SimpleImport("strconv")
				imports = append(imports, imp)
			}
			utWr.WriteHeader(title, g.target, imports)
			data := &UserTypeTemplateData{
				APIDefinition: api,
				UserType:      model,
				DefaultPkg:    g.target,
				AppPkg:        g.appPkgPath,
			}
			err = utWr.Execute(data)
			g.genfiles = append(g.genfiles, utFile)
			if err != nil {
				fmt.Println(err)
				return err
			}
			err = utWr.FormatCode()
			if err != nil {
				fmt.Println(err)
			}
			return err
		})
		return err
	})
	return err
}

// generateUserHelpers iterates through the user types and generates the data structures and
// marshaling code.
func (g *Generator) generateUserHelpers(outdir string, api *design.APIDefinition) error {
	var modelname, filename string
	err := GormaDesign.IterateStores(func(store *RelationalStoreDefinition) error {
		err := store.IterateModels(func(model *RelationalModelDefinition) error {
			modelname = strings.ToLower(codegen.Goify(model.ModelName, false))

			filename = fmt.Sprintf("%s_helper.go", modelname)
			utFile := filepath.Join(outdir, filename)
			err := os.RemoveAll(utFile)
			if err != nil {
				fmt.Println(err)
			}
			utWr, err := NewUserHelperWriter(utFile)
			if err != nil {
				panic(err) // bug
			}
			title := fmt.Sprintf("%s: Model Helpers", api.Context())
			imports := []*codegen.ImportSpec{
				codegen.SimpleImport(g.appPkgPath),
				codegen.SimpleImport("time"),
				codegen.SimpleImport("github.com/goadesign/goa"),
				codegen.SimpleImport("github.com/jinzhu/gorm"),
				codegen.SimpleImport("golang.org/x/net/context"),
				codegen.SimpleImport("golang.org/x/net/context"),
				codegen.SimpleImport("github.com/goadesign/goa/uuid"),
			}

			if model.Cached {
				imp := codegen.NewImport("cache", "github.com/patrickmn/go-cache")
				imports = append(imports, imp)
				imp = codegen.SimpleImport("strconv")
				imports = append(imports, imp)
			}
			utWr.WriteHeader(title, g.target, imports)
			data := &UserTypeTemplateData{
				APIDefinition: api,
				UserType:      model,
				DefaultPkg:    g.target,
				AppPkg:        g.appPkgPath,
			}
			err = utWr.Execute(data)
			g.genfiles = append(g.genfiles, utFile)
			if err != nil {
				fmt.Println(err)
				return err
			}
			err = utWr.FormatCode()
			if err != nil {
				fmt.Println(err)
			}
			return err
		})
		return err
	})
	return err
}
<|endoftext|>


<commit_before>/*
Copyright 2014 Pinterest.com

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 http

import (
	"io"
	"net/http"

	"github.com/pinterest/bender"
)

type HttpBodyValidator func(request interface{}, body io.ReadCloser) error

func CreateHttpExecutor(tr *http.Transport, client *http.Client, bodyValidator HttpBodyValidator) bender.RequestExecutor {
	if tr == nil {
		tr = &http.Transport{}
		client = &http.Client{Transport: tr}
	} else if client == nil {
		client = &http.Client{Transport: tr}
	}

	return func(_ int64, request interface{}) (interface{}, error) {
		req := request.(*http.Request)
		resp, err := client.Do(req)
		if err != nil {
			return nil, err
		}
		defer resp.Body.Close()
		err = bodyValidator(request, resp.Body)
		if err != nil {
			return nil, err
		}
		return resp, nil
	}
}
<commit_msg>check response was more useful than check response.body.<commit_after>/*
Copyright 2014 Pinterest.com

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 http

import (
	"net/http"

	"github.com/pinterest/bender"
)

type HttpResponseValidator func(request interface{}, resp *http.Response) error

func CreateHttpExecutor(tr *http.Transport, client *http.Client, responseValidator HttpResponseValidator) bender.RequestExecutor {
	if tr == nil {
		tr = &http.Transport{}
		client = &http.Client{Transport: tr}
	} else if client == nil {
		client = &http.Client{Transport: tr}
	}

	return func(_ int64, request interface{}) (interface{}, error) {
		req := request.(*http.Request)
		resp, err := client.Do(req)
		if err != nil {
			return nil, err
		}
		err = responseValidator(request, resp)
		if err != nil {
			return nil, err
		}
		return resp, nil
	}
}
<|endoftext|>


<commit_before>package http

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

// ReturnJson return json response with provided struct v
func ReturnJson(w http.ResponseWriter, v interface{}) error {
	w.Header().Set("Content-Type", "application/json")

	js, err := json.MarshalIndent(v, "", "\t")
	fmt.Fprint(w, string(js))

	return err
}

func ReturnAcceptJsonOrText(w http.ResponseWriter, r *http.Request, plainText string, jsonResp interface{}) error {
	h := r.Header
	accept := h.Get("Accept")
	if strings.HasPrefix(accept, "application/json") {
		return ReturnJson(w, jsonResp)
	}

	fmt.Fprint(w, plainText)
	return nil
}

// GetUrl fetch an url request with GET-Method. If a nil httpClient is
// provided, http.DefaultClient will be used.
// Returned the response as string
func GetUrl(client *http.Client, u string) string {
	if client == nil {
		client = http.DefaultClient
	}
	resp, err := client.Get(u)
	if err != nil {
		fmt.Println(err.Error())
		return err.Error()
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err.Error())
	}
	return string(body)
}

func GetJson(client *http.Client, url string, v interface{}) error {
	if client == nil {
		client = http.DefaultClient
	}
	resp, err := client.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	d := json.NewDecoder(resp.Body)

	return d.Decode(v)
}
<commit_msg>Add charset to Content-Type when response json<commit_after>package http

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

// ReturnJson return json response with provided struct v
func ReturnJson(w http.ResponseWriter, v interface{}) error {
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	js, err := json.MarshalIndent(v, "", "\t")
	fmt.Fprint(w, string(js))

	return err
}

func ReturnAcceptJsonOrText(w http.ResponseWriter, r *http.Request, plainText string, jsonResp interface{}) error {
	h := r.Header
	accept := h.Get("Accept")
	if strings.HasPrefix(accept, "application/json") {
		return ReturnJson(w, jsonResp)
	}

	fmt.Fprint(w, plainText)
	return nil
}

// GetUrl fetch an url request with GET-Method. If a nil httpClient is
// provided, http.DefaultClient will be used.
// Returned the response as string
func GetUrl(client *http.Client, u string) string {
	if client == nil {
		client = http.DefaultClient
	}
	resp, err := client.Get(u)
	if err != nil {
		fmt.Println(err.Error())
		return err.Error()
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err.Error())
	}
	return string(body)
}

func GetJson(client *http.Client, url string, v interface{}) error {
	if client == nil {
		client = http.DefaultClient
	}
	resp, err := client.Get(url)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	d := json.NewDecoder(resp.Body)

	return d.Decode(v)
}
<|endoftext|>


<commit_before>package service

import (
	"io"
	"os"
	"sync"

	pdebug "github.com/lestrrat/go-pdebug"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"
	"google.golang.org/cloud"
	"google.golang.org/cloud/storage"
)

func defaultGoogleStorageClient(ctx context.Context) (*storage.Client, error) {
	tokesrc, err := google.DefaultTokenSource(ctx, storage.ScopeFullControl)
	if err != nil {
		return nil, errors.Wrap(err, "failed to get default token source for storage client")
	}

	client, err := storage.NewClient(ctx, cloud.WithTokenSource(tokesrc))
	if err != nil {
		return nil, errors.Wrap(err, "failed to create storage client")
	}
	return client, nil
}

type CallOption interface {
	Get() interface{}
}

type WithObjectAttrs storage.ObjectAttrs
type WithQueryPrefix string

func (attr WithObjectAttrs) Get() interface{} {
	return storage.ObjectAttrs(attr)
}

func (p WithQueryPrefix) Get() interface{} {
	return string(p)
}

type ObjectList interface {
	Next() bool
	Object() interface{}
	Error() error
}

type StorageClient interface {
	URLFor(string) string
	List(ctx context.Context, options ...CallOption) (ObjectList, error)
	Move(ctx context.Context, src, dst string, options ...CallOption) error
	Upload(ctx context.Context, name string, src io.Reader, options ...CallOption) error
	DeleteObjects(ctx context.Context, list ObjectList) error
}

type GoogleStorageClient struct {
	bucketOnce sync.Once
	clientOnce sync.Once
	BucketName string
	Client     *storage.Client
}

func (c *GoogleStorageClient) GetBucketName() string {
	c.bucketOnce.Do(func() {
		if c.BucketName == "" {
			c.BucketName = os.Getenv("GOOGLE_STORAGE_MEDIA_BUCKET")
		}
	})
	return c.BucketName
}

func (c *GoogleStorageClient) GetClient(ctx context.Context) *storage.Client {
	c.clientOnce.Do(func() {
		if c.Client == nil {
			client, err := defaultGoogleStorageClient(ctx)
			if err != nil {
				panic(err.Error())
			}
			c.Client = client
		}
	})
	return c.Client
}

func (c *GoogleStorageClient) URLFor(fragment string) string {
	bucketName := c.GetBucketName()
	return "http://storage.googleapis.com/" + bucketName + "/" + fragment
}

func (c *GoogleStorageClient) Move(ctx context.Context, srcName, dstName string, options ...CallOption) error {
	storagecl := c.GetClient(ctx)
	bucketName := c.GetBucketName()
	src := storagecl.Bucket(bucketName).Object(srcName)
	dst := storagecl.Bucket(bucketName).Object(dstName)

	if pdebug.Enabled {
		pdebug.Printf("Copying %s to %s", srcName, dstName)
	}

	attrs, err := src.Attrs(ctx)
	if err != nil {
		return errors.Wrapf(err, "failed to fetch object attrs for '%s'", srcName)
	}

	if _, err = src.CopyTo(ctx, dst, attrs); err != nil {
		return errors.Wrapf(err, "failed to copy from '%s' to '%s'", srcName, dstName)
	}

	if pdebug.Enabled {
		pdebug.Printf("Deleting %s", srcName)
	}
	if err := src.Delete(ctx); err != nil {
		return errors.Wrapf(err, "failed to delete '%s'", src)
	}
	return nil
}

func (c *GoogleStorageClient) Upload(ctx context.Context, name string, src io.Reader, options ...CallOption) error {
	var attrs storage.ObjectAttrs
	for _, option := range options {
		switch option.(type) {
		case WithObjectAttrs:
			attrs = option.Get().(storage.ObjectAttrs)
		}
	}

	storagecl := c.GetClient(ctx)
	wc := storagecl.Bucket(c.GetBucketName()).Object(name).NewWriter(ctx)
	wc.ObjectAttrs = attrs

	if pdebug.Enabled {
		pdebug.Printf("Writing to %s", name)
	}

	if _, err := io.Copy(wc, src); err != nil {
		return errors.Wrap(err, "failed to write data to temporary location")
	}
	// Note: DO NOT defer wc.Close(), as it's part of the write operation.
	// If wc.Close() does not complete w/o errors. the write failed
	if err := wc.Close(); err != nil {
		return errors.Wrap(err, "failed to write data to temporary location")
	}

	return nil
}

type GoogleStorageObjectList struct {
	elements <-chan interface{}
	err      error
	mu       sync.Mutex
	next     interface{}
}

func (l *GoogleStorageObjectList) Object() interface{} {
	l.mu.Lock()
	defer l.mu.Unlock()
	return l.next
}

func (l *GoogleStorageObjectList) Error() error {
	l.mu.Lock()
	defer l.mu.Unlock()
	return l.err
}

func (l *GoogleStorageObjectList) Next() bool {
	select {
	case next, ok := <-l.elements:
		l.mu.Lock()
		defer l.mu.Unlock()
		if !ok {
			l.elements = nil
			l.next = nil
			return false
		}

		if e, ok := next.(error); ok {
			l.err = e
			return false
		}
		l.next = next
		return true
	default:
		return false
	}
}

func (c *GoogleStorageClient) List(ctx context.Context, options ...CallOption) (ObjectList, error) {
	var q *storage.Query
	if len(options) > 0 {
		q = &storage.Query{}
	}

	for _, option := range options {
		switch option.(type) {
		case WithQueryPrefix:
			q.Prefix = option.Get().(string)
		}
	}

	out := make(chan interface{})
	go func() {
		defer close(out)
		storagecl := c.GetClient(ctx)
		b := storagecl.Bucket(c.GetBucketName())
		for q != nil {
			objects, err := b.List(ctx, q)
			if err != nil {
				return
			}

			for _, object := range objects.Results {
				out <- object
			}

			q = objects.Next
		}
	}()

	return &GoogleStorageObjectList{
		elements: out,
	}, nil
}

func (c *GoogleStorageClient) DeleteObjects(ctx context.Context, objects ObjectList) error {
	storagecl := c.GetClient(ctx)
	for objects.Next() {
		attrs, ok := objects.Object().(*storage.ObjectAttrs)
		if !ok {
			continue
		}
		if pdebug.Enabled {
			pdebug.Printf("Deleting object '%s'", attrs.Name)
		}
		if err := storagecl.Bucket(attrs.Bucket).Object(attrs.Name).Delete(ctx); err != nil {
			if pdebug.Enabled {
				pdebug.Printf("Failed to delete '%s': %s", attrs.Name, err)
			}
			return errors.Wrap(err, "failed to delete object")
		}
	}
	return nil
}
<commit_msg>Add debug statements<commit_after>package service

import (
	"io"
	"os"
	"sync"

	pdebug "github.com/lestrrat/go-pdebug"
	"github.com/pkg/errors"
	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"
	"google.golang.org/cloud"
	"google.golang.org/cloud/storage"
)

func defaultGoogleStorageClient(ctx context.Context) (*storage.Client, error) {
	tokesrc, err := google.DefaultTokenSource(ctx, storage.ScopeFullControl)
	if err != nil {
		return nil, errors.Wrap(err, "failed to get default token source for storage client")
	}

	client, err := storage.NewClient(ctx, cloud.WithTokenSource(tokesrc))
	if err != nil {
		return nil, errors.Wrap(err, "failed to create storage client")
	}
	return client, nil
}

type CallOption interface {
	Get() interface{}
}

type WithObjectAttrs storage.ObjectAttrs
type WithQueryPrefix string

func (attr WithObjectAttrs) Get() interface{} {
	return storage.ObjectAttrs(attr)
}

func (p WithQueryPrefix) Get() interface{} {
	return string(p)
}

type ObjectList interface {
	Next() bool
	Object() interface{}
	Error() error
}

type StorageClient interface {
	URLFor(string) string
	List(ctx context.Context, options ...CallOption) (ObjectList, error)
	Move(ctx context.Context, src, dst string, options ...CallOption) error
	Upload(ctx context.Context, name string, src io.Reader, options ...CallOption) error
	DeleteObjects(ctx context.Context, list ObjectList) error
}

type GoogleStorageClient struct {
	bucketOnce sync.Once
	clientOnce sync.Once
	BucketName string
	Client     *storage.Client
}

func (c *GoogleStorageClient) GetBucketName() string {
	c.bucketOnce.Do(func() {
		if c.BucketName == "" {
			c.BucketName = os.Getenv("GOOGLE_STORAGE_MEDIA_BUCKET")
		}
	})
	return c.BucketName
}

func (c *GoogleStorageClient) GetClient(ctx context.Context) *storage.Client {
	c.clientOnce.Do(func() {
		if c.Client == nil {
			client, err := defaultGoogleStorageClient(ctx)
			if err != nil {
				panic(err.Error())
			}
			c.Client = client
		}
	})
	return c.Client
}

func (c *GoogleStorageClient) URLFor(fragment string) string {
	bucketName := c.GetBucketName()
	return "http://storage.googleapis.com/" + bucketName + "/" + fragment
}

func (c *GoogleStorageClient) Move(ctx context.Context, srcName, dstName string, options ...CallOption) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("service.GoogleStorageClient.Move").BindError(&err)
		defer g.End()
	}
	storagecl := c.GetClient(ctx)
	bucketName := c.GetBucketName()
	src := storagecl.Bucket(bucketName).Object(srcName)
	dst := storagecl.Bucket(bucketName).Object(dstName)

	if pdebug.Enabled {
		pdebug.Printf("Copying %s to %s", srcName, dstName)
	}

	attrs, err := src.Attrs(ctx)
	if err != nil {
		return errors.Wrapf(err, "failed to fetch object attrs for '%s'", srcName)
	}

	if _, err = src.CopyTo(ctx, dst, attrs); err != nil {
		return errors.Wrapf(err, "failed to copy from '%s' to '%s'", srcName, dstName)
	}

	if pdebug.Enabled {
		pdebug.Printf("Deleting %s", srcName)
	}
	if err := src.Delete(ctx); err != nil {
		return errors.Wrapf(err, "failed to delete '%s'", src)
	}
	return nil
}

func (c *GoogleStorageClient) Upload(ctx context.Context, name string, src io.Reader, options ...CallOption) (err error) {
	if pdebug.Enabled {
		g := pdebug.Marker("service.GoogleStorageClient.Upload").BindError(&err)
		defer g.End()
	}
	var attrs storage.ObjectAttrs
	for _, option := range options {
		switch option.(type) {
		case WithObjectAttrs:
			attrs = option.Get().(storage.ObjectAttrs)
		}
	}

	storagecl := c.GetClient(ctx)
	wc := storagecl.Bucket(c.GetBucketName()).Object(name).NewWriter(ctx)
	wc.ObjectAttrs = attrs

	if pdebug.Enabled {
		pdebug.Printf("Writing to %s", name)
	}

	if _, err := io.Copy(wc, src); err != nil {
		return errors.Wrap(err, "failed to write data to temporary location")
	}
	// Note: DO NOT defer wc.Close(), as it's part of the write operation.
	// If wc.Close() does not complete w/o errors. the write failed
	if err := wc.Close(); err != nil {
		return errors.Wrap(err, "failed to write data to temporary location")
	}

	return nil
}

type GoogleStorageObjectList struct {
	elements <-chan interface{}
	err      error
	mu       sync.Mutex
	next     interface{}
}

func (l *GoogleStorageObjectList) Object() interface{} {
	l.mu.Lock()
	defer l.mu.Unlock()
	return l.next
}

func (l *GoogleStorageObjectList) Error() error {
	l.mu.Lock()
	defer l.mu.Unlock()
	return l.err
}

func (l *GoogleStorageObjectList) Next() bool {
	select {
	case next, ok := <-l.elements:
		l.mu.Lock()
		defer l.mu.Unlock()
		if !ok {
			l.elements = nil
			l.next = nil
			return false
		}

		if e, ok := next.(error); ok {
			l.err = e
			return false
		}
		l.next = next
		return true
	default:
		return false
	}
}

func (c *GoogleStorageClient) List(ctx context.Context, options ...CallOption) (ObjectList, error) {
	var q *storage.Query
	if len(options) > 0 {
		q = &storage.Query{}
	}

	for _, option := range options {
		switch option.(type) {
		case WithQueryPrefix:
			q.Prefix = option.Get().(string)
		}
	}

	out := make(chan interface{})
	go func() {
		defer close(out)
		storagecl := c.GetClient(ctx)
		b := storagecl.Bucket(c.GetBucketName())
		for q != nil {
			objects, err := b.List(ctx, q)
			if err != nil {
				return
			}

			for _, object := range objects.Results {
				out <- object
			}

			q = objects.Next
		}
	}()

	return &GoogleStorageObjectList{
		elements: out,
	}, nil
}

func (c *GoogleStorageClient) DeleteObjects(ctx context.Context, objects ObjectList) error {
	storagecl := c.GetClient(ctx)
	for objects.Next() {
		attrs, ok := objects.Object().(*storage.ObjectAttrs)
		if !ok {
			continue
		}
		if pdebug.Enabled {
			pdebug.Printf("Deleting object '%s'", attrs.Name)
		}
		if err := storagecl.Bucket(attrs.Bucket).Object(attrs.Name).Delete(ctx); err != nil {
			if pdebug.Enabled {
				pdebug.Printf("Failed to delete '%s': %s", attrs.Name, err)
			}
			return errors.Wrap(err, "failed to delete object")
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package geo

import (
	"encoding/binary"
	"encoding/csv"
	"fmt"
	log "github.com/Lafeng/deblocus/golang/glog"
	"io"
	"net"
	"os"
	"strconv"
	"strings"
)

const (
	GEO2_LOC_FILE  = "GeoLite2-Country-Locations-en.csv"
	GEO2_IPV4_FILE = "GeoLite2-Country-Blocks-IPv4.csv"
)

type GeoLite2Reader struct {
	ipv4fp       *os.File
	locfp        *os.File
	CountryCode  map[int]string
	Count        int
	RelativePath string
}

func (r *GeoLite2Reader) Iter(callback func(fields []string)) (e error) {
	r.locfp, e = os.Open(r.RelativePath + GEO2_LOC_FILE)
	if e != nil {
		return e
	}
	defer r.locfp.Close()
	var countryCode = make(map[int]string)
	for rd := csv.NewReader(r.locfp); ; {
		row, e := rd.Read()
		if e != nil {
			break
		}
		id, _ := strconv.Atoi(row[0]) // geoname_id
		if _, y := countryCode[id]; !y {
			countryCode[id] = row[4] // country_iso_code
		}
	}
	r.CountryCode = countryCode
	r.ipv4fp, e = os.Open(r.RelativePath + GEO2_IPV4_FILE)
	if e != nil {
		return e
	}
	defer r.ipv4fp.Close()
	rd := csv.NewReader(r.ipv4fp)
	rd.Read() // skip first line
	var (
		i      = 0
		fields []string
	)
	for ; ; i++ {
		fields, e = rd.Read()
		if e != nil || fields == nil {
			if e == io.EOF {
				e = nil
			}
			break
		}
		callback(fields)
	}
	r.Count = i
	return
}

type GeoIPFilter struct {
	tab     *routingTable
	keyword string
}

func NewGeoIPFilter(keyword string) (f *GeoIPFilter, e error) {
	if len(keyword) != 2 {
		return nil, fmt.Errorf("filter keyword must be 2-byte country_iso_code")
	}
	var db = buildGeoDB()
	var size = len(db) / 6
	entries := make(entrySet, size)
	for i := 0; i < size; i++ {
		j := i * 6
		entries[i] = &entry{
			data:    binary.BigEndian.Uint32(db[j : j+4]),
			len:     uint32(db[j+4]),
			nexthop: string(db[j+5 : j+6]),
		}
	}
	f = new(GeoLite2Reader)
	f.keyword = strings.ToUpper(keyword)
	f.tab = buildRoutingTable(entries)
	if log.V(1) {
		log.Infoln("Init GeoIPFilter with target keyword", keyword)
	}
	return
}

func (f *GeoIPFilter) Filter(host string) bool {
	ipAddr, e := net.ResolveIPAddr("ip4", host)
	if e != nil {
		return false
	}

	// net.IP is 16-byte, ipv4.addr at 12-15
	ip := binary.BigEndian.Uint32(ipAddr.IP[12:])
	if nexthop, y := f.tab.Find(ip); y {
		return nexthop == f.keyword
	}
	return false
}

/*
 CIDR utils
*/
// parse 10-bit cidr literal to binary ip/mask
func ParseCIDR(s string) (ip, m uint32) {
	for _, c := range []byte(s) {
		if d := c - 0x30; d >= 0 && d <= 9 { // number
			m = m*10 + uint32(d)
		} else if c == '.' || c == '/' {
			ip, m = (ip<<8)|m, 0
		} else if c == ' ' { // space
			continue
		} else { // exception
			return
		}
	}
	return
}

var mask32 uint32 = 0xffffffff

func RangeCIDR(s string) (uint32, uint32) {
	ip_start, m := ParseCIDR(s)
	ip_start = ip_start >> (32 - m) << (32 - m)
	ip_end := ip_start | (mask32 >> m)
	return ip_start, ip_end
}

func IPv4Itoa(ip uint32) string {
	i, b := uint64(ip), 10
	return strconv.FormatUint(i>>24, b) + "." +
		strconv.FormatUint(i>>16&0xff, b) + "." +
		strconv.FormatUint(i>>8&0xff, b) + "." +
		strconv.FormatUint(i&0xff, b)
}
<commit_msg>fix geoip nil pointer<commit_after>package geo

import (
	"encoding/binary"
	"encoding/csv"
	"fmt"
	log "github.com/Lafeng/deblocus/golang/glog"
	"io"
	"net"
	"os"
	"strconv"
	"strings"
)

const (
	GEO2_LOC_FILE  = "GeoLite2-Country-Locations-en.csv"
	GEO2_IPV4_FILE = "GeoLite2-Country-Blocks-IPv4.csv"
)

type GeoLite2Reader struct {
	ipv4fp       *os.File
	locfp        *os.File
	CountryCode  map[int]string
	Count        int
	RelativePath string
}

func (r *GeoLite2Reader) Iter(callback func(fields []string)) (e error) {
	r.locfp, e = os.Open(r.RelativePath + GEO2_LOC_FILE)
	if e != nil {
		return e
	}
	defer r.locfp.Close()
	var countryCode = make(map[int]string)
	for rd := csv.NewReader(r.locfp); ; {
		row, e := rd.Read()
		if e != nil {
			break
		}
		id, _ := strconv.Atoi(row[0]) // geoname_id
		if _, y := countryCode[id]; !y {
			countryCode[id] = row[4] // country_iso_code
		}
	}
	r.CountryCode = countryCode
	r.ipv4fp, e = os.Open(r.RelativePath + GEO2_IPV4_FILE)
	if e != nil {
		return e
	}
	defer r.ipv4fp.Close()
	rd := csv.NewReader(r.ipv4fp)
	rd.Read() // skip first line
	var (
		i      = 0
		fields []string
	)
	for ; ; i++ {
		fields, e = rd.Read()
		if e != nil || fields == nil {
			if e == io.EOF {
				e = nil
			}
			break
		}
		callback(fields)
	}
	r.Count = i
	return
}

type GeoIPFilter struct {
	tab     *routingTable
	keyword string
}

func NewGeoIPFilter(keyword string) (f *GeoIPFilter, e error) {
	if len(keyword) != 2 {
		return nil, fmt.Errorf("filter keyword must be 2-byte country_iso_code")
	}
	var db = buildGeoDB()
	var size = len(db) / 6
	entries := make(entrySet, size)
	for i := 0; i < size; i++ {
		j := i * 6
		entries[i] = &entry{
			data:    binary.BigEndian.Uint32(db[j : j+4]),
			len:     uint32(db[j+4]),
			nexthop: string(db[j+5 : j+6]),
		}
	}
	f = new(GeoIPFilter)
	f.keyword = strings.ToUpper(keyword)
	f.tab = buildRoutingTable(entries)
	if log.V(1) {
		log.Infoln("Init GeoIPFilter with target keyword", keyword)
	}
	return
}

func (f *GeoIPFilter) Filter(host string) bool {
	ipAddr, e := net.ResolveIPAddr("ip4", host)
	if e != nil {
		return false
	}

	// net.IP is 16-byte, ipv4.addr at 12-15
	ip := binary.BigEndian.Uint32(ipAddr.IP[12:])
	if nexthop, y := f.tab.Find(ip); y {
		return nexthop == f.keyword
	}
	return false
}

/*
 CIDR utils
*/
// parse 10-bit cidr literal to binary ip/mask
func ParseCIDR(s string) (ip, m uint32) {
	for _, c := range []byte(s) {
		if d := c - 0x30; d >= 0 && d <= 9 { // number
			m = m*10 + uint32(d)
		} else if c == '.' || c == '/' {
			ip, m = (ip<<8)|m, 0
		} else if c == ' ' { // space
			continue
		} else { // exception
			return
		}
	}
	return
}

var mask32 uint32 = 0xffffffff

func RangeCIDR(s string) (uint32, uint32) {
	ip_start, m := ParseCIDR(s)
	ip_start = ip_start >> (32 - m) << (32 - m)
	ip_end := ip_start | (mask32 >> m)
	return ip_start, ip_end
}

func IPv4Itoa(ip uint32) string {
	i, b := uint64(ip), 10
	return strconv.FormatUint(i>>24, b) + "." +
		strconv.FormatUint(i>>16&0xff, b) + "." +
		strconv.FormatUint(i>>8&0xff, b) + "." +
		strconv.FormatUint(i&0xff, b)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
)

type ignoreFetcher struct {
	baseUrl string
}

func (fetcher *ignoreFetcher) NamesToUrls(namesChannel chan string, urlsChannel chan string) {
	for name := range namesChannel {
		url := fetcher.NameToUrl(name)
		urlsChannel <- url
	}
	close(urlsChannel)
}

func (fetcher *ignoreFetcher) NameToUrl(name string) string {
	return fetcher.baseUrl + "/" + name + ".gitignore"
}

func getNames(names []string, namesChannel chan string) {
	for _, v := range names {
		namesChannel <- v
	}
	close(namesChannel)
}

func getNamesFromFile(f *os.File) []string {
	var a []string
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		a = append(a, scanner.Text())
	}
	return a
}

func FetchIgnoreFiles(urlsChannel chan string, contentChannel chan string) error {
	var err error = nil
	for url := range urlsChannel {
		response, err := http.Get(url)
		if err != nil {
			close(contentChannel)
			return err
		}
		content, err := getContent(response.Body)
		if err != nil {
			close(contentChannel)
			return err
		}
		contentChannel <- content
	}
	close(contentChannel)
	return err
}

func getContent(body io.ReadCloser) (string, error) {
	var err error = nil
	output := ""
	scanner := bufio.NewScanner(body)
	for scanner.Scan() {
		output = output + fmt.Sprintln(scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
	return output, err
}

func writeContent(f *os.File, contentChannel chan string) error {
	var err error = nil
	for content := range contentChannel {
		_, err := f.WriteString(content)
		if err != nil {
			fmt.Fprintln(os.Stderr, "writing output:", err)
			return err
		}
	}
	return err
}

func main() {
	fetcher := ignoreFetcher{baseUrl: "https://raw.githubusercontent.com/github/gitignore/master"}

	filePointer := flag.String("file", "", "Path to file of names")
	flag.Parse()
	names := flag.Args()

	if *filePointer != "" {
		namesFile, _ := os.Open(*filePointer)
		names = append(names, getNamesFromFile(namesFile)...)
	}

	namesChannel := make(chan string)
	urlsChannel := make(chan string)
	contentChannel := make(chan string)
	go getNames(names, namesChannel)
	go fetcher.NamesToUrls(namesChannel, urlsChannel)
	go FetchIgnoreFiles(urlsChannel, contentChannel)
	f, _ := os.Create(".gitignore")
	writeContent(f, contentChannel)
}
<commit_msg>Extracts method to get names from arguments<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"net/http"
	"os"
)

type ignoreFetcher struct {
	baseUrl string
}

func (fetcher *ignoreFetcher) NamesToUrls(namesChannel chan string, urlsChannel chan string) {
	for name := range namesChannel {
		url := fetcher.NameToUrl(name)
		urlsChannel <- url
	}
	close(urlsChannel)
}

func (fetcher *ignoreFetcher) NameToUrl(name string) string {
	return fetcher.baseUrl + "/" + name + ".gitignore"
}

func addNamesToChannel(names []string, namesChannel chan string) {
	for _, v := range names {
		namesChannel <- v
	}
	close(namesChannel)
}

func getNamesFromArguments() []string {
	filePointer := flag.String("file", "", "Path to file of names")
	flag.Parse()
	names := flag.Args()

	if *filePointer != "" {
		namesFile, _ := os.Open(*filePointer)
		names = append(names, getNamesFromFile(namesFile)...)
	}
	return names
}

func getNamesFromFile(f *os.File) []string {
	var a []string
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		a = append(a, scanner.Text())
	}
	return a
}

func FetchIgnoreFiles(urlsChannel chan string, contentChannel chan string) error {
	var err error = nil
	for url := range urlsChannel {
		response, err := http.Get(url)
		if err != nil {
			close(contentChannel)
			return err
		}
		content, err := getContent(response.Body)
		if err != nil {
			close(contentChannel)
			return err
		}
		contentChannel <- content
	}
	close(contentChannel)
	return err
}

func getContent(body io.ReadCloser) (string, error) {
	var err error = nil
	output := ""
	scanner := bufio.NewScanner(body)
	for scanner.Scan() {
		output = output + fmt.Sprintln(scanner.Text())
	}
	if err := scanner.Err(); err != nil {
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
	return output, err
}

func writeContent(f *os.File, contentChannel chan string) error {
	var err error = nil
	for content := range contentChannel {
		_, err := f.WriteString(content)
		if err != nil {
			fmt.Fprintln(os.Stderr, "writing output:", err)
			return err
		}
	}
	return err
}

func main() {
	fetcher := ignoreFetcher{baseUrl: "https://raw.githubusercontent.com/github/gitignore/master"}
	names := getNamesFromArguments()
	namesChannel := make(chan string)
	urlsChannel := make(chan string)
	contentChannel := make(chan string)
	go addNamesToChannel(names, namesChannel)
	go fetcher.NamesToUrls(namesChannel, urlsChannel)
	go FetchIgnoreFiles(urlsChannel, contentChannel)
	f, _ := os.Create(".gitignore")
	writeContent(f, contentChannel)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os/user"

	flag "github.com/docker/docker/pkg/mflag"
)

type Config struct {
	BuildFlags string
	AuthToken  string
}

// initialize flags
var (
	// Config needs to be initted in init()
	Config      *string
	BuildFlags  = flag.String([]string{"b", "-buildflags"}, "", "Pass build flags to gox")
	ForceCreate = flag.Bool([]string{"f", "-force"}, false, "Replace the asset if it already exists")
	AssetName   = flag.String([]string{"n", "-name"}, "", "Set the name for the release asset")
	Prerelease  = flag.Bool([]string{"p", "-prerelease"}, false, "With -create, create as a dev release")
	ReleaseName = flag.String([]string{"r", "-release"}, "", "Create the release if it does not exist and set the release name")
	Version     = flag.Bool([]string{"v", "-version"}, false, "Print the name and version")
)

func init() {
	CurrentUser, _ := user.Current()
	DefaultConfigPath := fmt.Sprintf("%s/.config/ghrelease/config.json", CurrentUser.HomeDir)
	Config = flag.String([]string{"c", "-config"}, DefaultConfigPath, "Set ghrelease config file")

	flag.Parse()
}

func main() {
}
<commit_msg>ConfigPath not Config<commit_after>package main

import (
	"fmt"
	"os/user"

	flag "github.com/docker/docker/pkg/mflag"
)

type Config struct {
	BuildFlags string
	AuthToken  string
}

// initialize flags
var (
	// Config needs to be initted in init()
	ConfigPath  *string
	BuildFlags  = flag.String([]string{"b", "-buildflags"}, "", "Pass build flags to gox")
	ForceCreate = flag.Bool([]string{"f", "-force"}, false, "Replace the asset if it already exists")
	AssetName   = flag.String([]string{"n", "-name"}, "", "Set the name for the release asset")
	Prerelease  = flag.Bool([]string{"p", "-prerelease"}, false, "With -create, create as a dev release")
	ReleaseName = flag.String([]string{"r", "-release"}, "", "Create the release if it does not exist and set the release name")
	Version     = flag.Bool([]string{"v", "-version"}, false, "Print the name and version")
)

func init() {
	CurrentUser, _ := user.Current()
	DefaultConfigPath := fmt.Sprintf("%s/.config/ghrelease/config.json", CurrentUser.HomeDir)
	ConfigPath = flag.String([]string{"c", "-config"}, DefaultConfigPath, "Set ghrelease config file")

	flag.Parse()
}

func main() {
}
<|endoftext|>


<commit_before>// +build ignore

package main

import (
	"errors"
	//	"fmt"
	"./godump978"
	"log"
	"os"
	"os/signal"
	"syscall"

	rtl "./gortlsdr"
	// "unsafe"
	"fmt"
)

func sigAbort(dev *rtl.Context) {
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT)
	<-ch
	_ = dev.CancelAsync()
	dev.Close()
	os.Exit(0)
}

func printUAT() {
	for {
		uat := <-dump978.OutChan
		log.Printf("dump978: %s\n", string(uat))

		fmt.Printf("%s;\n", uat)
	}
}

func main() {
	var err error
	var dev *rtl.Context

	//---------- Device Check ----------
	if c := rtl.GetDeviceCount(); c == 0 {
		log.Fatal("No devices found, exiting.\n")
	} else {
		for i := 0; i < c; i++ {
			m, p, s, err := rtl.GetDeviceUsbStrings(i)
			if err == nil {
				err = errors.New("")
			}
			log.Printf("GetDeviceUsbStrings %s - %s %s %s\n",
				err, m, p, s)
		}
	}

	log.Printf("===== Device name: %s =====\n", rtl.GetDeviceName(0))
	log.Printf("===== Running tests using device indx: 0 =====\n")

	//---------- Open Device ----------
	if dev, err = rtl.Open(0); err != nil {
		log.Fatal("\tOpen Failed, exiting\n")
	}
	defer dev.Close()
	go sigAbort(dev)

	//---------- Device Strings ----------
	m, p, s, err := dev.GetUsbStrings()
	if err != nil {
		log.Printf("\tGetUsbStrings Failed - error: %s\n", err)
	} else {
		log.Printf("\tGetUsbStrings - %s %s %s\n", m, p, s)
	}

	log.Printf("\tGetTunerType: %s\n", dev.GetTunerType())

	//---------- Set Tuner Gain ----------
	tgain := 480

	err = dev.SetTunerGainMode(true)
	if err != nil {
		log.Printf("\tSetTunerGainMode Failed - error: %s\n", err)
	} else {
		log.Printf("\tSetTunerGainMode Successful\n")
	}

	err = dev.SetTunerGain(tgain)
	if err != nil {
		log.Printf("\tSetTunerGain Failed - error: %s\n", err)
	} else {
		log.Printf("\tSetTunerGain Successful\n")
	}

	//---------- Get/Set Sample Rate ----------
	samplerate := 2083334
	err = dev.SetSampleRate(samplerate)
	if err != nil {
		log.Printf("\tSetSampleRate Failed - error: %s\n", err)
	} else {
		log.Printf("\tSetSampleRate - rate: %d\n", samplerate)
	}
	log.Printf("\tGetSampleRate: %d\n", dev.GetSampleRate())

	//---------- Get/Set Xtal Freq ----------
	rtlFreq, tunerFreq, err := dev.GetXtalFreq()
	if err != nil {
		log.Printf("\tGetXtalFreq Failed - error: %s\n", err)
	} else {
		log.Printf("\tGetXtalFreq - Rtl: %d, Tuner: %d\n", rtlFreq, tunerFreq)
	}

	newRTLFreq := 28800000
	newTunerFreq := 28800000
	err = dev.SetXtalFreq(newRTLFreq, newTunerFreq)
	if err != nil {
		log.Printf("\tSetXtalFreq Failed - error: %s\n", err)
	} else {
		log.Printf("\tSetXtalFreq - Center freq: %d, Tuner freq: %d\n",
			newRTLFreq, newTunerFreq)
	}

	//---------- Get/Set Center Freq ----------
	err = dev.SetCenterFreq(978000000)
	if err != nil {
		log.Printf("\tSetCenterFreq 978MHz Failed, error: %s\n", err)
	} else {
		log.Printf("\tSetCenterFreq 978MHz Successful\n")
	}

	log.Printf("\tGetCenterFreq: %d\n", dev.GetCenterFreq())

	//---------- Set Bandwidth ----------
	bw := 1000000
	log.Printf("\tSetting Bandwidth: %d\n", bw)
	if err = dev.SetTunerBw(bw); err != nil {
		log.Printf("\tSetTunerBw %d Failed, error: %s\n", bw, err)
	} else {
		log.Printf("\tSetTunerBw %d Successful\n", bw)
	}

	/*
		//---------- Get/Set Freq Correction ----------
		freqCorr := dev.GetFreqCorrection()
		log.Printf("\tGetFreqCorrection: %d\n", freqCorr)
		err = dev.SetFreqCorrection(0) // 10ppm
		if err != nil {
			log.Printf("\tSetFreqCorrection %d Failed, error: %s\n", 0, err)
		} else {
			log.Printf("\tSetFreqCorrection %d Successful\n", 0)
		}

		//---------- Get/Set AGC Mode ----------
		if err = dev.SetAgcMode(false); err == nil {
			log.Printf("\tSetAgcMode off Successful\n")
		} else {
			log.Printf("\tSetAgcMode Failed, error: %s\n", err)
		}

		//---------- Get/Set Direct Sampling ----------
		if mode, err := dev.GetDirectSampling(); err == nil {
			log.Printf("\tGetDirectSampling Successful, mode: %s\n",
				rtl.SamplingModes[mode])
		} else {
			log.Printf("\tSetTestMode 'On' Failed - error: %s\n", err)
		}

		if err = dev.SetDirectSampling(rtl.SamplingNone); err == nil {
			log.Printf("\tSetDirectSampling 'On' Successful\n")
		} else {
			log.Printf("\tSetDirectSampling 'On' Failed - error: %s\n", err)
		}
	*/

	//---------- Get/Set Tuner IF Gain ----------
	// if err = SetTunerIfGain(stage, gain: int); err == nil {
	// 	log.Printf("\SetTunerIfGain Successful\n")
	// } else {
	// 	log.Printf("\tSetTunerIfGain Failed - error: %s\n", err)
	// }

	/*
		//---------- Get/Set test mode ----------
		if err = dev.SetTestMode(true); err == nil {
			log.Printf("\tSetTestMode 'On' Successful\n")
		} else {
			log.Printf("\tSetTestMode 'On' Failed - error: %s\n", err)
		}

		if err = dev.SetTestMode(false); err == nil {
			log.Printf("\tSetTestMode 'Off' Successful\n")
		} else {
			log.Printf("\tSetTestMode 'Off' Fail - error: %s\n", err)
		}

	*/

	//---------- Get/Set misc. streaming ----------
	dump978.Dump978Init()
	go printUAT()
	go dump978.ProcessDataFromChannel()

	if err = dev.ResetBuffer(); err == nil {
		log.Printf("\tResetBuffer Successful\n")
	} else {
		log.Printf("\tResetBuffer Failed - error: %s\n", err)
	}

	for {
		var buffer = make([]uint8, rtl.DefaultBufLength)
		nRead, err := dev.ReadSync(buffer, rtl.DefaultBufLength)
		if err != nil {
			log.Printf("\tReadSync Failed - error: %s\n", err)
		} else {
			log.Printf("\tReadSync %d\n", nRead)
			//			buf := buffer[:nRead]
			//			dump978.InChan <- buf
		}
	}
}
<commit_msg>package location change<commit_after>// +build ignore

package main

import (
	"errors"
	//	"fmt"
	"./godump978"
	"log"
	"os"
	"os/signal"
	"syscall"

	rtl "github.com/jpoirier/gortlsdr"
	// "unsafe"
	"fmt"
)

func sigAbort(dev *rtl.Context) {
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT)
	<-ch
	_ = dev.CancelAsync()
	dev.Close()
	os.Exit(0)
}

func printUAT() {
	for {
		uat := <-dump978.OutChan
		log.Printf("dump978: %s\n", string(uat))

		fmt.Printf("%s;\n", uat)
	}
}

func main() {
	var err error
	var dev *rtl.Context

	//---------- Device Check ----------
	if c := rtl.GetDeviceCount(); c == 0 {
		log.Fatal("No devices found, exiting.\n")
	} else {
		for i := 0; i < c; i++ {
			m, p, s, err := rtl.GetDeviceUsbStrings(i)
			if err == nil {
				err = errors.New("")
			}
			log.Printf("GetDeviceUsbStrings %s - %s %s %s\n",
				err, m, p, s)
		}
	}

	log.Printf("===== Device name: %s =====\n", rtl.GetDeviceName(0))
	log.Printf("===== Running tests using device indx: 0 =====\n")

	//---------- Open Device ----------
	if dev, err = rtl.Open(0); err != nil {
		log.Fatal("\tOpen Failed, exiting\n")
	}
	defer dev.Close()
	go sigAbort(dev)

	//---------- Device Strings ----------
	m, p, s, err := dev.GetUsbStrings()
	if err != nil {
		log.Printf("\tGetUsbStrings Failed - error: %s\n", err)
	} else {
		log.Printf("\tGetUsbStrings - %s %s %s\n", m, p, s)
	}

	log.Printf("\tGetTunerType: %s\n", dev.GetTunerType())

	//---------- Set Tuner Gain ----------
	tgain := 480

	err = dev.SetTunerGainMode(true)
	if err != nil {
		log.Printf("\tSetTunerGainMode Failed - error: %s\n", err)
	} else {
		log.Printf("\tSetTunerGainMode Successful\n")
	}

	err = dev.SetTunerGain(tgain)
	if err != nil {
		log.Printf("\tSetTunerGain Failed - error: %s\n", err)
	} else {
		log.Printf("\tSetTunerGain Successful\n")
	}

	//---------- Get/Set Sample Rate ----------
	samplerate := 2083334
	err = dev.SetSampleRate(samplerate)
	if err != nil {
		log.Printf("\tSetSampleRate Failed - error: %s\n", err)
	} else {
		log.Printf("\tSetSampleRate - rate: %d\n", samplerate)
	}
	log.Printf("\tGetSampleRate: %d\n", dev.GetSampleRate())

	//---------- Get/Set Xtal Freq ----------
	rtlFreq, tunerFreq, err := dev.GetXtalFreq()
	if err != nil {
		log.Printf("\tGetXtalFreq Failed - error: %s\n", err)
	} else {
		log.Printf("\tGetXtalFreq - Rtl: %d, Tuner: %d\n", rtlFreq, tunerFreq)
	}

	newRTLFreq := 28800000
	newTunerFreq := 28800000
	err = dev.SetXtalFreq(newRTLFreq, newTunerFreq)
	if err != nil {
		log.Printf("\tSetXtalFreq Failed - error: %s\n", err)
	} else {
		log.Printf("\tSetXtalFreq - Center freq: %d, Tuner freq: %d\n",
			newRTLFreq, newTunerFreq)
	}

	//---------- Get/Set Center Freq ----------
	err = dev.SetCenterFreq(978000000)
	if err != nil {
		log.Printf("\tSetCenterFreq 978MHz Failed, error: %s\n", err)
	} else {
		log.Printf("\tSetCenterFreq 978MHz Successful\n")
	}

	log.Printf("\tGetCenterFreq: %d\n", dev.GetCenterFreq())

	//---------- Set Bandwidth ----------
	bw := 1000000
	log.Printf("\tSetting Bandwidth: %d\n", bw)
	if err = dev.SetTunerBw(bw); err != nil {
		log.Printf("\tSetTunerBw %d Failed, error: %s\n", bw, err)
	} else {
		log.Printf("\tSetTunerBw %d Successful\n", bw)
	}

	/*
		//---------- Get/Set Freq Correction ----------
		freqCorr := dev.GetFreqCorrection()
		log.Printf("\tGetFreqCorrection: %d\n", freqCorr)
		err = dev.SetFreqCorrection(0) // 10ppm
		if err != nil {
			log.Printf("\tSetFreqCorrection %d Failed, error: %s\n", 0, err)
		} else {
			log.Printf("\tSetFreqCorrection %d Successful\n", 0)
		}

		//---------- Get/Set AGC Mode ----------
		if err = dev.SetAgcMode(false); err == nil {
			log.Printf("\tSetAgcMode off Successful\n")
		} else {
			log.Printf("\tSetAgcMode Failed, error: %s\n", err)
		}

		//---------- Get/Set Direct Sampling ----------
		if mode, err := dev.GetDirectSampling(); err == nil {
			log.Printf("\tGetDirectSampling Successful, mode: %s\n",
				rtl.SamplingModes[mode])
		} else {
			log.Printf("\tSetTestMode 'On' Failed - error: %s\n", err)
		}

		if err = dev.SetDirectSampling(rtl.SamplingNone); err == nil {
			log.Printf("\tSetDirectSampling 'On' Successful\n")
		} else {
			log.Printf("\tSetDirectSampling 'On' Failed - error: %s\n", err)
		}
	*/

	//---------- Get/Set Tuner IF Gain ----------
	// if err = SetTunerIfGain(stage, gain: int); err == nil {
	// 	log.Printf("\SetTunerIfGain Successful\n")
	// } else {
	// 	log.Printf("\tSetTunerIfGain Failed - error: %s\n", err)
	// }

	/*
		//---------- Get/Set test mode ----------
		if err = dev.SetTestMode(true); err == nil {
			log.Printf("\tSetTestMode 'On' Successful\n")
		} else {
			log.Printf("\tSetTestMode 'On' Failed - error: %s\n", err)
		}

		if err = dev.SetTestMode(false); err == nil {
			log.Printf("\tSetTestMode 'Off' Successful\n")
		} else {
			log.Printf("\tSetTestMode 'Off' Fail - error: %s\n", err)
		}

	*/

	//---------- Get/Set misc. streaming ----------
	dump978.Dump978Init()
	go printUAT()
	go dump978.ProcessDataFromChannel()

	if err = dev.ResetBuffer(); err == nil {
		log.Printf("\tResetBuffer Successful\n")
	} else {
		log.Printf("\tResetBuffer Failed - error: %s\n", err)
	}

	for {
		var buffer = make([]uint8, rtl.DefaultBufLength)
		nRead, err := dev.ReadSync(buffer, rtl.DefaultBufLength)
		if err != nil {
			log.Printf("\tReadSync Failed - error: %s\n", err)
		} else {
			log.Printf("\tReadSync %d\n", nRead)
			//			buf := buffer[:nRead]
			//			dump978.InChan <- buf
		}
	}
}
<|endoftext|>


<commit_before>package omise

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

type testAccount struct {
	ID    string
	Email string
}

func TestClient(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/account" {
			t.Error("expect path is /account")
		}
		if r.Header.Get("Authorization") != "Basic dG9rbl90ZXN0XzR5OTZvNWxueDZtN2Z3OHdwZzk6" {
			t.Error("expect basic is set", "tokn_test_4y96o5lnx6m7fw8wpg9:")
		}

		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.Write([]byte(`{
            "object": "account",
            "id": "acct_4xhe277ad8n8zc8t9q9",
            "email": "abc@mail.com"
        }`))
	}))
	defer ts.Close()

	c := &client{
		Client: &http.Client{},
		url:    ts.URL,
	}
	resp, err := c.do("GET", "tokn_test_4y96o5lnx6m7fw8wpg9", "/account", nil)

	if err != nil {
		t.Error(err)
	}

	var acc testAccount
	err = resp.decode(&acc)

	if err != nil {
		t.Error(err)
	}
	if acc.ID != "acct_4xhe277ad8n8zc8t9q9" {
		t.Error("expect account must be decode")
	}
}

func TestErrorClient(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusNotFound)
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.Write([]byte(`{
            "object": "error",
            "location": "https://docs.omise.co/api/errors#not-found",
            "code": "not_found",
            "message": "token tokn_test_4y9ki6uod9yna26dnlf was not found"
        }`))
	}))
	defer ts.Close()

	c := &client{
		Client: &http.Client{},
		url:    ts.URL,
	}

	_, err := c.do("GET", "tokn_test_4y96o5lnx6m7fw8wpg9", "/account", nil)

	if err == nil {
		t.Error("expect error not to be nil")
	}

	if e, ok := err.(*OmiseError); ok {
		testOmiseError(t, e)
	} else {
		t.Error("expect err must be cast to OmiseError", err)
	}

	if err.Error() != "[not_found] token tokn_test_4y9ki6uod9yna26dnlf was not found" {
		t.Error("unexpect message", err.Error())
	}
}

func testOmiseError(t *testing.T, e *OmiseError) {
	if e.Location != "https://docs.omise.co/api/errors#not-found" {
		t.Errorf(
			"expect location https://docs.omise.co/api/errors#not-found but got %s",
			e.Location,
		)
	}
	if e.Code != "not_found" {
		t.Errorf(
			"expect code is not_found but got %s",
			e.Code,
		)
	}
	if e.Message != "token tokn_test_4y9ki6uod9yna26dnlf was not found" {
		t.Errorf(
			"unexpect token is %s",
			e.Message,
		)
	}
}
<commit_msg>reformat client_test.go<commit_after>package omise

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

type testAccount struct {
	ID    string
	Email string
}

func TestClient(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/account" {
			t.Error("expect path is /account")
		}
		if r.Header.Get("Authorization") != "Basic dG9rbl90ZXN0XzR5OTZvNWxueDZtN2Z3OHdwZzk6" {
			t.Error("expect basic is set", "tokn_test_4y96o5lnx6m7fw8wpg9:")
		}

		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.Write([]byte(`{
			"object": "account",
			"id": "acct_4xhe277ad8n8zc8t9q9",
			"email": "abc@mail.com"
		}`))
	}))
	defer ts.Close()

	c := &client{
		Client: &http.Client{},
		url:    ts.URL,
	}
	resp, err := c.do("GET", "tokn_test_4y96o5lnx6m7fw8wpg9", "/account", nil)

	if err != nil {
		t.Error(err)
	}

	var acc testAccount
	err = resp.decode(&acc)

	if err != nil {
		t.Error(err)
	}
	if acc.ID != "acct_4xhe277ad8n8zc8t9q9" {
		t.Error("expect account must be decode")
	}
}

func TestErrorClient(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusNotFound)
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.Write([]byte(`{
			"object": "error",
			"location": "https://docs.omise.co/api/errors#not-found",
			"code": "not_found",
			"message": "token tokn_test_4y9ki6uod9yna26dnlf was not found"
		}`))
	}))
	defer ts.Close()

	c := &client{
		Client: &http.Client{},
		url:    ts.URL,
	}

	_, err := c.do("GET", "tokn_test_4y96o5lnx6m7fw8wpg9", "/account", nil)

	if err == nil {
		t.Error("expect error not to be nil")
	}

	if e, ok := err.(*OmiseError); ok {
		testOmiseError(t, e)
	} else {
		t.Error("expect err must be cast to OmiseError", err)
	}

	if err.Error() != "[not_found] token tokn_test_4y9ki6uod9yna26dnlf was not found" {
		t.Error("unexpect message", err.Error())
	}
}

func testOmiseError(t *testing.T, e *OmiseError) {
	if e.Location != "https://docs.omise.co/api/errors#not-found" {
		t.Errorf(
			"expect location https://docs.omise.co/api/errors#not-found but got %s",
			e.Location,
		)
	}
	if e.Code != "not_found" {
		t.Errorf(
			"expect code is not_found but got %s",
			e.Code,
		)
	}
	if e.Message != "token tokn_test_4y9ki6uod9yna26dnlf was not found" {
		t.Errorf(
			"unexpect token is %s",
			e.Message,
		)
	}
}
<|endoftext|>