<commit_before>// Copyright 2014 Hajime Hoshi
//
// 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 main

import (
	"fmt"
	"image"
	"image/color"
	"log"
	"math"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/ebitenutil"
)

const (
	screenWidth  = 320
	screenHeight = 240
)

var (
	count       int
	brushImage  *ebiten.Image
	canvasImage *ebiten.Image
)

func paint(screen *ebiten.Image, x, y int) error {
	op := &ebiten.DrawImageOptions{}
	op.GeoM.Translate(float64(x), float64(y))
	op.ColorM.Scale(1.0, 0.50, 0.125, 1.0)
	theta := 2.0 * math.Pi * float64(count%60) / ebiten.FPS
	op.ColorM.RotateHue(theta)
	if err := canvasImage.DrawImage(brushImage, op); err != nil {
		return err
	}
	return nil
}

func update(screen *ebiten.Image) error {
	drawn := false
	mx, my := ebiten.CursorPosition()
	if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
		if err := paint(screen, mx, my); err != nil {
			return err
		}
		drawn = true
	}
	for _, t := range ebiten.Touches() {
		x, y := t.Position()
		if err := paint(screen, x, y); err != nil {
			return err
		}
		drawn = true
	}
	if drawn {
		count++
	}

	if err := screen.DrawImage(canvasImage, nil); err != nil {
		return err
	}

	msg := fmt.Sprintf("(%d, %d)", mx, my)
	for _, t := range ebiten.Touches() {
		x, y := t.Position()
		msg += fmt.Sprintf("\n(%d, %d) touch %d", x, y, t.ID())
	}
	if err := ebitenutil.DebugPrint(screen, msg); err != nil {
		return err
	}
	return nil
}

func main() {
	var err error
	const a0, a1, a2 = 0x40, 0xc0, 0xff
	pixels := []uint8{
		a0, a1, a1, a0,
		a1, a2, a2, a1,
		a1, a2, a2, a1,
		a0, a1, a1, a0,
	}
	brushImage, err = ebiten.NewImageFromImage(&image.Alpha{
		Pix:    pixels,
		Stride: 4,
		Rect:   image.Rect(0, 0, 4, 4),
	}, ebiten.FilterNearest)
	if err != nil {
		log.Fatal(err)
	}

	canvasImage, err = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterNearest)
	if err != nil {
		log.Fatal(err)
	}
	canvasImage.Fill(color.White)

	if err := ebiten.Run(update, screenWidth, screenHeight, 1.5, "Paint (Ebiten Demo)"); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>examples/paint: Fix a float scale to an integer<commit_after>// Copyright 2014 Hajime Hoshi
//
// 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 main

import (
	"fmt"
	"image"
	"image/color"
	"log"
	"math"

	"github.com/hajimehoshi/ebiten"
	"github.com/hajimehoshi/ebiten/ebitenutil"
)

const (
	screenWidth  = 320
	screenHeight = 240
)

var (
	count       int
	brushImage  *ebiten.Image
	canvasImage *ebiten.Image
)

func paint(screen *ebiten.Image, x, y int) error {
	op := &ebiten.DrawImageOptions{}
	op.GeoM.Translate(float64(x), float64(y))
	op.ColorM.Scale(1.0, 0.50, 0.125, 1.0)
	theta := 2.0 * math.Pi * float64(count%60) / ebiten.FPS
	op.ColorM.RotateHue(theta)
	if err := canvasImage.DrawImage(brushImage, op); err != nil {
		return err
	}
	return nil
}

func update(screen *ebiten.Image) error {
	drawn := false
	mx, my := ebiten.CursorPosition()
	if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
		if err := paint(screen, mx, my); err != nil {
			return err
		}
		drawn = true
	}
	for _, t := range ebiten.Touches() {
		x, y := t.Position()
		if err := paint(screen, x, y); err != nil {
			return err
		}
		drawn = true
	}
	if drawn {
		count++
	}

	if err := screen.DrawImage(canvasImage, nil); err != nil {
		return err
	}

	msg := fmt.Sprintf("(%d, %d)", mx, my)
	for _, t := range ebiten.Touches() {
		x, y := t.Position()
		msg += fmt.Sprintf("\n(%d, %d) touch %d", x, y, t.ID())
	}
	if err := ebitenutil.DebugPrint(screen, msg); err != nil {
		return err
	}
	return nil
}

func main() {
	var err error
	const a0, a1, a2 = 0x40, 0xc0, 0xff
	pixels := []uint8{
		a0, a1, a1, a0,
		a1, a2, a2, a1,
		a1, a2, a2, a1,
		a0, a1, a1, a0,
	}
	brushImage, err = ebiten.NewImageFromImage(&image.Alpha{
		Pix:    pixels,
		Stride: 4,
		Rect:   image.Rect(0, 0, 4, 4),
	}, ebiten.FilterNearest)
	if err != nil {
		log.Fatal(err)
	}

	canvasImage, err = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterNearest)
	if err != nil {
		log.Fatal(err)
	}
	canvasImage.Fill(color.White)

	if err := ebiten.Run(update, screenWidth, screenHeight, 2, "Paint (Ebiten Demo)"); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package gqt_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path"
	"path/filepath"

	"code.cloudfoundry.org/garden"
	"code.cloudfoundry.org/guardian/gqt/runner"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Network plugin", func() {
	var (
		client    *runner.RunningGarden
		container garden.Container

		containerSpec    garden.ContainerSpec
		containerNetwork string

		extraProperties             garden.Properties
		rootFSWithoutHostsAndResolv string

		argsFile  string
		stdinFile string
	)

	BeforeEach(func() {
		rootFSWithoutHostsAndResolv = createRootfs(func(root string) {
			Expect(os.Chmod(filepath.Join(root, "tmp"), 0777)).To(Succeed())
			Expect(os.Remove(filepath.Join(root, "etc", "hosts"))).To(Succeed())
			Expect(os.Remove(filepath.Join(root, "etc", "resolv.conf"))).To(Succeed())
		}, 0755)

		containerNetwork = fmt.Sprintf("192.168.%d.0/24", 12+GinkgoParallelNode())
		containerSpec = garden.ContainerSpec{}

		tmpDir, err := ioutil.TempDir("", "netplugtest")
		Expect(err).NotTo(HaveOccurred())

		argsFile = path.Join(tmpDir, "args.log")
		stdinFile = path.Join(tmpDir, "stdin.log")

		config.NetworkPluginBin = binaries.NetworkPlugin
		config.NetworkPluginExtraArgs = []string{argsFile, stdinFile}
	})

	JustBeforeEach(func() {
		var err error

		client = runner.Start(config)

		containerSpec.Network = containerNetwork
		containerSpec.Properties = extraProperties
		container, err = client.Create(containerSpec)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		Expect(os.RemoveAll(rootFSWithoutHostsAndResolv)).To(Succeed())
		Expect(client.DestroyAndStop()).To(Succeed())
	})

	Context("and the plugin is essentially a noop", func() {
		BeforeEach(func() {
			config.NetworkPluginBin = "/bin/true"
		})

		It("successfully creates a container", func() {
			_, err := client.Create(garden.ContainerSpec{})
			Expect(err).NotTo(HaveOccurred())
		})
	})

	Context("when the network plugin returns properties and dns_servers", func() {
		var pluginReturn string

		BeforeEach(func() {
			pluginReturn = `{
					"properties":{
						"foo":"bar",
						"kawasaki.mtu":"1499",
						"garden.network.container-ip":"10.255.10.10",
						"garden.network.host-ip":"255.255.255.255"
					},
					"dns_servers": [
						"1.2.3.4",
						"1.2.3.5"
					]
			  }`
			config.NetworkPluginExtraArgs = append(
				config.NetworkPluginExtraArgs,
				pluginReturn,
			)
			extraProperties = garden.Properties{
				"some-property-on-the-spec": "some-value",
				"network.some-key":          "some-value",
				"network.some-other-key":    "some-other-value",
				"some-other-key":            "do-not-propagate",
				"garden.whatever":           "do-not-propagate",
				"kawasaki.nope":             "do-not-propagate",
			}
		})

		Context("when the container spec has properties that start with 'network.'", func() {
			var expectedJSON string

			BeforeEach(func() {
				expectedJSON = `"some-key":"some-value","some-other-key":"some-other-value"}`
			})

			It("propagates those properties as JSON to the network plugin up action", func() {
				Eventually(getContent(stdinFile)).Should(ContainSubstring(expectedJSON))
			})
		})

		It("sets the nameserver entries in the container's /etc/resolv.conf to the values supplied by the network plugin", func() {
			Expect(getNameservers(container)).To(Equal([]string{"1.2.3.4", "1.2.3.5"}))
		})

		Context("when the rootFS does not contain /etc/resolv.conf", func() {
			BeforeEach(func() {
				containerSpec.RootFSPath = fmt.Sprintf("raw://%s", rootFSWithoutHostsAndResolv)
			})

			It("sets the nameserver entries in the container's /etc/resolv.conf to the values supplied by the network plugin", func() {
				Expect(getNameservers(container)).To(Equal([]string{"1.2.3.4", "1.2.3.5"}))
			})
		})

		It("executes the network plugin during container destroy", func() {
			containerHandle := container.Handle()

			Expect(client.Destroy(containerHandle)).To(Succeed())
			Expect(argsFile).To(BeAnExistingFile())

			Eventually(getContent(argsFile)).Should(ContainSubstring(fmt.Sprintf("%s %s", argsFile, stdinFile)))
			Eventually(getContent(argsFile)).Should(ContainSubstring(fmt.Sprintf("--action down --handle %s", containerHandle)))
		})

		It("passes the container pid to plugin's stdin", func() {
			Eventually(getContent(stdinFile)).Should(
				MatchRegexp(`.*{"Pid":[0-9]+.*}.*`),
			)
		})

		It("executes the network plugin during container creation", func() {
			containerHandle := container.Handle()

			Eventually(getContent(argsFile)).Should(
				ContainSubstring(
					fmt.Sprintf("%s %s %s --action up --handle %s", argsFile, stdinFile, pluginReturn, containerHandle),
				),
			)
		})

		Context("and the containerSpec contains NetOutRules", func() {
			BeforeEach(func() {
				containerSpec.NetOut = []garden.NetOutRule{
					garden.NetOutRule{
						Protocol: garden.ProtocolTCP,
						Networks: []garden.IPRange{garden.IPRangeFromIP(net.ParseIP("8.8.8.8"))},
						Ports:    []garden.PortRange{garden.PortRangeFromPort(53)},
					},
					garden.NetOutRule{
						Protocol: garden.ProtocolTCP,
						Networks: []garden.IPRange{garden.IPRangeFromIP(net.ParseIP("8.8.4.4"))},
						Ports:    []garden.PortRange{garden.PortRangeFromPort(53)},
					},
				}
			})

			It("passes the NetOut rules to the plugin during container creation", func() {
				jsonBytes, err := json.Marshal(containerSpec.NetOut)
				Expect(err).NotTo(HaveOccurred())

				Eventually(getContent(stdinFile)).Should(
					ContainSubstring("\"netout_rules\":" + string(jsonBytes)),
				)
			})
		})

		Context("and the containerSpec contains NetIn", func() {
			BeforeEach(func() {
				containerSpec.NetIn = []garden.NetIn{
					garden.NetIn{
						HostPort:      9999,
						ContainerPort: 8080,
					},
					garden.NetIn{
						HostPort:      9989,
						ContainerPort: 8081,
					},
				}
			})

			It("passes the NetIn input to the plugin during container creation", func() {
				jsonBytes, err := json.Marshal(containerSpec.NetIn)
				Expect(err).NotTo(HaveOccurred())

				Eventually(getContent(stdinFile)).Should(
					ContainSubstring("\"netin\":" + string(jsonBytes)),
				)
			})
		})

		It("persists the returned properties to the container's properties", func() {
			info, err := container.Info()
			Expect(err).NotTo(HaveOccurred())

			containerProperties := info.Properties

			Expect(containerProperties["foo"]).To(Equal("bar"))
			Expect(containerProperties["garden.network.container-ip"]).To(Equal("10.255.10.10"))
			Expect(containerProperties["garden.network.host-ip"]).To(Equal("255.255.255.255"))
		})

		It("doesn't remove existing properties", func() {
			info, err := container.Info()
			Expect(err).NotTo(HaveOccurred())

			Expect(info.Properties).To(HaveKey("some-property-on-the-spec"))
		})

		It("sets the ExternalIP and ContainerIP fields on the container.Info()", func() {
			info, err := container.Info()
			Expect(err).NotTo(HaveOccurred())

			Expect(info.ExternalIP).NotTo(BeEmpty())
			Expect(info.ContainerIP).To(Equal("10.255.10.10"))
		})

		Context("when BulkNetOut is called", func() {
			It("passes down the bulk net out rules to the external networker", func() {
				rules := []garden.NetOutRule{
					garden.NetOutRule{
						Protocol: garden.ProtocolTCP,
					},
					garden.NetOutRule{
						Protocol: garden.ProtocolUDP,
					},
				}
				container.BulkNetOut(rules)

				Eventually(getContent(stdinFile)).Should(
					ContainSubstring(`{"container_ip":"10.255.10.10","netout_rules":[{"protocol":1},{"protocol":2}]}`),
				)
			})
		})

	})

	Context("when the network plugin returns properties but no dns_servers", func() {
		var (
			hostNameservers []string
		)

		BeforeEach(func() {
			out, err := ioutil.ReadFile("/etc/resolv.conf")
			Expect(err).NotTo(HaveOccurred())
			hostNameservers = parseNameservers(string(out))

			pluginReturn := `{
					"properties":{
						"foo":"bar",
						"kawasaki.mtu":"1499",
						"garden.network.container-ip":"10.255.10.10",
						"garden.network.host-ip":"255.255.255.255"
					}
			  }`
			config.NetworkPluginExtraArgs = append(
				config.NetworkPluginExtraArgs,
				pluginReturn,
			)
		})

		Context("and --dns-server/--additional-dns-server has not been provided", func() {
			It("adds the host's non-127.0.0.0/24 DNS servers to the container's /etc/resolv.conf", func() {
				resolvConf := readResolvConf(container)

				for _, hostNameserver := range hostNameservers {
					Expect(resolvConf).To(ContainSubstring(hostNameserver))
					Expect(resolvConf).NotTo(ContainSubstring("127.0.0."))
				}
			})
		})

		Context("when --dns-server is provided", func() {
			BeforeEach(func() {
				config.DNSServers = []string{"1.2.3.4"}
			})

			It("adds the IP address to the container's /etc/resolv.conf", func() {
				nameservers := getNameservers(container)
				Expect(nameservers).To(ContainElement("1.2.3.4"))
			})

			It("strips the host's DNS servers from the container's /etc/resolv.conf", func() {
				nameservers := getNameservers(container)

				for _, hostNameserver := range hostNameservers {
					Expect(nameservers).NotTo(ContainElement(hostNameserver))
				}
			})
		})

		Context("when --additional-dns-server is provided", func() {
			BeforeEach(func() {
				config.AdditionalDNSServers = []string{"1.2.3.4"}
			})

			It("writes the IP address and the host's non-127.0.0.0/24 DNS servers to the container's /etc/resolv.conf", func() {
				resolvConf := readResolvConf(container)

				for _, hostNameserver := range hostNameservers {
					Expect(resolvConf).To(ContainSubstring(hostNameserver))
					Expect(resolvConf).NotTo(ContainSubstring("127.0.0."))
				}

				Expect(resolvConf).To(ContainSubstring("nameserver 1.2.3.4"))
			})
		})

		Context("when --dns-server and --additional-dns-server is provided", func() {
			BeforeEach(func() {
				config.DNSServers = []string{"1.2.3.4"}
				config.AdditionalDNSServers = []string{"1.2.3.5"}
			})

			It("writes the --dns-server and --additional-dns-server DNS servers to the container's /etc/resolv.conf", func() {
				resolvConf := readResolvConf(container)
				Expect(resolvConf).To(Equal("nameserver 1.2.3.4\nnameserver 1.2.3.5\n"))
			})
		})
	})
})
<commit_msg>Refactor netplugin tests<commit_after>package gqt_test

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"os"
	"path"
	"path/filepath"

	"code.cloudfoundry.org/garden"
	"code.cloudfoundry.org/guardian/gqt/runner"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Network plugin", func() {
	var (
		client    *runner.RunningGarden
		container garden.Container

		containerSpec    garden.ContainerSpec
		containerNetwork string

		extraProperties garden.Properties

		argsFile        string
		stdinFile       string
		pluginReturn    string
		hostNameservers []string
	)

	BeforeEach(func() {

		containerNetwork = fmt.Sprintf("192.168.%d.0/24", 12+GinkgoParallelNode())
		containerSpec = garden.ContainerSpec{}

		tmpDir, err := ioutil.TempDir("", "netplugtest")
		Expect(err).NotTo(HaveOccurred())

		argsFile = path.Join(tmpDir, "args.log")
		stdinFile = path.Join(tmpDir, "stdin.log")

		config.NetworkPluginBin = binaries.NetworkPlugin
		config.NetworkPluginExtraArgs = []string{argsFile, stdinFile}

		pluginReturn = `{"properties":{"garden.network.container-ip":"10.255.10.10"}}`

		out, err := ioutil.ReadFile("/etc/resolv.conf")
		Expect(err).NotTo(HaveOccurred())
		hostNameservers = parseNameservers(string(out))
	})

	JustBeforeEach(func() {
		var err error

		config.NetworkPluginExtraArgs = append(
			config.NetworkPluginExtraArgs,
			pluginReturn,
		)
		client = runner.Start(config)

		containerSpec.Network = containerNetwork
		containerSpec.Properties = extraProperties
		container, err = client.Create(containerSpec)
		Expect(err).NotTo(HaveOccurred())
	})

	AfterEach(func() {
		Expect(client.DestroyAndStop()).To(Succeed())
	})

	It("executes the network plugin during container creation", func() {
		containerHandle := container.Handle()

		Eventually(getContent(argsFile)).Should(
			ContainSubstring(
				fmt.Sprintf("%s %s %s --action up --handle %s", argsFile, stdinFile, pluginReturn, containerHandle),
			),
		)
	})

	It("executes the network plugin during container destroy", func() {
		containerHandle := container.Handle()

		Expect(client.Destroy(containerHandle)).To(Succeed())
		Expect(argsFile).To(BeAnExistingFile())

		Eventually(getContent(argsFile)).Should(ContainSubstring(fmt.Sprintf("%s %s", argsFile, stdinFile)))
		Eventually(getContent(argsFile)).Should(ContainSubstring(fmt.Sprintf("--action down --handle %s", containerHandle)))
	})

	It("passes the container pid to plugin's stdin", func() {
		Eventually(getContent(stdinFile)).Should(
			MatchRegexp(`.*{"Pid":[0-9]+.*}.*`),
		)
	})

	It("sets the ExternalIP and ContainerIP fields on the container.Info()", func() {
		info, err := container.Info()
		Expect(err).NotTo(HaveOccurred())

		Expect(info.ExternalIP).NotTo(BeEmpty())
		Expect(info.ContainerIP).To(Equal("10.255.10.10"))
	})

	Context("when the containerSpec contains NetOutRules", func() {
		BeforeEach(func() {
			containerSpec.NetOut = []garden.NetOutRule{
				garden.NetOutRule{
					Protocol: garden.ProtocolTCP,
					Networks: []garden.IPRange{garden.IPRangeFromIP(net.ParseIP("8.8.8.8"))},
					Ports:    []garden.PortRange{garden.PortRangeFromPort(53)},
				},
				garden.NetOutRule{
					Protocol: garden.ProtocolTCP,
					Networks: []garden.IPRange{garden.IPRangeFromIP(net.ParseIP("8.8.4.4"))},
					Ports:    []garden.PortRange{garden.PortRangeFromPort(53)},
				},
			}
		})

		It("passes the NetOut rules to the plugin during container creation", func() {
			jsonBytes, err := json.Marshal(containerSpec.NetOut)
			Expect(err).NotTo(HaveOccurred())

			Eventually(getContent(stdinFile)).Should(
				ContainSubstring("\"netout_rules\":" + string(jsonBytes)),
			)
		})
	})

	Context("and the containerSpec contains NetIn", func() {
		BeforeEach(func() {
			containerSpec.NetIn = []garden.NetIn{
				garden.NetIn{
					HostPort:      9999,
					ContainerPort: 8080,
				},
				garden.NetIn{
					HostPort:      9989,
					ContainerPort: 8081,
				},
			}
		})

		It("passes the NetIn input to the plugin during container creation", func() {
			jsonBytes, err := json.Marshal(containerSpec.NetIn)
			Expect(err).NotTo(HaveOccurred())

			Eventually(getContent(stdinFile)).Should(
				ContainSubstring("\"netin\":" + string(jsonBytes)),
			)
		})
	})

	Context("when BulkNetOut is called", func() {
		It("passes down the bulk net out rules to the external networker", func() {
			rules := []garden.NetOutRule{
				garden.NetOutRule{
					Protocol: garden.ProtocolTCP,
				},
				garden.NetOutRule{
					Protocol: garden.ProtocolUDP,
				},
			}
			container.BulkNetOut(rules)

			Eventually(getContent(stdinFile)).Should(
				ContainSubstring(`{"container_ip":"10.255.10.10","netout_rules":[{"protocol":1},{"protocol":2}]}`),
			)
		})
	})

	It("adds the host's non-127.0.0.0/24 DNS servers to the container's /etc/resolv.conf", func() {
		resolvConf := readResolvConf(container)

		for _, hostNameserver := range hostNameservers {
			Expect(resolvConf).To(ContainSubstring(hostNameserver))
			Expect(resolvConf).NotTo(ContainSubstring("127.0.0."))
		}
	})

	Context("when --dns-server is provided", func() {
		BeforeEach(func() {
			config.DNSServers = []string{"1.2.3.4"}
		})

		It("adds the IP address to the container's /etc/resolv.conf", func() {
			nameservers := getNameservers(container)
			Expect(nameservers).To(ContainElement("1.2.3.4"))
		})

		It("strips the host's DNS servers from the container's /etc/resolv.conf", func() {
			nameservers := getNameservers(container)

			for _, hostNameserver := range hostNameservers {
				Expect(nameservers).NotTo(ContainElement(hostNameserver))
			}
		})
	})

	Context("when --additional-dns-server is provided", func() {
		BeforeEach(func() {
			config.AdditionalDNSServers = []string{"1.2.3.4"}
		})

		It("writes the IP address and the host's non-127.0.0.0/24 DNS servers to the container's /etc/resolv.conf", func() {
			resolvConf := readResolvConf(container)

			for _, hostNameserver := range hostNameservers {
				Expect(resolvConf).To(ContainSubstring(hostNameserver))
				Expect(resolvConf).NotTo(ContainSubstring("127.0.0."))
			}

			Expect(resolvConf).To(ContainSubstring("nameserver 1.2.3.4"))
		})
	})

	Context("when --dns-server and --additional-dns-server are provided", func() {
		BeforeEach(func() {
			config.DNSServers = []string{"1.2.3.4"}
			config.AdditionalDNSServers = []string{"1.2.3.5"}
		})

		It("writes the --dns-server and --additional-dns-server DNS servers to the container's /etc/resolv.conf", func() {
			resolvConf := readResolvConf(container)
			Expect(resolvConf).To(Equal("nameserver 1.2.3.4\nnameserver 1.2.3.5\n"))
		})
	})

	Context("and the plugin is essentially a noop", func() {
		BeforeEach(func() {
			config.NetworkPluginBin = "/bin/true"
		})

		It("successfully creates a container", func() {
			_, err := client.Create(garden.ContainerSpec{})
			Expect(err).NotTo(HaveOccurred())
		})
	})

	Context("when the container spec has properties", func() {
		BeforeEach(func() {
			extraProperties = garden.Properties{
				"some-property-on-the-spec": "some-value",
				"network.some-key":          "some-value",
				"network.some-other-key":    "some-other-value",
				"some-other-key":            "do-not-propagate",
			}
		})

		It("propagates the 'network.*' properties to the network plugin up action", func() {
			expectedJSON := `"some-key":"some-value","some-other-key":"some-other-value"}`
			Eventually(getContent(stdinFile)).Should(ContainSubstring(expectedJSON))
		})

		It("doesn't remove existing properties", func() {
			info, err := container.Info()
			Expect(err).NotTo(HaveOccurred())

			Expect(info.Properties).To(HaveKey("some-property-on-the-spec"))
		})
	})

	Context("when the network plugin returns properties", func() {
		BeforeEach(func() {
			pluginReturn = `{
					"properties":{
						"foo":"bar",
						"garden.network.container-ip":"10.255.10.10",
						"garden.network.host-ip":"255.255.255.255"
					}
			  }`
		})

		It("persists the returned properties to the container's properties", func() {
			info, err := container.Info()
			Expect(err).NotTo(HaveOccurred())

			containerProperties := info.Properties

			Expect(containerProperties["foo"]).To(Equal("bar"))
			Expect(containerProperties["garden.network.container-ip"]).To(Equal("10.255.10.10"))
			Expect(containerProperties["garden.network.host-ip"]).To(Equal("255.255.255.255"))
		})
	})

	Context("when the network plugin returns dns_servers", func() {
		BeforeEach(func() {
			pluginReturn = `{
					"properties":{
						"garden.network.container-ip":"10.255.10.10"
					},
					"dns_servers": [
						"1.2.3.4",
						"1.2.3.5"
					]
			  }`
		})

		It("sets the nameserver entries in the container's /etc/resolv.conf to the values supplied by the network plugin", func() {
			Expect(getNameservers(container)).To(Equal([]string{"1.2.3.4", "1.2.3.5"}))
		})

		Context("when the rootFS does not contain /etc/resolv.conf", func() {
			var rootFSWithoutHostsAndResolv string
			BeforeEach(func() {
				rootFSWithoutHostsAndResolv := createRootfs(func(root string) {
					Expect(os.Chmod(filepath.Join(root, "tmp"), 0777)).To(Succeed())
					Expect(os.Remove(filepath.Join(root, "etc", "hosts"))).To(Succeed())
					Expect(os.Remove(filepath.Join(root, "etc", "resolv.conf"))).To(Succeed())
				}, 0755)

				containerSpec.RootFSPath = fmt.Sprintf("raw://%s", rootFSWithoutHostsAndResolv)
			})

			AfterEach(func() {
				Expect(os.RemoveAll(rootFSWithoutHostsAndResolv)).To(Succeed())
			})

			It("sets the nameserver entries in the container's /etc/resolv.conf to the values supplied by the network plugin", func() {
				Expect(getNameservers(container)).To(Equal([]string{"1.2.3.4", "1.2.3.5"}))
			})
		})
	})
})
<|endoftext|>


<commit_before>package barcode

import (
	"bytes"
	bar "github.com/boombuler/barcode"
	"github.com/boombuler/barcode/qr"
	"github.com/hackform/governor"
	"github.com/sirupsen/logrus"
	"image/png"
	"net/http"
)

const (
	moduleID  = "barcode"
	barQRSize = 256
)

const (
	// TransportQRCode is a type constant for QRCode
	TransportQRCode = iota
)

type (
	// Generator is a service that encodes data into barcodes
	Generator interface {
		Generate(data string, transport int) (*bytes.Buffer, *governor.Error)
	}

	barcodeService struct {
		encoder *png.Encoder
		log     *logrus.Logger
	}
)

// New returns a new barcode service
func New(conf governor.Config, l *logrus.Logger) Generator {
	l.Info("initialized barcode service")

	return &barcodeService{
		encoder: &png.Encoder{
			CompressionLevel: png.BestCompression,
		},
		log: l,
	}
}

const (
	moduleIDGenerate = moduleID + ".Generate"
)

// Generate encodes data as a barcode image represented by a bytes Buffer
func (b *barcodeService) Generate(data string, transport int) (*bytes.Buffer, *governor.Error) {
	switch transport {
	case TransportQRCode:
		qrCode, err := qr.Encode(data, qr.H, qr.Unicode)
		if err != nil {
			return nil, governor.NewError(moduleIDGenerate, err.Error(), 0, http.StatusInternalServerError)
		}

		qrCode, err = bar.Scale(qrCode, barQRSize, barQRSize)
		if err != nil {
			return nil, governor.NewError(moduleIDGenerate, err.Error(), 0, http.StatusInternalServerError)
		}

		buf := &bytes.Buffer{}
		if err := b.encoder.Encode(buf, qrCode); err != nil {
			return nil, governor.NewError(moduleIDGenerate, err.Error(), 0, http.StatusInternalServerError)
		}

		return buf, nil
	}

	return nil, governor.NewError(moduleIDGenerate, "invalid transport", 0, http.StatusInternalServerError)
}
<commit_msg>Improve clarity of barcode generation method name<commit_after>package barcode

import (
	"bytes"
	bar "github.com/boombuler/barcode"
	"github.com/boombuler/barcode/qr"
	"github.com/hackform/governor"
	"github.com/sirupsen/logrus"
	"image/png"
	"net/http"
)

const (
	moduleID  = "barcode"
	barQRSize = 256
)

const (
	// TransportQRCode is a type constant for QRCode
	TransportQRCode = iota
)

type (
	// Generator is a service that encodes data into barcodes
	Generator interface {
		GenerateBarcode(transport int, data string) (*bytes.Buffer, *governor.Error)
	}

	barcodeService struct {
		encoder *png.Encoder
		log     *logrus.Logger
	}
)

// New returns a new barcode service
func New(conf governor.Config, l *logrus.Logger) Generator {
	l.Info("initialized barcode service")

	return &barcodeService{
		encoder: &png.Encoder{
			CompressionLevel: png.BestCompression,
		},
		log: l,
	}
}

const (
	moduleIDGenerate = moduleID + ".Generate"
)

// GenerateBarcode encodes data as a barcode image represented by a bytes Buffer
func (b *barcodeService) GenerateBarcode(transport int, data string) (*bytes.Buffer, *governor.Error) {
	switch transport {
	case TransportQRCode:
		qrCode, err := qr.Encode(data, qr.H, qr.Unicode)
		if err != nil {
			return nil, governor.NewError(moduleIDGenerate, err.Error(), 0, http.StatusInternalServerError)
		}

		qrCode, err = bar.Scale(qrCode, barQRSize, barQRSize)
		if err != nil {
			return nil, governor.NewError(moduleIDGenerate, err.Error(), 0, http.StatusInternalServerError)
		}

		buf := &bytes.Buffer{}
		if err := b.encoder.Encode(buf, qrCode); err != nil {
			return nil, governor.NewError(moduleIDGenerate, err.Error(), 0, http.StatusInternalServerError)
		}

		return buf, nil
	}

	return nil, governor.NewError(moduleIDGenerate, "invalid transport", 0, http.StatusInternalServerError)
}
<|endoftext|>


<commit_before>package game

import (
	"io"
	"labix.org/v2/mgo"
	"mud/database"
	"mud/utils"
	"net"
	"strings"
)

func toggleExit(room database.Room, dir database.ExitDirection) {
}

func getToggleExitMenu(room database.Room) utils.Menu {

	onOrOff := func(on bool) string {
		if on {
			return "On"
		}

		return "Off"
	}

	menu := utils.NewMenu("Edit Exits")

	menu.AddAction("n", "[N]orth: "+onOrOff(room.HasExit(database.North)))
	menu.AddAction("e", "[E]ast: "+onOrOff(room.HasExit(database.East)))
	menu.AddAction("s", "[S]outh: "+onOrOff(room.HasExit(database.South)))
	menu.AddAction("w", "[W]est: "+onOrOff(room.HasExit(database.West)))
	menu.AddAction("u", "[U]p: "+onOrOff(room.HasExit(database.Up)))
	menu.AddAction("d", "[D]own: "+onOrOff(room.HasExit(database.Down)))

	return menu
}

func Exec(session *mgo.Session, conn net.Conn, character string) {

	room, err := database.GetCharacterRoom(session, character)

	processCommand := func(command string) {

		switch command {
		case "?":
			fallthrough
		case "help":
		case "dig":
		case "edit":
			io.WriteString(conn, room.ToString(database.EditMode))

			for {
				input := utils.GetUserInput(conn, "\nSelect a section to edit> ")

				switch input {
				case "":
					utils.WriteLine(conn, room.ToString(database.ReadMode))
					return

				case "1":
					input = utils.GetRawUserInput(conn, "Enter new title: ")

					if input != "" {
						room.Title = input
						database.SetRoomTitle(session, room.Id, input)
					}
					utils.WriteLine(conn, room.ToString(database.EditMode))

				case "2":
					input = utils.GetRawUserInput(conn, "Enter new description: ")

					if input != "" {
						room.Description = input
						database.SetRoomDescription(session, room.Id, input)
					}
					utils.WriteLine(conn, room.ToString(database.EditMode))

				case "3":
					for {
						done := false
						menu := getToggleExitMenu(room)
						choice, _ := menu.Exec(conn)

						switch choice {
						case "n":
							toggleExit(room, database.North)
						case "e":
							toggleExit(room, database.East)
						case "s":
							toggleExit(room, database.South)
						case "w":
							toggleExit(room, database.West)
						case "u":
							toggleExit(room, database.Up)
						case "d":
							toggleExit(room, database.Down)
						case "":
							done = true
						}

						if done {
							break
						}
					}

					io.WriteString(conn, room.ToString(database.EditMode))

				default:
					utils.WriteLine(conn, "Invalid selection")
				}
			}

		case "rebuild":
			input := utils.GetUserInput(conn, "Are you sure (delete all rooms and starts from scratch)? ")
			if input[0] == 'y' || input == "yes" {
				database.GenerateDefaultMap(session)
			}
			room, err = database.GetCharacterRoom(session, character)

		default:
			io.WriteString(conn, "Unrecognized command")
		}
	}

	utils.WriteLine(conn, "Welcome, "+utils.FormatName(character))
	io.WriteString(conn, room.ToString(database.ReadMode))

	for {
		utils.PanicIfError(err)

		input := utils.GetUserInput(conn, "\n> ")

		if strings.HasPrefix(input, "/") {
			processCommand(input[1:len(input)])
		} else {
			switch input {
            case "n":
                fallthrough
            case "e":
                fallthrough
            case "s":
                fallthrough
            case "w":
                fallthrough
            case "u":
                fallthrough
            case "d":
                utils.WriteLine(conn, "You can't go that way")

			case "quit":
				fallthrough
			case "exit":
				utils.WriteLine(conn, "Goodbye")
				conn.Close()
				panic("User quit")
			case "l":
				io.WriteString(conn, room.ToString(database.ReadMode))
			case "i":
				io.WriteString(conn, "You aren't carrying anything")
			default:
				exit := database.StringToDirection(input)
				if room.HasExit(exit) {
					database.SetCharacterRoom(session, character, room.ExitId(exit))
				} else {
					io.WriteString(conn, "You can't do that")
				}
			}
		}
	}
}

// vim: nocindent
<commit_msg>Made newline writing more consistent<commit_after>package game

import (
	"labix.org/v2/mgo"
	"mud/database"
	"mud/utils"
	"net"
	"strings"
)

func toggleExit(room database.Room, dir database.ExitDirection) {
}

func getToggleExitMenu(room database.Room) utils.Menu {

	onOrOff := func(on bool) string {
		if on {
			return "On"
		}

		return "Off"
	}

	menu := utils.NewMenu("Edit Exits")

	menu.AddAction("n", "[N]orth: "+onOrOff(room.HasExit(database.North)))
	menu.AddAction("e", "[E]ast: "+onOrOff(room.HasExit(database.East)))
	menu.AddAction("s", "[S]outh: "+onOrOff(room.HasExit(database.South)))
	menu.AddAction("w", "[W]est: "+onOrOff(room.HasExit(database.West)))
	menu.AddAction("u", "[U]p: "+onOrOff(room.HasExit(database.Up)))
	menu.AddAction("d", "[D]own: "+onOrOff(room.HasExit(database.Down)))

	return menu
}

func Exec(session *mgo.Session, conn net.Conn, character string) {

	room, err := database.GetCharacterRoom(session, character)

	processCommand := func(command string) {

		switch command {
		case "?":
			fallthrough
		case "help":
		case "dig":
		case "edit":
			utils.WriteLine(conn, room.ToString(database.EditMode))

			for {
				input := utils.GetUserInput(conn, "Select a section to edit> ")

				switch input {
				case "":
					utils.WriteLine(conn, room.ToString(database.ReadMode))
					return

				case "1":
					input = utils.GetRawUserInput(conn, "Enter new title: ")

					if input != "" {
						room.Title = input
						database.SetRoomTitle(session, room.Id, input)
					}
					utils.WriteLine(conn, room.ToString(database.EditMode))

				case "2":
					input = utils.GetRawUserInput(conn, "Enter new description: ")

					if input != "" {
						room.Description = input
						database.SetRoomDescription(session, room.Id, input)
					}
					utils.WriteLine(conn, room.ToString(database.EditMode))

				case "3":
					for {
						done := false
						menu := getToggleExitMenu(room)
						choice, _ := menu.Exec(conn)

						switch choice {
						case "n":
							toggleExit(room, database.North)
						case "e":
							toggleExit(room, database.East)
						case "s":
							toggleExit(room, database.South)
						case "w":
							toggleExit(room, database.West)
						case "u":
							toggleExit(room, database.Up)
						case "d":
							toggleExit(room, database.Down)
						case "":
							done = true
						}

						if done {
							break
						}
					}

					utils.WriteLine(conn, room.ToString(database.EditMode))

				default:
					utils.WriteLine(conn, "Invalid selection")
				}
			}

		case "rebuild":
			input := utils.GetUserInput(conn, "Are you sure (delete all rooms and starts from scratch)? ")
			if input[0] == 'y' || input == "yes" {
				database.GenerateDefaultMap(session)
			}
			room, err = database.GetCharacterRoom(session, character)

		default:
			utils.WriteLine(conn, "Unrecognized command")
		}
	}

	utils.WriteLine(conn, "Welcome, "+utils.FormatName(character))
	utils.WriteLine(conn, room.ToString(database.ReadMode))

	for {
		utils.PanicIfError(err)

		input := utils.GetUserInput(conn, "> ")

		if strings.HasPrefix(input, "/") {
			processCommand(input[1:len(input)])
		} else {
			switch input {
            case "n":
                fallthrough
            case "e":
                fallthrough
            case "s":
                fallthrough
            case "w":
                fallthrough
            case "u":
                fallthrough
            case "d":
                utils.WriteLine(conn, "You can't go that way")

			case "quit":
				fallthrough
			case "exit":
				utils.WriteLine(conn, "Goodbye")
				conn.Close()
				panic("User quit")
			case "l":
				utils.WriteLine(conn, room.ToString(database.ReadMode))
			case "i":
				utils.WriteLine(conn, "You aren't carrying anything")
			default:
				exit := database.StringToDirection(input)
				if room.HasExit(exit) {
					database.SetCharacterRoom(session, character, room.ExitId(exit))
				} else {
					utils.WriteLine(conn, "You can't do that")
				}
			}
		}
	}
}

// vim: nocindent
<|endoftext|>


<commit_before>package pholcus_lib

import (
	// 基础包
	"github.com/henrylee2cn/pholcus/common/goquery"                        //DOM解析
	"github.com/henrylee2cn/pholcus/app/downloader/request" //必需
	// "github.com/henrylee2cn/pholcus/logs"           //信息输出
	. "github.com/henrylee2cn/pholcus/app/spider" //必需
	// . "github.com/henrylee2cn/pholcus/app/spider/common" //选用

	// net包
	// "net/http" //设置http.Header
	// "net/url"

	// 编码包
	// "encoding/xml"
	// "encoding/json"

	// 字符串处理包
	// "regexp"
	"strconv"
	// "strings"
	// 其他包
	 "fmt"
	// "math"
	// "time"
	//"log"
	//"log"
)

func init() {
	Xizhangxt.Register()
}

var Xizhangxt = &Spider{
	Name:        "西藏信托",
	Description: "西藏信托净值数据 [Auto Page] [http://www.ttco.cn/ttco/page_networth]",
	// Pausetime: 300,
	// Keyin:   KEYIN,
	// Limit:        LIMIT,
	NotDefaultField: true,

	Namespace: func(*Spider) string{
		return "xintuo"
	},
	// 子命名空间相对于表名，可依赖具体数据内容，可选
	SubNamespace: func(self *Spider, dataCell map[string]interface{}) string {
		return "fund_src_nav"
	},

	EnableCookie: false,
	RuleTree: &RuleTree{

		Root: func(ctx *Context) {
			ctx.Aid(map[string]interface{}{"loop": [2]int{1, 2}, "Rule": "生成请求"}, "生成请求")
		},

		Trunk: map[string]*Rule{

			"生成请求": {

				AidFunc: func(ctx *Context, aid map[string]interface{}) interface{} {
					for loop := aid["loop"].([2]int); loop[0] < loop[1]; loop[0]++ {
						ctx.AddQueue(&request.Request{
							Url:  "http://www.ttco.cn/ttco/page_networth",
							Rule: aid["Rule"].(string),
						})
					}
					return nil
				},
				ParseFunc: func(ctx *Context) {
					query := ctx.GetDom()

                    //ss := query.Find("pages")
                    //fmt.Println(ss)
					ss := query.Find("#_pageSum")
					var countStr string
					countStr = ss.Text()
					var count int
					count, error := strconv.Atoi(countStr)
					if error != nil{
						fmt.Println("string convert failed")
					}

					page := 0

				 	for i := 1; i < count + 1; i++{
						 page++
						 	ctx.AddQueue(&request.Request{
								Url:  "http://www.ttco.cn/ttco/page_networth?st=dd&netWorthPage.pageSize=10&netWorthPage.pageNum=" + strconv.Itoa(i),
								Rule: "获取结果",
								Temp: map[string]interface{}{
									"level1pages" : page,
								},
							})
					 }
				},
			},

			"获取结果": {
				//注意：有无字段语义和是否输出数据必须保持一致
				ItemFields: []string{
					"基金ID",
					"名称",
					"净值",
					"累计净值",
					"估值日期",
				},
				ParseFunc: func(ctx *Context) {
					query := ctx.GetDom()

					ss := query.Find(".mainDetail tbody").Find("tr")

					var page int
					ctx.GetTemp("level1pages", &page)

					count := 0

                    ss.Each(func(i int, goq *goquery.Selection) {

							titleLine := goq.Children().Eq(0).Text()
							if titleLine != "产品名称"{
								mingchen := goq.Children().Eq(0).Find("a").Text()
								jingzhi := goq.Children().Eq(3).Text()
								leijijingzhi := goq.Children().Eq(4).Text()
								guzhiriqi := goq.Children().Eq(7).Text()

								count++
								fundID := "XTXIZANG" + "P" + strconv.Itoa(page) + "L" + strconv.Itoa(count)

								ctx.Output(map[int]interface{}{
									0: fundID,
									1: mingchen,
									2: jingzhi,
									3: leijijingzhi,
									4: guzhiriqi,
								})
							}
					})
				},
			},

		},
	},
}<commit_msg>继续完善一个新的规则<commit_after>package pholcus_lib

import (
	// 基础包
	"github.com/henrylee2cn/pholcus/common/goquery"                        //DOM解析
	"github.com/henrylee2cn/pholcus/app/downloader/request" //必需
	// "github.com/henrylee2cn/pholcus/logs"           //信息输出
	. "github.com/henrylee2cn/pholcus/app/spider" //必需
	// . "github.com/henrylee2cn/pholcus/app/spider/common" //选用

	// net包
	// "net/http" //设置http.Header
	// "net/url"

	// 编码包
	// "encoding/xml"
	// "encoding/json"

	// 字符串处理包
	// "regexp"
	"strconv"
	// "strings"
	// 其他包
	 "fmt"
	// "math"
	// "time"
	//"log"
	//"log"
)

func init() {
	Xizhangxt.Register()
}

var Xizhangxt = &Spider{
	Name:        "西藏信托",
	Description: "西藏信托净值数据 [Auto Page] [http://www.ttco.cn/ttco/page_networth]",
	// Pausetime: 300,
	// Keyin:   KEYIN,
	// Limit:        LIMIT,
	NotDefaultField: true,

	Namespace: func(*Spider) string{
		return "xintuo"
	},
	// 子命名空间相对于表名，可依赖具体数据内容，可选
	SubNamespace: func(self *Spider, dataCell map[string]interface{}) string {
		return "fund_src_nav"
	},

	EnableCookie: false,
	RuleTree: &RuleTree{

		Root: func(ctx *Context) {
			ctx.Aid(map[string]interface{}{"loop": [2]int{1, 2}, "Rule": "生成请求"}, "生成请求")
		},

		Trunk: map[string]*Rule{

			"生成请求": {

				AidFunc: func(ctx *Context, aid map[string]interface{}) interface{} {
					for loop := aid["loop"].([2]int); loop[0] < loop[1]; loop[0]++ {
						ctx.AddQueue(&request.Request{
							Url:  "http://www.ttco.cn/ttco/page_networth",
							Rule: aid["Rule"].(string),
						})
					}
					return nil
				},
				ParseFunc: func(ctx *Context) {
					query := ctx.GetDom()

                    //ss := query.Find("pages")
                    //fmt.Println(ss)
					ss := query.Find("#_pageSum")
					var countStr string
					countStr = ss.Text()
					var count int
					count, error := strconv.Atoi(countStr)
					if error != nil{
						fmt.Println("string convert failed")
					}

					page := 0

				 	for i := 1; i < count + 1; i++{
						 page++
						 	ctx.AddQueue(&request.Request{
								Url:  "http://www.ttco.cn/ttco/page_networth?st=dd&netWorthPage.pageSize=10&netWorthPage.pageNum=" + strconv.Itoa(i),
								Rule: "获取结果",
								Temp: map[string]interface{}{
									"level1pages" : page,
								},
							})
					 }
				},
			},

			"获取结果": {
				//注意：有无字段语义和是否输出数据必须保持一致
				ItemFields: []string{
					"基金ID",
					"名称",
					"净值",
					"累计净值",
					"估值日期",
				},
				ParseFunc: func(ctx *Context) {
					query := ctx.GetDom()

					ss := query.Find(".mainDetail .productList tbody").Find("tr")

					var page int
					ctx.GetTemp("level1pages", &page)

					count := 0

                    ss.Each(func(i int, goq *goquery.Selection) {

							titleLine := goq.Children().Eq(0).Text()
							if titleLine != "产品名称"{
								mingchen := goq.Children().Eq(0).Find("a").Text()
								jingzhi := goq.Children().Eq(3).Text()
								leijijingzhi := goq.Children().Eq(4).Text()
								guzhiriqi := goq.Children().Eq(7).Text()

								count++
								fundID := "XTXIZANG" + "P" + strconv.Itoa(page) + "L" + strconv.Itoa(count)

								ctx.Output(map[int]interface{}{
									0: fundID,
									1: mingchen,
									2: jingzhi,
									3: leijijingzhi,
									4: guzhiriqi,
								})
							}
					})
				},
			},

		},
	},
}<|endoftext|>


<commit_before>package graph

import (
	"container/heap"
	"fmt"
	"math"
)

// Dijkstra returns the shortest path using Dijkstra
// algorithm with a min-priority queue. This algorithm
// does not work with negative weight edges.
// (https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)
//
//	 0. Dijkstra(G, source, target)
//	 1.
//	 2. 	let Q be a priority queue
//	 3. 	distance[source] = 0
//	 4.
//	 5. 	for each vertex v in G:
//	 6.
//	 7. 		if v ≠ source:
//	 8. 			distance[v] = ∞
//	 9. 			prev[v] = undefined
//	10.
//	11. 		Q.add_with_priority(v, distance[v])
//	12.
//	13. 	while Q is not empty:
//	14.
//	15. 		u = Q.extract_min()
//	16. 		if u == target:
//	17. 			break
//	18.
//	19. 		for each child vertex v of u:
//	20.
//	21. 			alt = distance[u] + weight(u, v)
//	22. 			if distance[v] > alt:
//	23. 				distance[v] = alt
//	24. 				prev[v] = u
//	25. 				Q.decrease_priority(v, alt)
//	26.
//	27. 	path = []
//	28. 	u = target
//	29. 	while prev[u] is defined:
//	30. 		path.push_front(u)
//	31. 		u = prev[u]
//	32.
//	33. 	return path, prev
//
func Dijkstra(g Graph, source, target string) ([]string, map[string]float64, error) {

	// let Q be a priority queue
	minHeap := &vertexDistanceHeap{}

	// distance[source] = 0
	distance := make(map[string]float64)
	distance[source] = 0.0

	// for each vertex v in G:
	for vtx := range g.GetVertices() {

		// if v ≠ source:
		if vtx != source {
			// distance[v] = ∞
			distance[vtx] = math.MaxFloat64

			// prev[v] = undefined
			// prev[v] = ""
		}

		// Q.add_with_priority(v, distance[v])
		vd := vertexDistance{}
		vd.vertex = vtx
		vd.distance = distance[vtx]

		heap.Push(minHeap, vd)
	}

	heap.Init(minHeap)
	prev := make(map[string]string)

	// while Q is not empty:
	for minHeap.Len() != 0 {

		// u = Q.extract_min()
		u := heap.Pop(minHeap).(vertexDistance)

		// if u == target:
		if u.vertex == target {
			break
		}

		// for each child vertex v of u:
		cmap, err := g.GetChildren(u.vertex)
		if err != nil {
			return nil, nil, err
		}
		for v := range cmap {

			// alt = distance[u] + weight(u, v)
			weight, err := g.GetWeight(u.vertex, v)
			if err != nil {
				return nil, nil, err
			}
			alt := distance[u.vertex] + weight

			// if distance[v] > alt:
			if distance[v] > alt {

				// distance[v] = alt
				distance[v] = alt

				// prev[v] = u
				prev[v] = u.vertex

				// Q.decrease_priority(v, alt)
				minHeap.updateDistance(v, alt)
				heap.Init(minHeap)
			}
		}
	}

	// path = []
	path := []string{}

	// u = target
	u := target

	// while prev[u] is defined:
	for {
		if _, ok := prev[u]; !ok {
			break
		}
		// path.push_front(u)
		temp := make([]string, len(path)+1)
		temp[0] = u
		copy(temp[1:], path)
		path = temp

		// u = prev[u]
		u = prev[u]
	}

	// add the source
	temp := make([]string, len(path)+1)
	temp[0] = source
	copy(temp[1:], path)
	path = temp

	return path, distance, nil
}

// BellmanFord returns the shortest path using Bellman-Ford algorithm
// This algorithm works with negative weight edges.
// Time complexity is O(|V||E|).
// (http://courses.csail.mit.edu/6.006/spring11/lectures/lec15.pdf)
// It returns error when there is a negative-weight cycle.
// A negatively-weighted cycle adds up to infinite negative-weight.
//
//	 0. BellmanFord(G, source, target)
//	 1.
//	 2. 	distance[source] = 0
//	 3.
//	 4. 	for each vertex v in G:
//	 5.
//	 6. 		if v ≠ source:
//	 7. 			distance[v] = ∞
//	 8. 			prev[v] = undefined
//	 9.
//	10.
//	11. 	for 1 to |V|-1:
//	12.
//	13. 		for every edge (u, v):
//	14.
//	15. 			alt = distance[u] + weight(u, v)
//	16. 			if distance[v] > alt:
//	17. 				distance[v] = alt
//	18. 				prev[v] = u
//	19.
//	20.
//	21. 	for every edge (u, v):
//	22.
//	23. 		alt = distance[u] + weight(u, v)
//	24. 		if distance[v] > alt:
//	25. 			there is a negative-weight cycle
//	26.
//	27.
//	28. 	path = []
//	29. 	u = target
//	30. 	while prev[u] is defined:
//	31. 		path.push_front(u)
//	32. 		u = prev[u]
//	33.
//	34. 	return path, prev
//
func BellmanFord(g Graph, source, target string) ([]string, map[string]float64, error) {

	// distance[source] = 0
	distance := make(map[string]float64)
	distance[source] = 0.0

	// for each vertex v in G:
	for vtx := range g.GetVertices() {

		// if v ≠ source:
		if vtx != source {
			// distance[v] = ∞
			distance[vtx] = math.MaxFloat64

			// prev[v] = undefined
			// prev[v] = ""
		}
	}

	prev := make(map[string]string)

	// for 1 to |V|-1:
	for i := 1; i <= len(g.GetVertices())-1; i++ {

		// for every edge (u, v):
		for vtx := range g.GetVertices() {

			cmap, err := g.GetChildren(vtx)
			if err != nil {
				return nil, nil, err
			}
			for v := range cmap {
				u := vtx
				// edge (u, v)
				weight, err := g.GetWeight(u, v)
				if err != nil {
					return nil, nil, err
				}

				// alt = distance[u] + weight(u, v)
				alt := distance[u] + weight

				// if distance[v] > alt:
				if distance[v] > alt {
					// distance[v] = alt
					distance[v] = alt

					// prev[v] = u
					prev[v] = u
				}
			}

			pmap, err := g.GetParents(vtx)
			if err != nil {
				return nil, nil, err
			}
			for u := range pmap {
				v := vtx
				// edge (u, v)
				weight, err := g.GetWeight(u, v)
				if err != nil {
					return nil, nil, err
				}

				// alt = distance[u] + weight(u, v)
				alt := distance[u] + weight

				// if distance[v] > alt:
				if distance[v] > alt {
					// distance[v] = alt
					distance[v] = alt

					// prev[v] = u
					prev[v] = u
				}
			}
		}
	}

	// for every edge (u, v):
	for vtx := range g.GetVertices() {

		cmap, err := g.GetChildren(vtx)
		if err != nil {
			return nil, nil, err
		}
		for v := range cmap {
			u := vtx
			// edge (u, v)
			weight, err := g.GetWeight(u, v)
			if err != nil {
				return nil, nil, err
			}

			// alt = distance[u] + weight(u, v)
			alt := distance[u] + weight

			// if distance[v] > alt:
			if distance[v] > alt {
				return nil, nil, fmt.Errorf("there is a negative-weight cycle: %v", g)
			}
		}

		pmap, err := g.GetParents(vtx)
		if err != nil {
			return nil, nil, err
		}
		for u := range pmap {
			v := vtx
			// edge (u, v)
			weight, err := g.GetWeight(u, v)
			if err != nil {
				return nil, nil, err
			}

			// alt = distance[u] + weight(u, v)
			alt := distance[u] + weight

			// if distance[v] > alt:
			if distance[v] > alt {
				return nil, nil, fmt.Errorf("there is a negative-weight cycle: %v", g)
			}
		}
	}

	// path = []
	path := []string{}

	// u = target
	u := target

	// while prev[u] is defined:
	for {
		if _, ok := prev[u]; !ok {
			break
		}
		// path.push_front(u)
		temp := make([]string, len(path)+1)
		temp[0] = u
		copy(temp[1:], path)
		path = temp

		// u = prev[u]
		u = prev[u]
	}

	// add the source
	temp := make([]string, len(path)+1)
	temp[0] = source
	copy(temp[1:], path)
	path = temp

	return path, distance, nil
}
<commit_msg>fix dijkstra algorithm from O(N^2) to O(N logN)<commit_after>package graph

import (
	"container/heap"
	"fmt"
	"math"
)

// Dijkstra returns the shortest path using Dijkstra
// algorithm with a min-priority queue. This algorithm
// does not work with negative weight edges.
// (https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm)
//
//	 0. Dijkstra(G, source, target)
//	 1.
//	 2. 	let Q be a priority queue
//	 3. 	distance[source] = 0
//	 4.
//	 5. 	for each vertex v in G:
//	 6.
//	 7. 		if v ≠ source:
//	 8. 			distance[v] = ∞
//	 9. 			prev[v] = undefined
//	10.
//	11. 		Q.add_with_priority(v, distance[v])
//	12.
//	13. 	while Q is not empty:
//	14.
//	15. 		u = Q.extract_min()
//	16. 		if u == target:
//	17. 			break
//	18.
//	19. 		for each child vertex v of u:
//	20.
//	21. 			alt = distance[u] + weight(u, v)
//	22. 			if distance[v] > alt:
//	23. 				distance[v] = alt
//	24. 				prev[v] = u
//	25. 				Q.decrease_priority(v, alt)
//	26.
//	27. 	path = []
//	28. 	u = target
//	29. 	while prev[u] is defined:
//	30. 		path.push_front(u)
//	31. 		u = prev[u]
//	32.
//	33. 	return path, prev
//
func Dijkstra(g Graph, source, target string) ([]string, map[string]float64, error) {

	// let Q be a priority queue
	minHeap := &vertexDistanceHeap{}

	// distance[source] = 0
	distance := make(map[string]float64)
	distance[source] = 0.0

	// for each vertex v in G:
	for vtx := range g.GetVertices() {

		// if v ≠ source:
		if vtx != source {
			// distance[v] = ∞
			distance[vtx] = math.MaxFloat64

			// prev[v] = undefined
			// prev[v] = ""
		}

		// Q.add_with_priority(v, distance[v])
		vd := vertexDistance{}
		vd.vertex = vtx
		vd.distance = distance[vtx]

		heap.Push(minHeap, vd)
	}

	heap.Init(minHeap)
	prev := make(map[string]string)

	// while Q is not empty:
	for minHeap.Len() != 0 {

		// u = Q.extract_min()
		u := heap.Pop(minHeap).(vertexDistance)

		// if u == target:
		if u.vertex == target {
			break
		}

		// for each child vertex v of u:
		cmap, err := g.GetChildren(u.vertex)
		if err != nil {
			return nil, nil, err
		}
		for v := range cmap {

			// alt = distance[u] + weight(u, v)
			weight, err := g.GetWeight(u.vertex, v)
			if err != nil {
				return nil, nil, err
			}
			alt := distance[u.vertex] + weight

			// if distance[v] > alt:
			if distance[v] > alt {

				// distance[v] = alt
				distance[v] = alt

				// prev[v] = u
				prev[v] = u.vertex

				// Q.decrease_priority(v, alt)
				minHeap.updateDistance(v, alt)
			}
		}
		heap.Init(minHeap)
	}

	// path = []
	path := []string{}

	// u = target
	u := target

	// while prev[u] is defined:
	for {
		if _, ok := prev[u]; !ok {
			break
		}
		// path.push_front(u)
		temp := make([]string, len(path)+1)
		temp[0] = u
		copy(temp[1:], path)
		path = temp

		// u = prev[u]
		u = prev[u]
	}

	// add the source
	temp := make([]string, len(path)+1)
	temp[0] = source
	copy(temp[1:], path)
	path = temp

	return path, distance, nil
}

// BellmanFord returns the shortest path using Bellman-Ford algorithm
// This algorithm works with negative weight edges.
// Time complexity is O(|V||E|).
// (http://courses.csail.mit.edu/6.006/spring11/lectures/lec15.pdf)
// It returns error when there is a negative-weight cycle.
// A negatively-weighted cycle adds up to infinite negative-weight.
//
//	 0. BellmanFord(G, source, target)
//	 1.
//	 2. 	distance[source] = 0
//	 3.
//	 4. 	for each vertex v in G:
//	 5.
//	 6. 		if v ≠ source:
//	 7. 			distance[v] = ∞
//	 8. 			prev[v] = undefined
//	 9.
//	10.
//	11. 	for 1 to |V|-1:
//	12.
//	13. 		for every edge (u, v):
//	14.
//	15. 			alt = distance[u] + weight(u, v)
//	16. 			if distance[v] > alt:
//	17. 				distance[v] = alt
//	18. 				prev[v] = u
//	19.
//	20.
//	21. 	for every edge (u, v):
//	22.
//	23. 		alt = distance[u] + weight(u, v)
//	24. 		if distance[v] > alt:
//	25. 			there is a negative-weight cycle
//	26.
//	27.
//	28. 	path = []
//	29. 	u = target
//	30. 	while prev[u] is defined:
//	31. 		path.push_front(u)
//	32. 		u = prev[u]
//	33.
//	34. 	return path, prev
//
func BellmanFord(g Graph, source, target string) ([]string, map[string]float64, error) {

	// distance[source] = 0
	distance := make(map[string]float64)
	distance[source] = 0.0

	// for each vertex v in G:
	for vtx := range g.GetVertices() {

		// if v ≠ source:
		if vtx != source {
			// distance[v] = ∞
			distance[vtx] = math.MaxFloat64

			// prev[v] = undefined
			// prev[v] = ""
		}
	}

	prev := make(map[string]string)

	// for 1 to |V|-1:
	for i := 1; i <= len(g.GetVertices())-1; i++ {

		// for every edge (u, v):
		for vtx := range g.GetVertices() {

			cmap, err := g.GetChildren(vtx)
			if err != nil {
				return nil, nil, err
			}
			for v := range cmap {
				u := vtx
				// edge (u, v)
				weight, err := g.GetWeight(u, v)
				if err != nil {
					return nil, nil, err
				}

				// alt = distance[u] + weight(u, v)
				alt := distance[u] + weight

				// if distance[v] > alt:
				if distance[v] > alt {
					// distance[v] = alt
					distance[v] = alt

					// prev[v] = u
					prev[v] = u
				}
			}

			pmap, err := g.GetParents(vtx)
			if err != nil {
				return nil, nil, err
			}
			for u := range pmap {
				v := vtx
				// edge (u, v)
				weight, err := g.GetWeight(u, v)
				if err != nil {
					return nil, nil, err
				}

				// alt = distance[u] + weight(u, v)
				alt := distance[u] + weight

				// if distance[v] > alt:
				if distance[v] > alt {
					// distance[v] = alt
					distance[v] = alt

					// prev[v] = u
					prev[v] = u
				}
			}
		}
	}

	// for every edge (u, v):
	for vtx := range g.GetVertices() {

		cmap, err := g.GetChildren(vtx)
		if err != nil {
			return nil, nil, err
		}
		for v := range cmap {
			u := vtx
			// edge (u, v)
			weight, err := g.GetWeight(u, v)
			if err != nil {
				return nil, nil, err
			}

			// alt = distance[u] + weight(u, v)
			alt := distance[u] + weight

			// if distance[v] > alt:
			if distance[v] > alt {
				return nil, nil, fmt.Errorf("there is a negative-weight cycle: %v", g)
			}
		}

		pmap, err := g.GetParents(vtx)
		if err != nil {
			return nil, nil, err
		}
		for u := range pmap {
			v := vtx
			// edge (u, v)
			weight, err := g.GetWeight(u, v)
			if err != nil {
				return nil, nil, err
			}

			// alt = distance[u] + weight(u, v)
			alt := distance[u] + weight

			// if distance[v] > alt:
			if distance[v] > alt {
				return nil, nil, fmt.Errorf("there is a negative-weight cycle: %v", g)
			}
		}
	}

	// path = []
	path := []string{}

	// u = target
	u := target

	// while prev[u] is defined:
	for {
		if _, ok := prev[u]; !ok {
			break
		}
		// path.push_front(u)
		temp := make([]string, len(path)+1)
		temp[0] = u
		copy(temp[1:], path)
		path = temp

		// u = prev[u]
		u = prev[u]
	}

	// add the source
	temp := make([]string, len(path)+1)
	temp[0] = source
	copy(temp[1:], path)
	path = temp

	return path, distance, nil
}
<|endoftext|>


<commit_before>package task

import (
	"neon/build"
	"neon/util"
)

func init() {
	build.TaskMap["try"] = build.TaskDescriptor{
		Constructor: Try,
		Help:        "Try/catch construct",
	}
}

func Try(target *build.Target, args util.Object) (build.Task, error) {
	fields := []string{"try", "catch"}
	if err := CheckFields(args, fields, fields); err != nil {
		return nil, err
	}
	trySteps, err := ParseSteps(target, args, "try")
	if err != nil {
		return nil, err
	}
	catchSteps, err := ParseSteps(target, args, "catch")
	if err != nil {
		return nil, err
	}
	return func() error {
		err := RunSteps(trySteps)
		if err != nil {
			target.Build.Context.SetProperty("error", err.Error())
			err = RunSteps(catchSteps)
			if err != nil {
				return err
			}
		}
		return nil
	}, nil
}
<commit_msg>Fixed by initializing error to empty string<commit_after>package task

import (
	"neon/build"
	"neon/util"
)

func init() {
	build.TaskMap["try"] = build.TaskDescriptor{
		Constructor: Try,
		Help:        "Try/catch construct",
	}
}

func Try(target *build.Target, args util.Object) (build.Task, error) {
	fields := []string{"try", "catch"}
	if err := CheckFields(args, fields, fields); err != nil {
		return nil, err
	}
	trySteps, err := ParseSteps(target, args, "try")
	if err != nil {
		return nil, err
	}
	catchSteps, err := ParseSteps(target, args, "catch")
	if err != nil {
		return nil, err
	}
	return func() error {
		target.Build.Context.SetProperty("error", "")
		err := RunSteps(trySteps)
		if err != nil {
			target.Build.Context.SetProperty("error", err.Error())
			err = RunSteps(catchSteps)
			if err != nil {
				return err
			}
		}
		return nil
	}, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2015 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package args

import (
	"fmt"
	"path"

	"github.com/spf13/pflag"
	"k8s.io/gengo/args"

	"k8s.io/code-generator/cmd/client-gen/types"
	codegenutil "k8s.io/code-generator/pkg/util"
)

var DefaultInputDirs = []string{
	"k8s.io/apimachinery/pkg/fields",
	"k8s.io/apimachinery/pkg/labels",
	"k8s.io/apimachinery/pkg/watch",
	"k8s.io/apimachinery/pkg/apimachinery/registered",
}

// ClientGenArgs is a wrapper for arguments to client-gen.
type CustomArgs struct {
	// A sorted list of group versions to generate. For each of them the package path is found
	// in GroupVersionToInputPath.
	Groups []types.GroupVersions

	// Overrides for which types should be included in the client.
	IncludedTypesOverrides map[types.GroupVersion][]string

	// ClientsetName is the name of the clientset to be generated. It's
	// populated from command-line arguments.
	ClientsetName string
	// ClientsetAPIPath is the default API HTTP path for generated clients.
	ClientsetAPIPath string
	// ClientsetOnly determines if we should generate the clients for groups and
	// types along with the clientset. It's populated from command-line
	// arguments.
	ClientsetOnly bool
	// FakeClient determines if client-gen generates the fake clients.
	FakeClient bool
}

func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
	genericArgs := args.Default().WithoutDefaultFlagParsing()
	customArgs := &CustomArgs{
		ClientsetName:    "internalclientset",
		ClientsetAPIPath: "/apis",
		ClientsetOnly:    false,
		FakeClient:       true,
	}
	genericArgs.CustomArgs = customArgs
	genericArgs.InputDirs = DefaultInputDirs

	if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 {
		genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/clientset")
	}

	return genericArgs, customArgs
}

func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) {
	gvsBuilder := NewGroupVersionsBuilder(&ca.Groups)
	pflag.Var(NewGVPackagesValue(gvsBuilder, nil), "input", "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\".")
	pflag.Var(NewGVTypesValue(&ca.IncludedTypesOverrides, []string{}), "included-types-overrides", "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient will be used for other group versions.")
	pflag.Var(NewInputBasePathValue(gvsBuilder, inputBase), "input-base", "base path to look for the api group.")
	pflag.StringVarP(&ca.ClientsetName, "clientset-name", "n", ca.ClientsetName, "the name of the generated clientset package.")
	pflag.StringVarP(&ca.ClientsetAPIPath, "clientset-api-path", "", ca.ClientsetAPIPath, "the value of default API HTTP path, starting with / and without trailing /.")
	pflag.BoolVar(&ca.ClientsetOnly, "clientset-only", ca.ClientsetOnly, "when set, client-gen only generates the clientset shell, without generating the individual typed clients")
	pflag.BoolVar(&ca.FakeClient, "fake-clientset", ca.FakeClient, "when set, client-gen will generate the fake clientset that can be used in tests")

	// support old flags
	fs.SetNormalizeFunc(mapFlagName("clientset-path", "output-package", fs.GetNormalizeFunc()))
}

func Validate(genericArgs *args.GeneratorArgs) error {
	customArgs := genericArgs.CustomArgs.(*CustomArgs)

	if len(genericArgs.OutputPackagePath) == 0 {
		return fmt.Errorf("output package cannot be empty")
	}
	if len(customArgs.ClientsetName) == 0 {
		return fmt.Errorf("clientset name cannot be empty")
	}
	if len(customArgs.ClientsetAPIPath) == 0 {
		return fmt.Errorf("clientset API path cannot be empty")
	}

	return nil
}

// GroupVersionPackages returns a map from GroupVersion to the package with the types.go.
func (ca *CustomArgs) GroupVersionPackages() map[types.GroupVersion]string {
	res := map[types.GroupVersion]string{}
	for _, pkg := range ca.Groups {
		for _, v := range pkg.Versions {
			res[types.GroupVersion{Group: pkg.Group, Version: v.Version}] = v.Package
		}
	}
	return res
}

func mapFlagName(from, to string, old func(fs *pflag.FlagSet, name string) pflag.NormalizedName) func(fs *pflag.FlagSet, name string) pflag.NormalizedName {
	return func(fs *pflag.FlagSet, name string) pflag.NormalizedName {
		if name == from {
			name = to
		}
		return old(fs, name)
	}
}
<commit_msg>client-gen: remove base input dirs<commit_after>/*
Copyright 2015 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package args

import (
	"fmt"
	"path"

	"github.com/spf13/pflag"
	"k8s.io/gengo/args"

	"k8s.io/code-generator/cmd/client-gen/types"
	codegenutil "k8s.io/code-generator/pkg/util"
)

var DefaultInputDirs = []string{}

// ClientGenArgs is a wrapper for arguments to client-gen.
type CustomArgs struct {
	// A sorted list of group versions to generate. For each of them the package path is found
	// in GroupVersionToInputPath.
	Groups []types.GroupVersions

	// Overrides for which types should be included in the client.
	IncludedTypesOverrides map[types.GroupVersion][]string

	// ClientsetName is the name of the clientset to be generated. It's
	// populated from command-line arguments.
	ClientsetName string
	// ClientsetAPIPath is the default API HTTP path for generated clients.
	ClientsetAPIPath string
	// ClientsetOnly determines if we should generate the clients for groups and
	// types along with the clientset. It's populated from command-line
	// arguments.
	ClientsetOnly bool
	// FakeClient determines if client-gen generates the fake clients.
	FakeClient bool
}

func NewDefaults() (*args.GeneratorArgs, *CustomArgs) {
	genericArgs := args.Default().WithoutDefaultFlagParsing()
	customArgs := &CustomArgs{
		ClientsetName:    "internalclientset",
		ClientsetAPIPath: "/apis",
		ClientsetOnly:    false,
		FakeClient:       true,
	}
	genericArgs.CustomArgs = customArgs
	genericArgs.InputDirs = DefaultInputDirs

	if pkg := codegenutil.CurrentPackage(); len(pkg) != 0 {
		genericArgs.OutputPackagePath = path.Join(pkg, "pkg/client/clientset")
	}

	return genericArgs, customArgs
}

func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) {
	gvsBuilder := NewGroupVersionsBuilder(&ca.Groups)
	pflag.Var(NewGVPackagesValue(gvsBuilder, nil), "input", "group/versions that client-gen will generate clients for. At most one version per group is allowed. Specified in the format \"group1/version1,group2/version2...\".")
	pflag.Var(NewGVTypesValue(&ca.IncludedTypesOverrides, []string{}), "included-types-overrides", "list of group/version/type for which client should be generated. By default, client is generated for all types which have genclient in types.go. This overrides that. For each groupVersion in this list, only the types mentioned here will be included. The default check of genclient will be used for other group versions.")
	pflag.Var(NewInputBasePathValue(gvsBuilder, inputBase), "input-base", "base path to look for the api group.")
	pflag.StringVarP(&ca.ClientsetName, "clientset-name", "n", ca.ClientsetName, "the name of the generated clientset package.")
	pflag.StringVarP(&ca.ClientsetAPIPath, "clientset-api-path", "", ca.ClientsetAPIPath, "the value of default API HTTP path, starting with / and without trailing /.")
	pflag.BoolVar(&ca.ClientsetOnly, "clientset-only", ca.ClientsetOnly, "when set, client-gen only generates the clientset shell, without generating the individual typed clients")
	pflag.BoolVar(&ca.FakeClient, "fake-clientset", ca.FakeClient, "when set, client-gen will generate the fake clientset that can be used in tests")

	// support old flags
	fs.SetNormalizeFunc(mapFlagName("clientset-path", "output-package", fs.GetNormalizeFunc()))
}

func Validate(genericArgs *args.GeneratorArgs) error {
	customArgs := genericArgs.CustomArgs.(*CustomArgs)

	if len(genericArgs.OutputPackagePath) == 0 {
		return fmt.Errorf("output package cannot be empty")
	}
	if len(customArgs.ClientsetName) == 0 {
		return fmt.Errorf("clientset name cannot be empty")
	}
	if len(customArgs.ClientsetAPIPath) == 0 {
		return fmt.Errorf("clientset API path cannot be empty")
	}

	return nil
}

// GroupVersionPackages returns a map from GroupVersion to the package with the types.go.
func (ca *CustomArgs) GroupVersionPackages() map[types.GroupVersion]string {
	res := map[types.GroupVersion]string{}
	for _, pkg := range ca.Groups {
		for _, v := range pkg.Versions {
			res[types.GroupVersion{Group: pkg.Group, Version: v.Version}] = v.Package
		}
	}
	return res
}

func mapFlagName(from, to string, old func(fs *pflag.FlagSet, name string) pflag.NormalizedName) func(fs *pflag.FlagSet, name string) pflag.NormalizedName {
	return func(fs *pflag.FlagSet, name string) pflag.NormalizedName {
		if name == from {
			name = to
		}
		return old(fs, name)
	}
}
<|endoftext|>


<commit_before>package scraperService

import (
	"fmt"
	"net"
	"net/url"
	"time"

	"github.com/NyaaPantsu/nyaa/config"
	"github.com/NyaaPantsu/nyaa/db"
	"github.com/NyaaPantsu/nyaa/model"
	"github.com/NyaaPantsu/nyaa/util/log"
)

// MTU yes this is the ipv6 mtu
const MTU = 1500

// max number of scrapes per packet
const ScrapesPerPacket = 74

// bittorrent scraper
type Scraper struct {
	done             chan int
	sendQueue        chan *SendEvent
	recvQueue        chan *RecvEvent
	errQueue         chan error
	trackers         map[string]*Bucket
	ticker           *time.Ticker
	cleanup          *time.Ticker
	interval         time.Duration
	PacketsPerSecond uint
}

func New(conf *config.ScraperConfig) (sc *Scraper, err error) {
	sc = &Scraper{
		done:      make(chan int),
		sendQueue: make(chan *SendEvent, 1024),
		recvQueue: make(chan *RecvEvent, 1024),
		errQueue:  make(chan error),
		trackers:  make(map[string]*Bucket),
		ticker:    time.NewTicker(time.Second * 10),
		interval:  time.Second * time.Duration(conf.IntervalSeconds),
		cleanup:   time.NewTicker(time.Minute),
	}

	if sc.PacketsPerSecond == 0 {
		sc.PacketsPerSecond = 10
	}

	for idx := range conf.Trackers {
		err = sc.AddTracker(&conf.Trackers[idx])
		if err != nil {
			break
		}
	}
	return
}

func (sc *Scraper) AddTracker(conf *config.ScrapeConfig) (err error) {
	var u *url.URL
	u, err = url.Parse(conf.URL)
	if err == nil {
		var ips []net.IP
		ips, err = net.LookupIP(u.Hostname())
		if err == nil {
			// TODO: use more than 1 ip ?
			addr := &net.UDPAddr{
				IP: ips[0],
			}
			addr.Port, err = net.LookupPort("udp", u.Port())
			if err == nil {
				sc.trackers[addr.String()] = NewBucket(addr)
			}
		}
	}
	return
}

func (sc *Scraper) Close() (err error) {
	close(sc.sendQueue)
	close(sc.recvQueue)
	close(sc.errQueue)
	sc.ticker.Stop()
	sc.done <- 1
	return
}

func (sc *Scraper) runRecv(pc net.PacketConn) {
	for {
		var buff [MTU]byte
		n, from, err := pc.ReadFrom(buff[:])

		if err == nil {

			log.Debugf("got %d from %s", n, from)
			sc.recvQueue <- &RecvEvent{
				From: from,
				Data: buff[:n],
			}
		} else {
			sc.errQueue <- err
		}
	}
}

func (sc *Scraper) runSend(pc net.PacketConn) {
	for {
		ev, ok := <-sc.sendQueue
		if !ok {
			return
		}
		log.Debugf("write %d to %s", len(ev.Data), ev.To)
		pc.WriteTo(ev.Data, ev.To)
	}
}

func (sc *Scraper) RunWorker(pc net.PacketConn) (err error) {

	go sc.runRecv(pc)
	go sc.runSend(pc)
	for {
		var bucket *Bucket
		ev, ok := <-sc.recvQueue
		if !ok {
			break
		}
		tid, err := ev.TID()
		if err != nil {
			log.Warnf("failed: %s", err)
			break
		}
		action, err := ev.Action()
		if err != nil {
			log.Warnf("failed: %s", err)
			break
		}
		log.Debugf("transaction = %d action = %d", tid, action)
		bucket, ok = sc.trackers[ev.From.String()]
		if !ok || bucket == nil {
			log.Warnf("bucket not found for %s", ev.From)
			break
		}

		bucket.VisitTransaction(tid, func(t *Transaction) {
			if t == nil {
				log.Warnf("no transaction %d", tid)
				return
			}
			if t.GotData(ev.Data) {
				err := t.Sync()
				if err != nil {
					log.Warnf("failed to sync swarm: %s", err)
				}
				t.Done()
				log.Debugf("transaction %d done", tid)
			} else {
				sc.sendQueue <- t.SendEvent(ev.From)
			}
		})
	}
	return
}

func (sc *Scraper) Run() {
	for {
		select {
		case <-sc.ticker.C:
			sc.Scrape(sc.PacketsPerSecond)
			break
		case <-sc.cleanup.C:
			sc.removeStale()
			break
		}
	}
}

func (sc *Scraper) removeStale() {

	for k := range sc.trackers {
		sc.trackers[k].ForEachTransaction(func(tid uint32, t *Transaction) {
			if t == nil || t.IsTimedOut() {
				sc.trackers[k].Forget(tid)
			}
		})
	}
}

func (sc *Scraper) Scrape(packets uint) {
	now := time.Now().Add(0 - sc.interval)
	// only scrape torretns uploaded within 90 days
	oldest := now.Add(0 - (time.Hour * 24 * 90))

	query := fmt.Sprintf(
		"SELECT * FROM ("+

			// previously scraped torrents that will be scraped again:
			"SELECT %[1]s.torrent_id, torrent_hash FROM %[1]s, %[2]s WHERE "+
			"date > ? AND "+
			"%[1]s.torrent_id = %[2]s.torrent_id AND "+
			"$[2]s.last_scrape < ?"+

			// torrents that weren't scraped before:
			" UNION "+
			"SELECT torrent_id, torrent_hash FROM %[1]s WHERE "+
			"date > ? AND "+
			"torrent_id NOT IN (SELECT torrent_id FROM %[2]s)"+

			") AS x ORDER BY torrent_id DESC LIMIT ?",
		config.Conf.Models.TorrentsTableName, config.Conf.Models.ScrapeTableName)
	rows, err := db.ORM.Raw(query, oldest, now, oldest, packets*ScrapesPerPacket).Rows()

	if err == nil {
		counter := 0
		var scrape [ScrapesPerPacket]model.Torrent
		for rows.Next() {
			idx := counter % ScrapesPerPacket
			rows.Scan(&scrape[idx].ID, &scrape[idx].Hash)
			counter++
			if counter%ScrapesPerPacket == 0 {
				for _, b := range sc.trackers {
					t := b.NewTransaction(scrape[:])
					sc.sendQueue <- t.SendEvent(b.Addr)
				}
			}
		}
		idx := counter % ScrapesPerPacket
		if idx > 0 {
			for _, b := range sc.trackers {
				t := b.NewTransaction(scrape[:idx])
				sc.sendQueue <- t.SendEvent(b.Addr)
			}
		}
		log.Infof("scrape %d", counter)
		rows.Close()
	} else {
		log.Warnf("failed to select torrents for scrape: %s", err)
	}
}

func (sc *Scraper) Wait() {
	<-sc.done
}
<commit_msg>Change $ to %<commit_after>package scraperService

import (
	"fmt"
	"net"
	"net/url"
	"time"

	"github.com/NyaaPantsu/nyaa/config"
	"github.com/NyaaPantsu/nyaa/db"
	"github.com/NyaaPantsu/nyaa/model"
	"github.com/NyaaPantsu/nyaa/util/log"
)

// MTU yes this is the ipv6 mtu
const MTU = 1500

// max number of scrapes per packet
const ScrapesPerPacket = 74

// bittorrent scraper
type Scraper struct {
	done             chan int
	sendQueue        chan *SendEvent
	recvQueue        chan *RecvEvent
	errQueue         chan error
	trackers         map[string]*Bucket
	ticker           *time.Ticker
	cleanup          *time.Ticker
	interval         time.Duration
	PacketsPerSecond uint
}

func New(conf *config.ScraperConfig) (sc *Scraper, err error) {
	sc = &Scraper{
		done:      make(chan int),
		sendQueue: make(chan *SendEvent, 1024),
		recvQueue: make(chan *RecvEvent, 1024),
		errQueue:  make(chan error),
		trackers:  make(map[string]*Bucket),
		ticker:    time.NewTicker(time.Second * 10),
		interval:  time.Second * time.Duration(conf.IntervalSeconds),
		cleanup:   time.NewTicker(time.Minute),
	}

	if sc.PacketsPerSecond == 0 {
		sc.PacketsPerSecond = 10
	}

	for idx := range conf.Trackers {
		err = sc.AddTracker(&conf.Trackers[idx])
		if err != nil {
			break
		}
	}
	return
}

func (sc *Scraper) AddTracker(conf *config.ScrapeConfig) (err error) {
	var u *url.URL
	u, err = url.Parse(conf.URL)
	if err == nil {
		var ips []net.IP
		ips, err = net.LookupIP(u.Hostname())
		if err == nil {
			// TODO: use more than 1 ip ?
			addr := &net.UDPAddr{
				IP: ips[0],
			}
			addr.Port, err = net.LookupPort("udp", u.Port())
			if err == nil {
				sc.trackers[addr.String()] = NewBucket(addr)
			}
		}
	}
	return
}

func (sc *Scraper) Close() (err error) {
	close(sc.sendQueue)
	close(sc.recvQueue)
	close(sc.errQueue)
	sc.ticker.Stop()
	sc.done <- 1
	return
}

func (sc *Scraper) runRecv(pc net.PacketConn) {
	for {
		var buff [MTU]byte
		n, from, err := pc.ReadFrom(buff[:])

		if err == nil {

			log.Debugf("got %d from %s", n, from)
			sc.recvQueue <- &RecvEvent{
				From: from,
				Data: buff[:n],
			}
		} else {
			sc.errQueue <- err
		}
	}
}

func (sc *Scraper) runSend(pc net.PacketConn) {
	for {
		ev, ok := <-sc.sendQueue
		if !ok {
			return
		}
		log.Debugf("write %d to %s", len(ev.Data), ev.To)
		pc.WriteTo(ev.Data, ev.To)
	}
}

func (sc *Scraper) RunWorker(pc net.PacketConn) (err error) {

	go sc.runRecv(pc)
	go sc.runSend(pc)
	for {
		var bucket *Bucket
		ev, ok := <-sc.recvQueue
		if !ok {
			break
		}
		tid, err := ev.TID()
		if err != nil {
			log.Warnf("failed: %s", err)
			break
		}
		action, err := ev.Action()
		if err != nil {
			log.Warnf("failed: %s", err)
			break
		}
		log.Debugf("transaction = %d action = %d", tid, action)
		bucket, ok = sc.trackers[ev.From.String()]
		if !ok || bucket == nil {
			log.Warnf("bucket not found for %s", ev.From)
			break
		}

		bucket.VisitTransaction(tid, func(t *Transaction) {
			if t == nil {
				log.Warnf("no transaction %d", tid)
				return
			}
			if t.GotData(ev.Data) {
				err := t.Sync()
				if err != nil {
					log.Warnf("failed to sync swarm: %s", err)
				}
				t.Done()
				log.Debugf("transaction %d done", tid)
			} else {
				sc.sendQueue <- t.SendEvent(ev.From)
			}
		})
	}
	return
}

func (sc *Scraper) Run() {
	for {
		select {
		case <-sc.ticker.C:
			sc.Scrape(sc.PacketsPerSecond)
			break
		case <-sc.cleanup.C:
			sc.removeStale()
			break
		}
	}
}

func (sc *Scraper) removeStale() {

	for k := range sc.trackers {
		sc.trackers[k].ForEachTransaction(func(tid uint32, t *Transaction) {
			if t == nil || t.IsTimedOut() {
				sc.trackers[k].Forget(tid)
			}
		})
	}
}

func (sc *Scraper) Scrape(packets uint) {
	now := time.Now().Add(0 - sc.interval)
	// only scrape torretns uploaded within 90 days
	oldest := now.Add(0 - (time.Hour * 24 * 90))

	query := fmt.Sprintf(
		"SELECT * FROM ("+

			// previously scraped torrents that will be scraped again:
			"SELECT %[1]s.torrent_id, torrent_hash FROM %[1]s, %[2]s WHERE "+
			"date > ? AND "+
			"%[1]s.torrent_id = %[2]s.torrent_id AND "+
			"%[2]s.last_scrape < ?"+

			// torrents that weren't scraped before:
			" UNION "+
			"SELECT torrent_id, torrent_hash FROM %[1]s WHERE "+
			"date > ? AND "+
			"torrent_id NOT IN (SELECT torrent_id FROM %[2]s)"+

			") AS x ORDER BY torrent_id DESC LIMIT ?",
		config.Conf.Models.TorrentsTableName, config.Conf.Models.ScrapeTableName)
	rows, err := db.ORM.Raw(query, oldest, now, oldest, packets*ScrapesPerPacket).Rows()

	if err == nil {
		counter := 0
		var scrape [ScrapesPerPacket]model.Torrent
		for rows.Next() {
			idx := counter % ScrapesPerPacket
			rows.Scan(&scrape[idx].ID, &scrape[idx].Hash)
			counter++
			if counter%ScrapesPerPacket == 0 {
				for _, b := range sc.trackers {
					t := b.NewTransaction(scrape[:])
					sc.sendQueue <- t.SendEvent(b.Addr)
				}
			}
		}
		idx := counter % ScrapesPerPacket
		if idx > 0 {
			for _, b := range sc.trackers {
				t := b.NewTransaction(scrape[:idx])
				sc.sendQueue <- t.SendEvent(b.Addr)
			}
		}
		log.Infof("scrape %d", counter)
		rows.Close()
	} else {
		log.Warnf("failed to select torrents for scrape: %s", err)
	}
}

func (sc *Scraper) Wait() {
	<-sc.done
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net/http"
	"runtime"
	"sync/atomic"
	"time"

	"github.com/lomik/graphite-clickhouse/config"
	"github.com/lomik/graphite-clickhouse/find"
	"github.com/lomik/graphite-clickhouse/render"
	"github.com/lomik/graphite-clickhouse/tagger"
	"github.com/lomik/zapwriter"
	"go.uber.org/zap"

	_ "net/http/pprof"
)

// Version of graphite-clickhouse
const Version = "0.5.0"

type LogResponseWriter struct {
	http.ResponseWriter
	status int
}

func (w *LogResponseWriter) WriteHeader(status int) {
	w.status = status
	w.ResponseWriter.WriteHeader(status)
}

func (w *LogResponseWriter) Status() int {
	if w.status == 0 {
		return http.StatusOK
	}
	return w.status
}

func WrapResponseWriter(w http.ResponseWriter) *LogResponseWriter {
	if wrapped, ok := w.(*LogResponseWriter); ok {
		return wrapped
	}
	return &LogResponseWriter{ResponseWriter: w}
}

func Handler(logger *zap.Logger, handler http.Handler) http.Handler {
	var requestCounter uint32
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		writer := WrapResponseWriter(w)

		requestID := r.Header.Get("X-Request-Id")
		if requestID == "" {
			requestID = fmt.Sprintf("%d", atomic.AddUint32(&requestCounter, 1))
		}

		logger := logger.With(zap.String("request_id", requestID))

		r = r.WithContext(context.WithValue(r.Context(), "logger", logger))

		start := time.Now()
		handler.ServeHTTP(w, r)
		d := time.Since(start)
		logger.Info("access",
			zap.Duration("time", d),
			zap.String("method", r.Method),
			zap.String("url", r.URL.String()),
			zap.String("peer", r.RemoteAddr),
			zap.Int("status", writer.Status()),
		)
	})
}

func main() {
	var err error

	/* CONFIG start */

	configFile := flag.String("config", "/etc/graphite-clickhouse/graphite-clickhouse.conf", "Filename of config")
	printDefaultConfig := flag.Bool("config-print-default", false, "Print default config")
	checkConfig := flag.Bool("check-config", false, "Check config and exit")
	tags := flag.Bool("tags", false, "Build tags table")

	printVersion := flag.Bool("version", false, "Print version")

	flag.Parse()

	if *printVersion {
		fmt.Print(Version)
		return
	}

	if *printDefaultConfig {
		if err = config.PrintDefaultConfig(); err != nil {
			log.Fatal(err)
		}
		return
	}

	cfg, err := config.ReadConfig(*configFile)
	if err != nil {
		log.Fatal(err)
	}

	// config parsed successfully. Exit in check-only mode
	if *checkConfig {
		return
	}

	if err = zapwriter.ApplyConfig(cfg.Logging); err != nil {
		log.Fatal(err)
	}

	runtime.GOMAXPROCS(cfg.Common.MaxCPU)

	/* CONFIG end */

	/* CONSOLE COMMANDS start */
	if *tags {
		if err := tagger.Make(cfg); err != nil {
			log.Fatal(err)
		}
		return
	}

	/* CONSOLE COMMANDS end */

	http.Handle("/metrics/find/", Handler(zapwriter.Default(), find.NewHandler(cfg)))
	http.Handle("/render/", Handler(zapwriter.Default(), render.NewHandler(cfg)))

	http.Handle("/", Handler(zapwriter.Default(), http.HandlerFunc(http.NotFound)))

	log.Fatal(http.ListenAndServe(cfg.Common.Listen, nil))
}
<commit_msg>version 0.5.1<commit_after>package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"net/http"
	"runtime"
	"sync/atomic"
	"time"

	"github.com/lomik/graphite-clickhouse/config"
	"github.com/lomik/graphite-clickhouse/find"
	"github.com/lomik/graphite-clickhouse/render"
	"github.com/lomik/graphite-clickhouse/tagger"
	"github.com/lomik/zapwriter"
	"go.uber.org/zap"

	_ "net/http/pprof"
)

// Version of graphite-clickhouse
const Version = "0.5.1"

type LogResponseWriter struct {
	http.ResponseWriter
	status int
}

func (w *LogResponseWriter) WriteHeader(status int) {
	w.status = status
	w.ResponseWriter.WriteHeader(status)
}

func (w *LogResponseWriter) Status() int {
	if w.status == 0 {
		return http.StatusOK
	}
	return w.status
}

func WrapResponseWriter(w http.ResponseWriter) *LogResponseWriter {
	if wrapped, ok := w.(*LogResponseWriter); ok {
		return wrapped
	}
	return &LogResponseWriter{ResponseWriter: w}
}

func Handler(logger *zap.Logger, handler http.Handler) http.Handler {
	var requestCounter uint32
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		writer := WrapResponseWriter(w)

		requestID := r.Header.Get("X-Request-Id")
		if requestID == "" {
			requestID = fmt.Sprintf("%d", atomic.AddUint32(&requestCounter, 1))
		}

		logger := logger.With(zap.String("request_id", requestID))

		r = r.WithContext(context.WithValue(r.Context(), "logger", logger))

		start := time.Now()
		handler.ServeHTTP(w, r)
		d := time.Since(start)
		logger.Info("access",
			zap.Duration("time", d),
			zap.String("method", r.Method),
			zap.String("url", r.URL.String()),
			zap.String("peer", r.RemoteAddr),
			zap.Int("status", writer.Status()),
		)
	})
}

func main() {
	var err error

	/* CONFIG start */

	configFile := flag.String("config", "/etc/graphite-clickhouse/graphite-clickhouse.conf", "Filename of config")
	printDefaultConfig := flag.Bool("config-print-default", false, "Print default config")
	checkConfig := flag.Bool("check-config", false, "Check config and exit")
	tags := flag.Bool("tags", false, "Build tags table")

	printVersion := flag.Bool("version", false, "Print version")

	flag.Parse()

	if *printVersion {
		fmt.Print(Version)
		return
	}

	if *printDefaultConfig {
		if err = config.PrintDefaultConfig(); err != nil {
			log.Fatal(err)
		}
		return
	}

	cfg, err := config.ReadConfig(*configFile)
	if err != nil {
		log.Fatal(err)
	}

	// config parsed successfully. Exit in check-only mode
	if *checkConfig {
		return
	}

	if err = zapwriter.ApplyConfig(cfg.Logging); err != nil {
		log.Fatal(err)
	}

	runtime.GOMAXPROCS(cfg.Common.MaxCPU)

	/* CONFIG end */

	/* CONSOLE COMMANDS start */
	if *tags {
		if err := tagger.Make(cfg); err != nil {
			log.Fatal(err)
		}
		return
	}

	/* CONSOLE COMMANDS end */

	http.Handle("/metrics/find/", Handler(zapwriter.Default(), find.NewHandler(cfg)))
	http.Handle("/render/", Handler(zapwriter.Default(), render.NewHandler(cfg)))

	http.Handle("/", Handler(zapwriter.Default(), http.HandlerFunc(http.NotFound)))

	log.Fatal(http.ListenAndServe(cfg.Common.Listen, nil))
}
<|endoftext|>