<commit_before>/*
Copyright 2018 Google LLC

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 deploy

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"text/template"

	"github.com/GoogleCloudPlatform/skaffold/pkg/skaffold/build"
	"github.com/GoogleCloudPlatform/skaffold/pkg/skaffold/docker"
	"github.com/GoogleCloudPlatform/skaffold/pkg/skaffold/schema/v1alpha2"
	"github.com/GoogleCloudPlatform/skaffold/pkg/skaffold/util"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	yaml "gopkg.in/yaml.v2"
)

// Slightly modified from kubectl run --dry-run
var deploymentTemplate = template.Must(template.New("deployment").Parse(`apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: skaffold
  name: skaffold
spec:
  replicas: 1
  selector:
    matchLabels:
      run: skaffold
  strategy: {}
  template:
    metadata:
      labels:
        run: skaffold
    spec:
      containers:
      - image: IMAGE
        name: app
{{if .Ports}}
        ports:
{{range .Ports}}
        - containerPort: {{.}}
{{end}}
{{end}}
`))

type KubectlDeployer struct {
	*v1alpha2.DeployConfig
	kubeContext string
}

// NewKubectlDeployer returns a new KubectlDeployer for a DeployConfig filled
// with the needed configuration for `kubectl apply`
func NewKubectlDeployer(cfg *v1alpha2.DeployConfig, kubeContext string) *KubectlDeployer {
	return &KubectlDeployer{
		DeployConfig: cfg,
		kubeContext:  kubeContext,
	}
}

// Deploy templates the provided manifests with a simple `find and replace` and
// runs `kubectl apply` on those manifests
func (k *KubectlDeployer) Deploy(ctx context.Context, out io.Writer, b *build.BuildResult) (*Result, error) {
	if len(k.DeployConfig.KubectlDeploy.Manifests) == 0 {
		if len(b.Builds) != 1 {
			return nil, errors.New("must specify manifest if using more than one image")
		}
		yaml, err := generateManifest(b.Builds[0])
		if err != nil {
			return nil, errors.Wrap(err, "generating manifest")
		}
		params := map[string]build.Build{"IMAGE": b.Builds[0]}

		if err := k.deployManifestFile(strings.NewReader(yaml), params); err != nil {
			return nil, errors.Wrap(err, "deploying manifest")
		}
		return &Result{}, nil
	}
	manifests, err := util.ExpandPathsGlob(k.DeployConfig.KubectlDeploy.Manifests)
	if err != nil {
		return nil, errors.Wrap(err, "expanding kubectl manifest paths")
	}
	for _, m := range manifests {
		logrus.Debugf("Deploying path: %s", m)
		if err := k.deployManifest(out, b.Builds, m); err != nil {
			return nil, errors.Wrap(err, "deploying manifests")
		}
	}

	return &Result{}, nil
}

func generateManifest(b build.Build) (string, error) {
	logrus.Info("No manifests specified. Generating a deployment.")
	dockerfilePath := filepath.Join(b.Artifact.Workspace, b.Artifact.DockerArtifact.DockerfilePath)
	r, err := os.Open(dockerfilePath)
	if err != nil {
		return "", errors.Wrap(err, "reading dockerfile")
	}
	ports, err := docker.PortsFromDockerfile(r)
	if err != nil {
		logrus.Warnf("Unable to determine port from Dockerfile: %s.", err)
	}
	var out bytes.Buffer
	if err := deploymentTemplate.Execute(&out, struct{ Ports []string }{Ports: ports}); err != nil {
		return "", err
	}
	return out.String(), nil
}

func imageToBuild(b []build.Build) map[string]build.Build {
	m := map[string]build.Build{}
	for _, build := range b {
		m[build.ImageName] = build
	}
	return m
}

func (k *KubectlDeployer) deployManifest(out io.Writer, b []build.Build, manifest string) error {
	imageToBuilds := imageToBuild(b)
	if !util.IsSupportedKubernetesFormat(manifest) {
		if !util.StrSliceContains(k.KubectlDeploy.Manifests, manifest) {
			logrus.Infof("Refusing to deploy non {json, yaml} file %s", manifest)
			logrus.Info("If you still wish to deploy this file, please specify it directly, outside a glob pattern.")
			return nil
		}
	}
	fmt.Fprintf(out, "Deploying %s...\n", manifest)
	f, err := util.Fs.Open(manifest)
	if err != nil {
		return errors.Wrap(err, "opening manifest")
	}
	if err := k.deployManifestFile(f, imageToBuilds); err != nil {
		return errors.Wrapf(err, "deploying manifest %s", manifest)
	}
	return nil
}

func (k *KubectlDeployer) deployManifestFile(r io.Reader, params map[string]build.Build) error {
	var manifestContents bytes.Buffer
	if _, err := manifestContents.ReadFrom(r); err != nil {
		return errors.Wrap(err, "reading manifest")
	}

	manifest, err := replaceParameters(manifestContents.Bytes(), params)
	if err != nil {
		return errors.Wrap(err, "replacing image in manifest")
	}

	cmd := exec.Command("kubectl", "--context", k.kubeContext, "apply", "-f", "-")
	stdin := strings.NewReader(manifest)
	out, outerr, err := util.RunCommand(cmd, stdin)
	if err != nil {
		return errors.Wrapf(err, "running kubectl apply: stdout: %s stderr: %s err: %s", out, outerr, err)
	}
	return nil
}

func replaceParameters(contents []byte, params map[string]build.Build) (string, error) {
	var manifests []string

	parts := bytes.Split(contents, []byte("\n---"))
	for _, part := range parts {
		m := make(map[interface{}]interface{})
		if err := yaml.Unmarshal(part, &m); err != nil {
			return "", errors.Wrap(err, "reading kubernetes YAML")
		}

		replaced := recursiveReplace(m, params)
		replacedMap := replaced.(map[string]interface{})

		out, err := yaml.Marshal(replacedMap)
		if err != nil {
			return "", errors.Wrap(err, "marshalling yaml")
		}

		manifests = append(manifests, string(out))
	}

	manifest := strings.Join(manifests, "---\n")
	logrus.Debugln("Applying manifest:", manifest)

	return manifest, nil
}

func recursiveReplace(i interface{}, params map[string]build.Build) interface{} {
	switch t := i.(type) {
	case map[interface{}]interface{}:
		m := map[string]interface{}{}
		for k, v := range t {
			if k.(string) == "image" {
				for img, b := range params {
					if v.(string) == img {
						v = b.Tag
					}
				}
			}
			m[k.(string)] = recursiveReplace(v, params)
		}
		return m
	case []interface{}:
		for i, v := range t {
			t[i] = recursiveReplace(v, params)
		}
	}
	return i
}
<commit_msg>Warn when an image is built but not used<commit_after>/*
Copyright 2018 Google LLC

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 deploy

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"text/template"

	"github.com/GoogleCloudPlatform/skaffold/pkg/skaffold/build"
	"github.com/GoogleCloudPlatform/skaffold/pkg/skaffold/docker"
	"github.com/GoogleCloudPlatform/skaffold/pkg/skaffold/schema/v1alpha2"
	"github.com/GoogleCloudPlatform/skaffold/pkg/skaffold/util"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	yaml "gopkg.in/yaml.v2"
)

// Slightly modified from kubectl run --dry-run
var deploymentTemplate = template.Must(template.New("deployment").Parse(`apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    run: skaffold
  name: skaffold
spec:
  replicas: 1
  selector:
    matchLabels:
      run: skaffold
  strategy: {}
  template:
    metadata:
      labels:
        run: skaffold
    spec:
      containers:
      - image: IMAGE
        name: app
{{if .Ports}}
        ports:
{{range .Ports}}
        - containerPort: {{.}}
{{end}}
{{end}}
`))

type KubectlDeployer struct {
	*v1alpha2.DeployConfig
	kubeContext string
}

// NewKubectlDeployer returns a new KubectlDeployer for a DeployConfig filled
// with the needed configuration for `kubectl apply`
func NewKubectlDeployer(cfg *v1alpha2.DeployConfig, kubeContext string) *KubectlDeployer {
	return &KubectlDeployer{
		DeployConfig: cfg,
		kubeContext:  kubeContext,
	}
}

// Deploy templates the provided manifests with a simple `find and replace` and
// runs `kubectl apply` on those manifests
func (k *KubectlDeployer) Deploy(ctx context.Context, out io.Writer, b *build.BuildResult) (*Result, error) {
	if len(k.DeployConfig.KubectlDeploy.Manifests) == 0 {
		if len(b.Builds) != 1 {
			return nil, errors.New("must specify manifest if using more than one image")
		}
		yaml, err := generateManifest(b.Builds[0])
		if err != nil {
			return nil, errors.Wrap(err, "generating manifest")
		}
		params := map[string]build.Build{"IMAGE": b.Builds[0]}

		if err := k.deployManifestFile(strings.NewReader(yaml), params); err != nil {
			return nil, errors.Wrap(err, "deploying manifest")
		}
		return &Result{}, nil
	}
	manifests, err := util.ExpandPathsGlob(k.DeployConfig.KubectlDeploy.Manifests)
	if err != nil {
		return nil, errors.Wrap(err, "expanding kubectl manifest paths")
	}
	for _, m := range manifests {
		logrus.Debugf("Deploying path: %s", m)
		if err := k.deployManifest(out, b.Builds, m); err != nil {
			return nil, errors.Wrap(err, "deploying manifests")
		}
	}

	return &Result{}, nil
}

func generateManifest(b build.Build) (string, error) {
	logrus.Info("No manifests specified. Generating a deployment.")
	dockerfilePath := filepath.Join(b.Artifact.Workspace, b.Artifact.DockerArtifact.DockerfilePath)
	r, err := os.Open(dockerfilePath)
	if err != nil {
		return "", errors.Wrap(err, "reading dockerfile")
	}
	ports, err := docker.PortsFromDockerfile(r)
	if err != nil {
		logrus.Warnf("Unable to determine port from Dockerfile: %s.", err)
	}
	var out bytes.Buffer
	if err := deploymentTemplate.Execute(&out, struct{ Ports []string }{Ports: ports}); err != nil {
		return "", err
	}
	return out.String(), nil
}

func imageToBuild(b []build.Build) map[string]build.Build {
	m := map[string]build.Build{}
	for _, build := range b {
		m[build.ImageName] = build
	}
	return m
}

func (k *KubectlDeployer) deployManifest(out io.Writer, b []build.Build, manifest string) error {
	imageToBuilds := imageToBuild(b)
	if !util.IsSupportedKubernetesFormat(manifest) {
		if !util.StrSliceContains(k.KubectlDeploy.Manifests, manifest) {
			logrus.Infof("Refusing to deploy non {json, yaml} file %s", manifest)
			logrus.Info("If you still wish to deploy this file, please specify it directly, outside a glob pattern.")
			return nil
		}
	}
	fmt.Fprintf(out, "Deploying %s...\n", manifest)
	f, err := util.Fs.Open(manifest)
	if err != nil {
		return errors.Wrap(err, "opening manifest")
	}
	if err := k.deployManifestFile(f, imageToBuilds); err != nil {
		return errors.Wrapf(err, "deploying manifest %s", manifest)
	}
	return nil
}

func (k *KubectlDeployer) deployManifestFile(r io.Reader, params map[string]build.Build) error {
	var manifestContents bytes.Buffer
	if _, err := manifestContents.ReadFrom(r); err != nil {
		return errors.Wrap(err, "reading manifest")
	}

	manifest, err := replaceParameters(manifestContents.Bytes(), params)
	if err != nil {
		return errors.Wrap(err, "replacing image in manifest")
	}

	cmd := exec.Command("kubectl", "--context", k.kubeContext, "apply", "-f", "-")
	stdin := strings.NewReader(manifest)
	out, outerr, err := util.RunCommand(cmd, stdin)
	if err != nil {
		return errors.Wrapf(err, "running kubectl apply: stdout: %s stderr: %s err: %s", out, outerr, err)
	}
	return nil
}

type replacement struct {
	tag   string
	found bool
}

func replaceParameters(contents []byte, params map[string]build.Build) (string, error) {
	var manifests []string

	replacements := map[string]*replacement{}
	for img, b := range params {
		replacements[img] = &replacement{
			tag: b.Tag,
		}
	}

	parts := bytes.Split(contents, []byte("\n---"))
	for _, part := range parts {
		m := make(map[interface{}]interface{})
		if err := yaml.Unmarshal(part, &m); err != nil {
			return "", errors.Wrap(err, "reading kubernetes YAML")
		}

		replaced := recursiveReplace(m, replacements)
		replacedMap := replaced.(map[string]interface{})

		out, err := yaml.Marshal(replacedMap)
		if err != nil {
			return "", errors.Wrap(err, "marshalling yaml")
		}

		manifests = append(manifests, string(out))
	}

	for name, replacement := range replacements {
		if !replacement.found {
			logrus.Warnf("image [%s] is not used by the deployment", name)
		}
	}

	manifest := strings.Join(manifests, "---\n")
	logrus.Debugln("Applying manifest:", manifest)

	return manifest, nil
}

func recursiveReplace(i interface{}, replacements map[string]*replacement) interface{} {
	switch t := i.(type) {
	case map[interface{}]interface{}:
		m := map[string]interface{}{}
		for k, v := range t {
			if k.(string) == "image" {
				name := v.(string)
				if img, present := replacements[name]; present {
					v = img.tag
					img.found = true
				}
			}
			m[k.(string)] = recursiveReplace(v, replacements)
		}
		return m
	case []interface{}:
		for i, v := range t {
			t[i] = recursiveReplace(v, replacements)
		}
	}
	return i
}
<|endoftext|>


<commit_before>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017, 2018 Red Hat, Inc.
 *
 */

package console

import (
	"fmt"
	"io"
	"os"
	"os/signal"

	"golang.org/x/crypto/ssh/terminal"

	"github.com/spf13/cobra"

	"k8s.io/client-go/tools/clientcmd"

	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/pkg/virtctl/templates"
)

func NewCommand(clientConfig clientcmd.ClientConfig) *cobra.Command {
	cmd := &cobra.Command{
		Use:     "console (vmi)",
		Short:   "Connect to a console of a virtual machine.",
		Example: usage(),
		Args:    cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			c := Console{clientConfig: clientConfig}
			return c.Run(cmd, args)
		},
	}
	cmd.SetUsageTemplate(templates.UsageTemplate())
	return cmd
}

type Console struct {
	clientConfig clientcmd.ClientConfig
}

func usage() string {
	usage := "# Connect to the console on VirtualMachineInstance 'myvmi':\n"
	usage += "virtctl console myvmi"
	return usage
}

func (c *Console) Run(cmd *cobra.Command, args []string) error {
	namespace, _, err := c.clientConfig.Namespace()
	if err != nil {
		return err
	}

	vmi := args[0]

	virtCli, err := kubecli.GetKubevirtClientFromClientConfig(c.clientConfig)
	if err != nil {
		return err
	}

	state, err := terminal.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		return fmt.Errorf("Make raw terminal failed: %s", err)
	}
	fmt.Fprint(os.Stderr, "Escape sequence is ^]\n")

	in := os.Stdin
	out := os.Stdout

	stdinReader, stdinWriter := io.Pipe()
	stdoutReader, stdoutWriter := io.Pipe()

	// in -> stdinWriter | stdinReader -> console
	// out <- stdoutReader | stdoutWriter <- console

	resChan := make(chan error)
	stopChan := make(chan struct{}, 1)
	writeStop := make(chan error)
	readStop := make(chan error)

	go func() {
		con, err := virtCli.VirtualMachineInstance(namespace).SerialConsole(vmi)
		if err != nil {
			resChan <- err
			return
		}

		resChan <- con.Stream(kubecli.StreamOptions{
			In:  stdinReader,
			Out: stdoutWriter,
		})
	}()

	go func() {
		interrupt := make(chan os.Signal, 1)
		signal.Notify(interrupt, os.Interrupt)
		<-interrupt
		close(stopChan)
	}()

	go func() {
		_, err := io.Copy(out, stdoutReader)
		readStop <- err
	}()

	go func() {
		defer close(writeStop)
		buf := make([]byte, 1024, 1024)
		for {
			// reading from stdin
			n, err := in.Read(buf)
			if err != nil && err != io.EOF {
				writeStop <- err
				return
			}
			if n == 0 && err == io.EOF {
				return
			}

			// the escape sequence
			if buf[0] == 29 {
				return
			}
			// Writing out to the console connection
			_, err = stdinWriter.Write(buf[0:n])
			if err == io.EOF {
				return
			}
		}
	}()

	select {
	case <-stopChan:
	case err = <-readStop:
	case err = <-writeStop:
	case err = <-resChan:
	}

	terminal.Restore(int(os.Stdin.Fd()), state)

	if err != nil {
		return err
	}
	return nil
}
<commit_msg>virtctl console wait until the virtual machine is in ready state.<commit_after>/*
 * This file is part of the KubeVirt project
 *
 * 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.
 *
 * Copyright 2017, 2018 Red Hat, Inc.
 *
 */

package console

import (
	"fmt"
	"io"
	"os"
	"os/signal"
	"strings"
	"time"

	"golang.org/x/crypto/ssh/terminal"

	"github.com/spf13/cobra"

	"k8s.io/client-go/tools/clientcmd"

	"kubevirt.io/kubevirt/pkg/kubecli"
	"kubevirt.io/kubevirt/pkg/virtctl/templates"
)

var timeout int

func NewCommand(clientConfig clientcmd.ClientConfig) *cobra.Command {
	cmd := &cobra.Command{
		Use:     "console (vmi)",
		Short:   "Connect to a console of a virtual machine.",
		Example: usage(),
		Args:    cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			c := Console{clientConfig: clientConfig}
			return c.Run(cmd, args)
		},
	}

	cmd.Flags().IntVar(&timeout, "timeout", 5, "The number of minutes to wait for the virtual machine instance to be ready.")
	cmd.SetUsageTemplate(templates.UsageTemplate())
	return cmd
}

type Console struct {
	clientConfig clientcmd.ClientConfig
}

func usage() string {
	usage := `# Connect to the console on VirtualMachineInstance 'myvmi':
  virtctl console myvmi
# Configure one minute timeout (default 5 minutes)
  virtctl console --timeout=1 myvmi`

	return usage
}

func (c *Console) Run(cmd *cobra.Command, args []string) error {
	namespace, _, err := c.clientConfig.Namespace()
	if err != nil {
		return err
	}

	vmi := args[0]

	virtCli, err := kubecli.GetKubevirtClientFromClientConfig(c.clientConfig)
	if err != nil {
		return err
	}

	stdinReader, stdinWriter := io.Pipe()
	stdoutReader, stdoutWriter := io.Pipe()

	// in -> stdinWriter | stdinReader -> console
	// out <- stdoutReader | stdoutWriter <- console

	resChan := make(chan error)
	stopChan := make(chan struct{}, 1)
	writeStop := make(chan error)
	readStop := make(chan error)

	// Wait until the virtual machine is in running phase, user interrupt or timeout
	runningChan := make(chan error)
	timeoutChan := time.Tick(time.Duration(timeout) * time.Minute)
	waitInterrupt := make(chan os.Signal, 1)
	signal.Notify(waitInterrupt, os.Interrupt)

	go func() {
		con, err := virtCli.VirtualMachineInstance(namespace).SerialConsole(vmi)
		if strings.Contains(fmt.Sprint(err), "not found") {
			runningChan <- err
		}

		for err != nil {
			// Sleep to prevent denial of service on the api server
			time.Sleep(500 * time.Millisecond)
			con, err = virtCli.VirtualMachineInstance(namespace).SerialConsole(vmi)
		}

		runningChan <- nil
		resChan <- con.Stream(kubecli.StreamOptions{
			In:  stdinReader,
			Out: stdoutWriter,
		})
	}()

	select {
	case <-timeoutChan:
		return fmt.Errorf("Timeout trying to connect to the virtual machine instance")
	case <-waitInterrupt:
		// Make a new line in the terminal
		fmt.Println()
		return nil
	case err = <-runningChan:
		if err != nil {
			return err
		}
	}

	state, err := terminal.MakeRaw(int(os.Stdin.Fd()))
	if err != nil {
		return fmt.Errorf("Make raw terminal failed: %s", err)
	}
	fmt.Fprint(os.Stderr, "Successfully connected to ", vmi, " console. The escape sequence is ^]\n")

	in := os.Stdin
	out := os.Stdout

	go func() {
		interrupt := make(chan os.Signal, 1)
		signal.Notify(interrupt, os.Interrupt)
		<-interrupt
		close(stopChan)
	}()

	go func() {
		_, err := io.Copy(out, stdoutReader)
		readStop <- err
	}()

	go func() {
		defer close(writeStop)
		buf := make([]byte, 1024, 1024)
		for {
			// reading from stdin
			n, err := in.Read(buf)
			if err != nil && err != io.EOF {
				writeStop <- err
				return
			}
			if n == 0 && err == io.EOF {
				return
			}

			// the escape sequence
			if buf[0] == 29 {
				return
			}
			// Writing out to the console connection
			_, err = stdinWriter.Write(buf[0:n])
			if err == io.EOF {
				return
			}
		}
	}()

	select {
	case <-stopChan:
	case err = <-readStop:
	case err = <-writeStop:
	case err = <-resChan:
	}

	terminal.Restore(int(os.Stdin.Fd()), state)

	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// The ghstatus package allows you to check the system status of GitHub from
// your own applications. The status information is retrieved from GitHub's
// system status API (https://status.github.com/api).

package ghstatus

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

// The root URL of GitHub's system status API.
const StatusApiUrl = "https://status.github.com/api"

// Possible status values.
const (
	StatusGood  = "good"
	StatusMinor = "minor"
	StatusMajor = "major"
)

// Current system status as returned by the /status endpoint.
type Status struct {
	Status      string `json:"status"`
	LastUpdated string `json:"last_updated"`
}

// A status message as returned by the /messages and /last-message endpoints.
type Message struct {
	Status    string `json:"status"`
	Body      string `json:"body"`
	CreatedOn string `json:"created_on"`
}

func sendRequest(endpoint string, v interface{}) error {
	resp, err := http.Get(StatusApiUrl + endpoint + ".json")
	if err != nil {
		return err
	}
	defer resp.Body.Close()

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

	return json.Unmarshal(body, v)
}

// Get current system status and timestamp.
func GetStatus() (*Status, error) {
	var status *Status
	if err := sendRequest("/status", &status); err != nil {
		return nil, err
	}
	return status, nil
}

// Get most recent human communications with status and timestamp.
func GetMessages() ([]Message, error) {
	var messages []Message
	if err := sendRequest("/messages", &messages); err != nil {
		return nil, err
	}
	return messages, nil
}

// Get last human communication, status, and timestamp.
func GetLastMessage() (*Message, error) {
	var message *Message
	if err := sendRequest("/last-message", &message); err != nil {
		return nil, err
	}
	return message, nil
}
<commit_msg>Fix endpoints<commit_after>// The ghstatus package allows you to check the system status of GitHub from
// your own applications. The status information is retrieved from GitHub's
// system status API (https://status.github.com/api).

package ghstatus

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

// The root URL of GitHub's system status API.
const StatusApiUrl = "https://status.github.com"

// Possible status values.
const (
	StatusGood  = "good"
	StatusMinor = "minor"
	StatusMajor = "major"
)

// Current system status as returned by the /api/status.json endpoint.
type Status struct {
	Status      string `json:"status"`
	LastUpdated string `json:"last_updated"`
}

// A status message as returned by the /api/messages.json and
// /api/last-message.json endpoints.
type Message struct {
	Status    string `json:"status"`
	Body      string `json:"body"`
	CreatedOn string `json:"created_on"`
}

func sendRequest(endpoint string, v interface{}) error {
	resp, err := http.Get(StatusApiUrl + endpoint)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

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

	return json.Unmarshal(body, v)
}

// Get current system status and timestamp.
func GetStatus() (*Status, error) {
	var status *Status
	if err := sendRequest("/api/status.json", &status); err != nil {
		return nil, err
	}
	return status, nil
}

// Get most recent human communications with status and timestamp.
func GetMessages() ([]Message, error) {
	var messages []Message
	if err := sendRequest("/api/messages.json", &messages); err != nil {
		return nil, err
	}
	return messages, nil
}

// Get last human communication, status, and timestamp.
func GetLastMessage() (*Message, error) {
	var message *Message
	if err := sendRequest("/api/last-message.json", &message); err != nil {
		return nil, err
	}
	return message, nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package watcher

import (
	"path"

	"github.com/golang/glog"
)

// FakeWatcher implements an in-memory Watcher.
type FakeWatcher struct {
	watches map[string]bool
	events  chan Event
}

// NewFakeWatcher returns a fake Watcher for use in tests.
func NewFakeWatcher() *FakeWatcher {
	return &FakeWatcher{
		make(map[string]bool),
		make(chan Event)}
}

// Add adds a watch to the FakeWatcher
func (w *FakeWatcher) Add(name string) error {
	w.watches[name] = true
	return nil
}

// Close closes down the FakeWatcher
func (w *FakeWatcher) Close() error {
	close(w.events)
	return nil
}

// Remove removes a watch from the FakeWatcher
func (w *FakeWatcher) Remove(name string) error {
	delete(w.watches, name)
	return nil
}

// Events returns the channel of messages.
func (w *FakeWatcher) Events() <-chan Event { return w.events }

// InjectCreate lets a test inject a fake creation event.
func (w *FakeWatcher) InjectCreate(name string) {
	dirname := path.Dir(name)
	if w.watches[dirname] {
		w.events <- CreateEvent{name}
	} else {
		glog.Infof("not watching %s to see %s", dirname, name)
	}
}

// InjectUpdate lets a test inject a fake update event.
func (w *FakeWatcher) InjectUpdate(name string) {
	if w.watches[name] {
		w.events <- UpdateEvent{name}
	} else {
		glog.Infof("not watching %s", name)
	}
}

// InjectDelete lets a test inject a fake deletion event.
func (w *FakeWatcher) InjectDelete(name string) {
	if w.watches[name] {
		w.events <- DeleteEvent{name}
	} else {
		glog.Infof("not watching %s", name)
	}
}

// Watches returns a list of paths being watched.
func (w *FakeWatcher) Watches() (keys []string) {
	keys = make([]string, 0, len(w.watches))
	for k := range w.watches {
		keys = append(keys, k)
	}
	return
}
<commit_msg>Lock accesses to the fake watcher watch map, fixing a data race.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package watcher

import (
	"path"
	"sync"

	"github.com/golang/glog"
)

// FakeWatcher implements an in-memory Watcher.
type FakeWatcher struct {
	sync.RWMutex
	watches map[string]bool
	events  chan Event
}

// NewFakeWatcher returns a fake Watcher for use in tests.
func NewFakeWatcher() *FakeWatcher {
	return &FakeWatcher{
		watches: make(map[string]bool),
		events:  make(chan Event)}
}

// Add adds a watch to the FakeWatcher
func (w *FakeWatcher) Add(name string) error {
	w.Lock()
	w.watches[name] = true
	w.Unlock()
	return nil
}

// Close closes down the FakeWatcher
func (w *FakeWatcher) Close() error {
	close(w.events)
	return nil
}

// Remove removes a watch from the FakeWatcher
func (w *FakeWatcher) Remove(name string) error {
	w.Lock()
	delete(w.watches, name)
	w.Unlock()
	return nil
}

// Events returns the channel of messages.
func (w *FakeWatcher) Events() <-chan Event { return w.events }

// InjectCreate lets a test inject a fake creation event.
func (w *FakeWatcher) InjectCreate(name string) {
	dirname := path.Dir(name)
	w.RLock()
	defer w.RUnlock()
	if w.watches[dirname] {
		w.events <- CreateEvent{name}
	} else {
		glog.Infof("not watching %s to see %s", dirname, name)
	}
}

// InjectUpdate lets a test inject a fake update event.
func (w *FakeWatcher) InjectUpdate(name string) {
	w.RLock()
	defer w.RUnlock()
	if w.watches[name] {
		w.events <- UpdateEvent{name}
	} else {
		glog.Infof("not watching %s", name)
	}
}

// InjectDelete lets a test inject a fake deletion event.
func (w *FakeWatcher) InjectDelete(name string) {
	w.RLock()
	defer w.RUnlock()
	if w.watches[name] {
		w.events <- DeleteEvent{name}
	} else {
		glog.Infof("not watching %s", name)
	}
}

// Watches returns a list of paths being watched.
func (w *FakeWatcher) Watches() (keys []string) {
	w.RLock()
	defer w.RUnlock()
	keys = make([]string, 0, len(w.watches))
	for k := range w.watches {
		keys = append(keys, k)
	}
	return
}
<|endoftext|>


<commit_before>package git

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
)

type InitOptions struct {
	Quiet bool
	Bare  bool

	Template File

	// Not implemented
	SeparateGitDir File

	// Not implemented
	Shared os.FileMode
}

func Init(c *Client, opts InitOptions, dir string) (*Client, error) {
	if dir == "" {
		dir2, err := os.Getwd()
		if err != nil {
			return nil, err
		}
		dir = dir2
	}

	if err := os.MkdirAll(dir, 0755); err != nil {
		return nil, err
	}

	if !opts.Bare {
		if err := os.Mkdir(dir+"/.git", 0755); err != nil {
			return nil, err
		}
		if c != nil {
			c.GitDir = GitDir(dir + "/.git")
			c.WorkDir = WorkDir(dir)
		} else {
			c2, err := NewClient(dir+"/.git", dir)
			if err != nil {
				return nil, err
			}
			c = c2
		}
	} else {
		if c != nil {
			c.GitDir = GitDir(dir)
		} else {
			c2, err := NewClient(dir, "")
			if err != nil {
				return nil, err
			}
			c = c2
		}
	}

	// These are all the directories created by a clean "git init"
	// with the canonical git implementation
	if err := os.MkdirAll(c.GitDir.String()+"/objects/pack", 0755); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/objects/info", 0755); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/info", 0755); err != nil {
		// FIXME: Should have exclude file in it
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/hooks", 0755); err != nil {
		// FIXME: Should have sample hooks in it.
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/branches", 0755); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/refs/heads", 0755); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/refs/tags", 0755); err != nil {
		return nil, err
	}
	if err := c.GitDir.WriteFile("HEAD", []byte("ref: refs/heads/master\n"), 0644); err != nil {
		return nil, err
	}
	if err := c.GitDir.WriteFile("config", []byte("[core]\n\trepositoryformatversion = 0\n\tbare = false\n"), 0644); err != nil {
		return nil, err
	}
	if err := c.GitDir.WriteFile("description", []byte("Unnamed repository; edit this file 'description' to name the repository.\n"), 0644); err != nil {
		return nil, err
	}
	if !opts.Quiet {
		dir, err := filepath.Abs(c.GitDir.String())
		if err != nil {
			return c, err
		}
		fmt.Printf("Initialized empty Git repository in %v/\n", dir)
	}

	// Now go into the directory and adjust workdir and gitdir so that
	// tests are in the right place.
	if err := os.Chdir(c.WorkDir.String()); err != nil {
		return c, err
	}
	wd, err := os.Getwd()
	if err != nil {
		return c, err
	}
	c.WorkDir = WorkDir(wd)
	c.GitDir = GitDir(wd + "/.git")

	if opts.Template != "" {
		err = filepath.Walk(opts.Template.String(), func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			path, err = filepath.Rel(opts.Template.String(), path)
			if err != nil {
				return err
			}

			if info.IsDir() {
				os.MkdirAll(filepath.Join(c.GitDir.String(), path), 0777)
			} else {
				newFile, err := c.GitDir.Create(File(path))
				if err != nil {
					return err
				}
				defer newFile.Close()
				f, err := os.Open(filepath.Join(opts.Template.String(), path))
				if err != nil {
					return err
				}
				defer f.Close()
				_, err = io.Copy(newFile, f)
				if err != nil {
					return err
				}
			}

			return nil
		})

		return c, err
	}

	return c, nil
}
<commit_msg>Allow reinitialization of existing git repositories<commit_after>package git

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
)

type InitOptions struct {
	Quiet bool
	Bare  bool

	Template File

	// Not implemented
	SeparateGitDir File

	// Not implemented
	Shared os.FileMode
}

func Init(c *Client, opts InitOptions, dir string) (*Client, error) {
	if dir == "" {
		dir2, err := os.Getwd()
		if err != nil {
			return nil, err
		}
		dir = dir2
	}

	if err := os.MkdirAll(dir, 0755); err != nil {
		return nil, err
	}

	reinit := false
	if !opts.Bare {
		if File(dir + "/.git").Exists() {
			reinit = true
		} else if err := os.Mkdir(dir+"/.git", 0755); err != nil {
			return nil, err
		}
		if c != nil {
			c.GitDir = GitDir(dir + "/.git")
			c.WorkDir = WorkDir(dir)
		} else {
			c2, err := NewClient(dir+"/.git", dir)
			if err != nil {
				return nil, err
			}
			c = c2
		}
	} else {
		if c != nil {
			c.GitDir = GitDir(dir)
		} else {
			c2, err := NewClient(dir, "")
			if err != nil {
				return nil, err
			}
			c = c2
		}
	}

	// These are all the directories created by a clean "git init"
	// with the canonical git implementation
	if err := os.MkdirAll(c.GitDir.String()+"/objects/pack", 0755); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/objects/info", 0755); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/info", 0755); err != nil {
		// FIXME: Should have exclude file in it
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/hooks", 0755); err != nil {
		// FIXME: Should have sample hooks in it.
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/branches", 0755); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/refs/heads", 0755); err != nil {
		return nil, err
	}
	if err := os.MkdirAll(c.GitDir.String()+"/refs/tags", 0755); err != nil {
		return nil, err
	}

	if c.GitDir.File("HEAD").Exists() {
		reinit = true
	} else if err := c.GitDir.WriteFile("HEAD", []byte("ref: refs/heads/master\n"), 0644); err != nil {
		return nil, err
	}

	if c.GitDir.File("config").Exists() {
		reinit = true
	} else if err := c.GitDir.WriteFile("config", []byte("[core]\n\trepositoryformatversion = 0\n\tbare = false\n"), 0644); err != nil {
		return nil, err
	}
	if c.GitDir.File("description").Exists() {
		reinit = true
	} else if err := c.GitDir.WriteFile("description", []byte("Unnamed repository; edit this file 'description' to name the repository.\n"), 0644); err != nil {
		return nil, err
	}
	if !opts.Quiet {
		dir, err := filepath.Abs(c.GitDir.String())
		if err != nil {
			return c, err
		}
		if reinit {
			fmt.Printf("Reinitialized existing Git repository in %v/\n", dir)
		} else {
			fmt.Printf("Initialized empty Git repository in %v/\n", dir)
		}
	}

	// Now go into the directory and adjust workdir and gitdir so that
	// tests are in the right place.
	if err := os.Chdir(c.WorkDir.String()); err != nil {
		return c, err
	}
	wd, err := os.Getwd()
	if err != nil {
		return c, err
	}
	c.WorkDir = WorkDir(wd)
	c.GitDir = GitDir(wd + "/.git")

	if opts.Template != "" {
		err = filepath.Walk(opts.Template.String(), func(path string, info os.FileInfo, err error) error {
			if err != nil {
				return err
			}
			path, err = filepath.Rel(opts.Template.String(), path)
			if err != nil {
				return err
			}

			if info.IsDir() {
				os.MkdirAll(filepath.Join(c.GitDir.String(), path), 0777)
			} else {
				if c.GitDir.File(File(path)).Exists() {
					return nil
				}
				newFile, err := c.GitDir.Create(File(path))
				if err != nil {
					return err
				}
				defer newFile.Close()
				f, err := os.Open(filepath.Join(opts.Template.String(), path))
				if err != nil {
					return err
				}
				defer f.Close()
				_, err = io.Copy(newFile, f)
				if err != nil {
					return err
				}
			}

			return nil
		})

		return c, err
	}

	return c, nil
}
<|endoftext|>


<commit_before>package shark

import(
	tp "tritium/proto"
	"libxml/xpath"
	"rubex"
	proto "goprotobuf.googlecode.com/hg/proto"
)

type Shark struct {
	RegexpCache map[string]*rubex.Regexp
	XPathCache map[string]*xpath.Expression
}

type Ctx struct {
	Functions []*Function
	Types []string
	Exports [][]string
	Logs []string
	Env map[string]string
	LocalVar map[string]interface{}
	MatchStack []string
	MatchShouldContinue []bool
	*Shark
	*tp.Transform
}

type Function struct {
	Name string
	*tp.Function
}

type Scope struct {
	Value interface{}
}

func NewEngine() (*Shark) {
	e := &Shark{
		RegexpCache: make(map[string]*rubex.Regexp),
		XPathCache: make(map[string]*xpath.Expression),
	}
	return e
}

func (ctx *Ctx) UsePackage(pkg *tp.Package) {
	ctx.Types = make([]string, len(pkg.Types))
	for i, t := range(pkg.Types) {
		ctx.Types[i] = proto.GetString(t.Name)
	}

	ctx.Functions = make([]*Function, len(pkg.Functions))
	for i, f := range(pkg.Functions) {
		name := proto.GetString(f.Name)
		for _, a := range(f.Args) {
			typeString := ctx.Types[int(proto.GetInt32(a.TypeId))]
			name = name + "." + typeString
		}
		fun := &Function{
			Name: name,
			Function: f,
		}
		ctx.Functions[i] = fun
	}
}

func (eng *Shark) Run(transform *tp.Transform, input string, vars map[string]string) (data string, exports [][]string, logs []string) {
	ctx := &Ctx{
		Shark: eng,
		Exports: make([][]string, 0),
		Logs: make([]string, 0),
		Env: vars,
		Transform: transform,
		LocalVar: make(map[string]interface{}, 0),
		MatchStack: make([]string, 0),
		MatchShouldContinue: make([]bool, 0),
	}
	ctx.UsePackage(transform.Pkg)
	scope := &Scope{Value:input}
	ctx.runInstruction(scope, transform.Objects[0].Root, nil)
	data = scope.Value.(string)
	exports = ctx.Exports
	logs = ctx.Logs
	return
}

func (ctx *Ctx) matchShouldContinue() (bool) {
	return ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1]
}
func (ctx *Ctx) matchTarget() (string) {
	return ctx.MatchStack[len(ctx.MatchStack)-1]
}

func (ctx *Ctx) runInstruction(scope *Scope, ins *tp.Instruction, yieldBlock *tp.Instruction) (returnValue interface{}) {
	returnValue = ""
	switch *ins.Type {
	case tp.Instruction_BLOCK:
		returnValue = ctx.runChildren(scope, ins, yieldBlock)
	case tp.Instruction_TEXT:
		returnValue = proto.GetString(ins.Value)
	case tp.Instruction_LOCAL_VAR:
		name := proto.GetString(ins.Value)
		if len(ins.Arguments) > 0 {
			ctx.LocalVar[name] = ctx.runInstruction(scope, ins.Arguments[0], yieldBlock)
		}
		returnValue = ctx.LocalVar[name]
	case tp.Instruction_IMPORT:
		ctx.runChildren(scope, ctx.Objects[int(proto.GetInt32(ins.ObjectId))].Root, nil)
	case tp.Instruction_FUNCTION_CALL:
		//println(ins.String())
		fun := ctx.Functions[int(proto.GetInt32(ins.FunctionId))]
		args := make([]interface{}, len(ins.Arguments))
		for i, argIns := range(ins.Arguments) {
			args[i] = ctx.runInstruction(scope, argIns, yieldBlock)
		}
		if proto.GetBool(fun.BuiltIn) {
			switch fun.Name {
			case "this":
				returnValue = scope.Value
			case "yield":
				returnValue = ctx.runChildren(scope, yieldBlock, nil)
				yieldBlock = nil
			case "concat.Text.Text":
				returnValue = args[0].(string) + args[1].(string)
			case "var.Text":
				val := ctx.Env[args[0].(string)]
				ts := &Scope{Value: val}
				ctx.runChildren(ts, ins, yieldBlock)
				returnValue = ts.Value
				ctx.Env[args[0].(string)] = returnValue.(string)
			case "var.Text.Text":
				ctx.Env[args[0].(string)] = args[1].(string)
			case "match.Text":
				// Setup stacks
				ctx.MatchStack = append(ctx.MatchStack, args[0].(string))
				ctx.MatchShouldContinue = append(ctx.MatchShouldContinue, true)

				// Run children
				ctx.runChildren(scope, ins, yieldBlock)

				if ctx.matchShouldContinue() {
					returnValue = "false"
				} else {
					returnValue = "true"
				}

				// Clear
				ctx.MatchShouldContinue = ctx.MatchShouldContinue[:len(ctx.MatchShouldContinue)-1]
				ctx.MatchStack = ctx.MatchStack[:len(ctx.MatchStack)-1]
			case "with.Text":
				returnValue = "false"
				if ctx.matchShouldContinue() {
					if args[0].(string) == ctx.matchTarget() {
						ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1] = false
						ctx.runChildren(scope, ins, yieldBlock)
						returnValue = "true"
					}
				}
			case "with.Regexp":
				returnValue = "false"
				if ctx.matchShouldContinue() {
					//println(matcher.MatchAgainst, matchWith)
					if (args[0].(*rubex.Regexp)).Match([]uint8(ctx.matchTarget())) {
						ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1] = false
						ctx.runChildren(scope, ins, yieldBlock)
						returnValue = "true"
					}
				}
			case "not.Text":
				returnValue = "false"
				if ctx.matchShouldContinue() {
					if args[0].(string) != ctx.matchTarget() {
						ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1] = false
						ctx.runChildren(scope, ins, yieldBlock)
						returnValue = "true"
					}
				}
			case "not.Regexp":
				returnValue = "false"
				if ctx.matchShouldContinue() {
					//println(matcher.MatchAgainst, matchWith)
					if !(args[0].(*rubex.Regexp)).Match([]uint8(ctx.matchTarget())) {
						ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1] = false
						ctx.runChildren(scope, ins, yieldBlock)
						returnValue = "true"
					}
				}
			case "regexp.Text":
				returnValue = rubex.MustCompile(args[0].(string))
			case "export.Text":
				val := make([]string, 2)
				val[0] = args[0].(string)
				ts := &Scope{Value:""}
				ctx.runChildren(ts, ins, yieldBlock)
				val[1] = ts.Value.(string)
				ctx.Exports = append(ctx.Exports, val)
			case "set.Text":
				scope.Value = args[0]
			case "log.Text":
				ctx.Logs = append(ctx.Logs, args[0].(string))
			case "append.Text":
				scope.Value = scope.Value.(string) + args[0].(string)
			case "prepend.Text":
				scope.Value = args[0].(string) + scope.Value.(string)
			default:
				println("Must implement", fun.Name)
			}
		} else { // We are using a user-defined function
			// Store the current frame
			localVar := ctx.LocalVar

			// Setup the new local var
			ctx.LocalVar = make(map[string]interface{}, len(args))
			for i, arg := range(fun.Args) {
				ctx.LocalVar[proto.GetString(arg.Name)] = args[i]
			}

			yieldIns := &tp.Instruction{
				Type: tp.NewInstruction_InstructionType(tp.Instruction_BLOCK),
				Children: ins.Children,
			}
			returnValue = ctx.runChildren(scope, fun.Instruction, yieldIns)

			// Put the local var scope back!
			ctx.LocalVar = localVar
		}
	}
	return
}

func (ctx *Ctx) runChildren(scope *Scope, ins *tp.Instruction, yieldBlock *tp.Instruction) (returnValue interface{}) {
	for _, child := range(ins.Children) {
		returnValue = ctx.runInstruction(scope, child, yieldBlock)
	}
	return
}
<commit_msg>temporarily implemented concat.3<commit_after>package shark

import(
	tp "tritium/proto"
	"libxml/xpath"
	"rubex"
	proto "goprotobuf.googlecode.com/hg/proto"
)

type Shark struct {
	RegexpCache map[string]*rubex.Regexp
	XPathCache map[string]*xpath.Expression
}

type Ctx struct {
	Functions []*Function
	Types []string
	Exports [][]string
	Logs []string
	Env map[string]string
	LocalVar map[string]interface{}
	MatchStack []string
	MatchShouldContinue []bool
	*Shark
	*tp.Transform
}

type Function struct {
	Name string
	*tp.Function
}

type Scope struct {
	Value interface{}
}

func NewEngine() (*Shark) {
	e := &Shark{
		RegexpCache: make(map[string]*rubex.Regexp),
		XPathCache: make(map[string]*xpath.Expression),
	}
	return e
}

func (ctx *Ctx) UsePackage(pkg *tp.Package) {
	ctx.Types = make([]string, len(pkg.Types))
	for i, t := range(pkg.Types) {
		ctx.Types[i] = proto.GetString(t.Name)
	}

	ctx.Functions = make([]*Function, len(pkg.Functions))
	for i, f := range(pkg.Functions) {
		name := proto.GetString(f.Name)
		for _, a := range(f.Args) {
			typeString := ctx.Types[int(proto.GetInt32(a.TypeId))]
			name = name + "." + typeString
		}
		fun := &Function{
			Name: name,
			Function: f,
		}
		ctx.Functions[i] = fun
	}
}

func (eng *Shark) Run(transform *tp.Transform, input string, vars map[string]string) (data string, exports [][]string, logs []string) {
	ctx := &Ctx{
		Shark: eng,
		Exports: make([][]string, 0),
		Logs: make([]string, 0),
		Env: vars,
		Transform: transform,
		LocalVar: make(map[string]interface{}, 0),
		MatchStack: make([]string, 0),
		MatchShouldContinue: make([]bool, 0),
	}
	ctx.UsePackage(transform.Pkg)
	scope := &Scope{Value:input}
	ctx.runInstruction(scope, transform.Objects[0].Root, nil)
	data = scope.Value.(string)
	exports = ctx.Exports
	logs = ctx.Logs
	return
}

func (ctx *Ctx) matchShouldContinue() (bool) {
	return ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1]
}
func (ctx *Ctx) matchTarget() (string) {
	return ctx.MatchStack[len(ctx.MatchStack)-1]
}

func (ctx *Ctx) runInstruction(scope *Scope, ins *tp.Instruction, yieldBlock *tp.Instruction) (returnValue interface{}) {
	returnValue = ""
	switch *ins.Type {
	case tp.Instruction_BLOCK:
		returnValue = ctx.runChildren(scope, ins, yieldBlock)
	case tp.Instruction_TEXT:
		returnValue = proto.GetString(ins.Value)
	case tp.Instruction_LOCAL_VAR:
		name := proto.GetString(ins.Value)
		if len(ins.Arguments) > 0 {
			ctx.LocalVar[name] = ctx.runInstruction(scope, ins.Arguments[0], yieldBlock)
		}
		returnValue = ctx.LocalVar[name]
	case tp.Instruction_IMPORT:
		ctx.runChildren(scope, ctx.Objects[int(proto.GetInt32(ins.ObjectId))].Root, nil)
	case tp.Instruction_FUNCTION_CALL:
		//println(ins.String())
		fun := ctx.Functions[int(proto.GetInt32(ins.FunctionId))]
		args := make([]interface{}, len(ins.Arguments))
		for i, argIns := range(ins.Arguments) {
			args[i] = ctx.runInstruction(scope, argIns, yieldBlock)
		}
		if proto.GetBool(fun.BuiltIn) {
			switch fun.Name {
			case "this":
				returnValue = scope.Value
			case "yield":
				returnValue = ctx.runChildren(scope, yieldBlock, nil)
				yieldBlock = nil
			case "concat.Text.Text":
				returnValue = args[0].(string) + args[1].(string)
			case "concat.Text.Text.Text": //REMOVE
				returnValue = args[0].(string) + args[1].(string) + args[2].(string)
			case "var.Text":
				val := ctx.Env[args[0].(string)]
				ts := &Scope{Value: val}
				ctx.runChildren(ts, ins, yieldBlock)
				returnValue = ts.Value
				ctx.Env[args[0].(string)] = returnValue.(string)
			case "var.Text.Text":
				ctx.Env[args[0].(string)] = args[1].(string)
			case "match.Text":
				// Setup stacks
				ctx.MatchStack = append(ctx.MatchStack, args[0].(string))
				ctx.MatchShouldContinue = append(ctx.MatchShouldContinue, true)

				// Run children
				ctx.runChildren(scope, ins, yieldBlock)

				if ctx.matchShouldContinue() {
					returnValue = "false"
				} else {
					returnValue = "true"
				}

				// Clear
				ctx.MatchShouldContinue = ctx.MatchShouldContinue[:len(ctx.MatchShouldContinue)-1]
				ctx.MatchStack = ctx.MatchStack[:len(ctx.MatchStack)-1]
			case "with.Text":
				returnValue = "false"
				if ctx.matchShouldContinue() {
					if args[0].(string) == ctx.matchTarget() {
						ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1] = false
						ctx.runChildren(scope, ins, yieldBlock)
						returnValue = "true"
					}
				}
			case "with.Regexp":
				returnValue = "false"
				if ctx.matchShouldContinue() {
					//println(matcher.MatchAgainst, matchWith)
					if (args[0].(*rubex.Regexp)).Match([]uint8(ctx.matchTarget())) {
						ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1] = false
						ctx.runChildren(scope, ins, yieldBlock)
						returnValue = "true"
					}
				}
			case "not.Text":
				returnValue = "false"
				if ctx.matchShouldContinue() {
					if args[0].(string) != ctx.matchTarget() {
						ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1] = false
						ctx.runChildren(scope, ins, yieldBlock)
						returnValue = "true"
					}
				}
			case "not.Regexp":
				returnValue = "false"
				if ctx.matchShouldContinue() {
					//println(matcher.MatchAgainst, matchWith)
					if !(args[0].(*rubex.Regexp)).Match([]uint8(ctx.matchTarget())) {
						ctx.MatchShouldContinue[len(ctx.MatchShouldContinue)-1] = false
						ctx.runChildren(scope, ins, yieldBlock)
						returnValue = "true"
					}
				}
			case "regexp.Text":
				returnValue = rubex.MustCompile(args[0].(string))
			case "export.Text":
				val := make([]string, 2)
				val[0] = args[0].(string)
				ts := &Scope{Value:""}
				ctx.runChildren(ts, ins, yieldBlock)
				val[1] = ts.Value.(string)
				ctx.Exports = append(ctx.Exports, val)
			case "set.Text":
				scope.Value = args[0]
			case "log.Text":
				ctx.Logs = append(ctx.Logs, args[0].(string))
			case "append.Text":
				scope.Value = scope.Value.(string) + args[0].(string)
			case "prepend.Text":
				scope.Value = args[0].(string) + scope.Value.(string)
			default:
				println("Must implement", fun.Name)
			}
		} else { // We are using a user-defined function
			// Store the current frame
			localVar := ctx.LocalVar

			// Setup the new local var
			ctx.LocalVar = make(map[string]interface{}, len(args))
			for i, arg := range(fun.Args) {
				ctx.LocalVar[proto.GetString(arg.Name)] = args[i]
			}

			yieldIns := &tp.Instruction{
				Type: tp.NewInstruction_InstructionType(tp.Instruction_BLOCK),
				Children: ins.Children,
			}
			returnValue = ctx.runChildren(scope, fun.Instruction, yieldIns)

			// Put the local var scope back!
			ctx.LocalVar = localVar
		}
	}
	return
}

func (ctx *Ctx) runChildren(scope *Scope, ins *tp.Instruction, yieldBlock *tp.Instruction) (returnValue interface{}) {
	for _, child := range(ins.Children) {
		returnValue = ctx.runInstruction(scope, child, yieldBlock)
	}
	return
}
<|endoftext|>


<commit_before>package commands

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
)

var errCtrlC = errors.New("^C")

func printDu1Line(out io.Writer, name string, size int64) {
	fmt.Fprintf(out, "%7s %s\n", formatByHumanize(size), name)
}

// _du returns the sum (bytes) of path
func _du(path string, output func(string, int64) error, stderr io.Writer, blocksize int64) (int64, error) {
	fd, err := os.Open(path)
	if err != nil {
		return 0, err
	}
	stat, err := fd.Stat()
	if err != nil {
		return 0, err
	}
	if !stat.IsDir() {
		fd.Close()
		return ((stat.Size() + blocksize - 1) / blocksize) * blocksize, nil
	}
	files, err := fd.Readdir(-1)
	if err != nil {
		fd.Close()
		return 0, err
	}
	var diskuse int64
	dirs := make([]string, 0, len(files))
	for _, file1 := range files {
		if file1.IsDir() {
			dirs = append(dirs, file1.Name())
		} else {
			diskuse += ((file1.Size() + blocksize - 1) / blocksize) * blocksize
		}
	}
	if err := fd.Close(); err != nil {
		return diskuse, err
	}
	for _, dir1 := range dirs {
		fullpath := filepath.Join(path, dir1)
		diskuse1, err := _du(fullpath, output, stderr, blocksize)
		if err == nil {
			if err = output(fullpath, diskuse1); err == nil {
				diskuse += diskuse1
				continue
			}
		}
		fmt.Fprintf(stderr, "%s: %s\n", fullpath, err)
	}
	return diskuse, nil
}

func cmdDiskUsed(ctx context.Context, cmd Param) (int, error) {
	output := func(name string, size int64) error {
		printDu1Line(cmd.Out(), name, size)
		if ctx != nil {
			select {
			case <-ctx.Done():
				return errCtrlC
			default:
			}
		}
		return nil
	}
	count := 0
	for _, arg1 := range cmd.Args()[1:] {
		if arg1 == "-s" {
			output = func(_ string, _ int64) error {
				if ctx != nil {
					select {
					case <-ctx.Done():
						return errCtrlC
					default:
					}
				}
				return nil
			}
			continue
		}
		size, err := _du(arg1, output, cmd.Err(), 4096)
		count++
		if err != nil {
			fmt.Fprintf(cmd.Err(), "%s: %s\n", arg1, err)
			continue
		}
		printDu1Line(cmd.Out(), arg1, size)
	}
	if count <= 0 {
		size, err := _du(".", output, cmd.Err(), 4096)
		if err != nil {
			return 1, err
		}
		printDu1Line(cmd.Out(), ".", size)
	}
	return 0, nil
}
<commit_msg>Fix: diskused can not be stoped by Ctrl-C<commit_after>package commands

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
)

var errCtrlC = errors.New("^C")

func printDu1Line(out io.Writer, name string, size int64) {
	fmt.Fprintf(out, "%7s %s\n", formatByHumanize(size), name)
}

// _du returns the sum (bytes) of path
func _du(path string, output func(string, int64) error, stderr io.Writer, blocksize int64) (int64, error) {
	fd, err := os.Open(path)
	if err != nil {
		return 0, err
	}
	stat, err := fd.Stat()
	if err != nil {
		return 0, err
	}
	if !stat.IsDir() {
		fd.Close()
		return ((stat.Size() + blocksize - 1) / blocksize) * blocksize, nil
	}
	files, err := fd.Readdir(-1)
	if err != nil {
		fd.Close()
		return 0, err
	}
	var diskuse int64
	dirs := make([]string, 0, len(files))
	for _, file1 := range files {
		if file1.IsDir() {
			dirs = append(dirs, file1.Name())
		} else {
			diskuse += ((file1.Size() + blocksize - 1) / blocksize) * blocksize
		}
	}
	if err := fd.Close(); err != nil {
		return diskuse, err
	}
	for _, dir1 := range dirs {
		fullpath := filepath.Join(path, dir1)
		diskuse1, err := _du(fullpath, output, stderr, blocksize)
		if err == errCtrlC {
			return diskuse, err
		}
		if err == nil {
			if err = output(fullpath, diskuse1); err == nil {
				diskuse += diskuse1
				continue
			} else if err == errCtrlC {
				return diskuse1, errCtrlC
			}
		}
		fmt.Fprintf(stderr, "%s: %s\n", fullpath, err)
	}
	return diskuse, nil
}

func cmdDiskUsed(ctx context.Context, cmd Param) (int, error) {
	output := func(name string, size int64) error {
		printDu1Line(cmd.Out(), name, size)
		if ctx != nil {
			select {
			case <-ctx.Done():
				return errCtrlC
			default:
			}
		}
		return nil
	}
	count := 0
	for _, arg1 := range cmd.Args()[1:] {
		if arg1 == "-s" {
			output = func(_ string, _ int64) error {
				if ctx != nil {
					select {
					case <-ctx.Done():
						return errCtrlC
					default:
					}
				}
				return nil
			}
			continue
		}
		size, err := _du(arg1, output, cmd.Err(), 4096)
		count++
		if err != nil {
			fmt.Fprintf(cmd.Err(), "%s: %s\n", arg1, err)
			if err == errCtrlC {
				return 0, err
			}
			continue
		}
		printDu1Line(cmd.Out(), arg1, size)
	}
	if count <= 0 {
		size, err := _du(".", output, cmd.Err(), 4096)
		if err != nil {
			return 1, err
		}
		printDu1Line(cmd.Out(), ".", size)
	}
	return 0, nil
}
<|endoftext|>


<commit_before>/*

Copyright 2015 Zola Mahlaza <adeebnqo@gmail.com>
22 January 2015

*/
package main

import (
	"code.google.com/p/gocc/ast"
	"container/list"
	"fmt"
	"github.com/AdeebNqo/sublimegen/repository"
	"strconv"
	"strings"
)

//----------------------------------------------------------------------
//
//   REGEX
//
//----------------------------------------------------------------------

/*

Function for disentangling a pattern to obtain it's regex

*/
func constructregexandfillgroups(alternatives []*ast.LexAlt) string {
	regex := ""
	for index, lexitem := range alternatives {
		tmpregex := getregex(lexitem)
		if index > 0 {
			tmpregex = "|" + tmpregex
		}
		regex += tmpregex
	}
	//regex += ")"
	return regex
}

/*

function for retrieving regex from individual lexalt item

return a string, the regex
*/
func getregex(lexitem *ast.LexAlt) string {
	regex := ""
	for _, term := range lexitem.Terms {
		regex += reallygetregex(term)
	}
	return regex
}

/*

Function for really retrieving regex from individual lexterm items.
This function essentially helps "getregex"

return a string, the regex
*/
func reallygetregex(lexterm interface{}) string {
	switch lexterm.(type) {
	case *ast.LexCharLit:
		{
			term := lexterm.(*ast.LexCharLit)
			termasstring := stripliteral(term.String())

			//The outside character classes are .^$*+?()[{\|
			//The inside character classes are ^-]\

			return Escape(termasstring)
		}
	case *ast.LexCharRange:
		{
			term := lexterm.(*ast.LexCharRange)
			from := reallygetregex(term.From)
			to := reallygetregex(term.To)
			retval := fmt.Sprintf("[%v-%v]", from, to)

			return retval
		}
	case *ast.LexGroupPattern:
		{
			term := lexterm.(*ast.LexGroupPattern)

			retval := "("
			for index, lexalt := range term.LexPattern.Alternatives {
				if index > 0 {
					retval += "|"
				}
				retval += getregex(lexalt)
			}
			retval += ")"
			return retval
		}
	case *ast.LexOptPattern:
		{

			term := lexterm.(*ast.LexOptPattern)

			alternatives := term.LexPattern.Alternatives

			if len(alternatives)==1{
			    terms := alternatives[0].Terms
			    if len(terms)==1{
			        switch terms[0].(type){
			            case *ast.LexCharLit:{
			                return fmt.Sprintf("%v?", getregex(alternatives[0]))
			            }
			            case *ast.LexDot:{
			                return fmt.Sprintf("%v?", getregex(alternatives[0]))
			            }
			        }
			    }
			}
			retval := "("
			for index, lexalt := range alternatives {
				if index > 0 {
					retval += "|"
				}
				retval += getregex(lexalt)
			}
			retval += ")?"
			return retval
		}
	case *ast.LexRepPattern:
		{
			term := lexterm.(*ast.LexRepPattern)

			alternatives := term.LexPattern.Alternatives

			if len(alternatives)==1{
			   terms := alternatives[0].Terms
			   if len(terms)==1{
			       switch terms[0].(type){
			           case *ast.LexCharLit:{
			               return fmt.Sprintf("%v*", getregex(alternatives[0]))
			           }
			           case *ast.LexDot:{
			               return fmt.Sprintf("%v*", getregex(alternatives[0]))
			           }
			       }
			   }
			}
			retval := "("
			for index, lexalt := range alternatives {
				if index > 0 {
					retval += "|"
				}
				retval += getregex(lexalt)
			}
			retval += ")*"
			return retval
		}
	case *ast.LexDot:
		{
			return "."
		}
	case *ast.LexRegDefId:
		{
			term := lexterm.(*ast.LexRegDefId)

			for val := repoitems.Front(); val != nil; val = val.Next() {
				rval := val.Value.(*repository.Repoitem)
				if repository.GetRealname(rval) == term.Id {
					if repository.Isregexempty(rval) {

						alternatives := repository.GetRighthandside(rval).Alternatives
						retval := ""
						for index, lexalt := range alternatives {
							if index > 0 {
								retval += "|"
							}
							retval += getregex(lexalt)
						}
						repository.Setregex(rval, retval)
						//return retval
						return fmt.Sprintf("(%s)",retval) //debug

					} else {
						//return repository.Getregex(rval)
						return "("+repository.Getregex(rval)+")"
					}
				}
			}
		}
	default:
		{
			return "err"
		}
	}
	return ""
}

/*

Method for escaping special regex characters

*/

func Escape(termasstring string) string {
	if termasstring == "/" {
		return "\\/"
	} else if termasstring == "$" {
		return "\\$"
	} else if termasstring == "*" {
		return "\\*"
	} else if termasstring == "[" {
		return "\\["
	} else if termasstring == "]" {
		return "\\]"
	} else if termasstring == "\\" {
		return "\\\\"
	} else if termasstring == " " {
		return "[ ]"
	} else if termasstring == "+" {
		return "\\+"
	} else if termasstring == "(" {
		return "\\("
	} else if termasstring == ")" {
		return "\\)"
	} else if termasstring == "{" {
		return "\\{"
	} else if termasstring == "}" {
		return "\\}"
	}
	return termasstring
}

/*

Method for strippinf the start and end characters from a token.
It is used mainly to turn 'foobar' to foobar.

*/

func stripliteral(somelit string) string {
	if somelit != "" {
		somelit = somelit[1 : len(somelit)-1]
	}
	return somelit
}

//----------------------------------------------------------------------
//
//   Groups
//
//----------------------------------------------------------------------

/*

This method is used to determine whether the current regex is
is multiline line or not. If it is, it will return true and the begin,
middle and end parts of the regex. This assumes that regex can be seperated
in three. If not, it will return false, and three empty strings.

*/
func determinebeginandend(someregex string) (bool, string, string, string) {
	var begin string
	var end string
	var middle string
	for index, somechar := range someregex {
		//we possibly found the middle part
		if somechar == '(' {
			slice := someregex[index:]
			if len(slice) == 0 {
				return false, "", "", ""
			} else {
				//collecting the middle part
				for innerindex, innersomechar := range slice {
					if innersomechar == ')' {
						middle += ")"

						possibleend := someregex[index+innerindex+1:]
						if len(possibleend) == 0 {
							return false, "", "", ""
						} else {
							if possibleend[0] == '?' || possibleend[0] == '+' || possibleend[0] == '*' {
								middle += string(possibleend[0])
								possibleend = possibleend[1:]
							}
							//collecting end part
							for _, endchar := range possibleend {
								if endchar == '(' || endchar == ')' {
									return false, "", "", ""
								}
								end += string(endchar)
							}
						}
					}
					if len(end) == 0 {
						//else increase middle
						middle += string(innersomechar)
					}
				}
			}
			break
		}else if somechar=='|'{
			return false, "", "", ""
		}
		//appending to the begin char
		begin += string(somechar)
	}
	if len(end) == 0 || len(begin) == 0 {
		return false, "", "", ""
	}
	return true, begin, middle, end
}

/*

This method is for identifiying groups from a regular expressions.
It is will return two lists, The first list contains identified
groups so far, each entry entry will look like the following:

    <somescope>|<number>

Here the somescope variable refers to the scope to be used, e.g constant.numeric
and the number is the number of the group within the regex.

Please note that this method is made to be called kinda-recursively. The second list
the levels are as follows:
is the list of groups in a group level. for instance given the regex (A(B)(C)(D(E))))
Level 1 -  (A(B)(C)(D(E)))
Level 2 - (B), (C), (D(E))
Level 3 - (E)

*/
func getgroups(currentregex string, originalregex string, groupcount int, scopecontainer *list.List, nextlayer *list.List) (*list.List, *list.List) {

	var matched bool
	var scope string

	if currentregex!=""{
        //fmt.Println("X---X")
        fmt.Println("curregex:",currentregex)
		matched, scope = retrievescopefromcapturegroup(currentregex, false)
        //fmt.Println("X---X")
	}
	if matched {
		groupcount += 1
		scopecontainer.PushBack(scope + "|" + strconv.Itoa(groupcount))
		return scopecontainer, nextlayer
	} else {

		count := 0
		regexlength := len(currentregex)
		stack := Stack{}

        hacked := false
        pos := strings.Index(currentregex,"(")
        for ;pos!= -1 && pos!=0 && currentregex[pos-1]=='\\';{
            hacked = true
            nextpos := strings.Index(currentregex[pos+1:],"(")
            if nextpos == -1{
                break
            }else{
                pos += 1+nextpos
            }
        }

        if pos!=-1{
            count+=1
            fmt.Println("start at pos: ",pos)
            for innerindex:=pos+1; innerindex<regexlength; innerindex++{
                innercurrcharacter := string(currentregex[innerindex])
                if innercurrcharacter=="("{
                    //found brace inner group, start by checking if it's not escaped
                    if innerindex-1<0 || currentregex[innerindex-1]!='\\'{
                        //it is not escaped
                        count +=1
                        stack.Push(innercurrcharacter)
                        //fmt.Println(innercurrcharacter,count) //debug
                    }else{
                        stack.Push(innercurrcharacter)
                    }
                }else if innercurrcharacter==")"{
                    if innerindex+1<regexlength{
                        //still within bounds of regex, that is, there is a next char
                        if currentregex[innerindex+1]=='*' || currentregex[innerindex+1]=='+' || currentregex[innerindex+1]=='?'{
                            //do decrease count, push it in
                            count -= 1
                            stack.Push(innercurrcharacter)
                        }else{
                            count -= 1
                            if count!=0{
                                stack.Push(innercurrcharacter)
                            }
                        }
                    }else{
                        count-=1;
                    }
                }else{
                    stack.Push(innercurrcharacter)
                }
                if count==0{
                    //the contents of the stack are the group elements

                    biggest := ""
                    for {
                        head := stack.Pop()
                        if head == nil {
                            break
                        }
                        biggest = head.(string) + biggest
                    }

                    //fmt.Println("X---X")
                    fmt.Println("group: ",biggest)
                    //trying to see if group can be matched
                    matched, scope = retrievescopefromcapturegroup(biggest, false)
                    fmt.Println("matched:",matched)
                    //fmt.Println("X---X")

                    if matched {
                            groupcount += 1
                            scopecontainer.PushBack(scope + "|" + strconv.Itoa(groupcount))
                    }
                    if !matched {
                        groupcount += 1
                        nextlayer.PushFront(biggest)
                        fmt.Println("added ff to next layer:",biggest)
                    }
                    if hacked{
                        currentregex = ""
                        hacked = false
                    }
                    if len(biggest) < regexlength {
                        if len(currentregex)>0{
                            scopecontainer, nextlayer = getgroups(currentregex[innerindex+1:], originalregex, groupcount, scopecontainer, nextlayer)
                        }
                    }
                    if nextlayer.Len() != 0 {
                        for it := nextlayer.Back(); it != nil; it = it.Prev() {
                            nextlayer.Remove(it)
                            itvalue := it.Value.(string)
                            scopecontainer, nextlayer = getgroups(itvalue, originalregex, groupcount, scopecontainer, nextlayer)
                        }
                    }
                    break
                }
            }
        }
	}
	return scopecontainer, nextlayer
}

/*

Inefficient method for retrieving scope of regex
*/
func retrievescopefromcapturegroup(capturedregex string, activate bool) (bool, string) {

	if capturedregex!=""{
		if activate==true {
			capturedregex = capturedregex[1 : len(capturedregex)-1]
		}
		for ritem := repoitems.Front(); ritem != nil; ritem = ritem.Next() {

			if repository.Getregex(ritem.Value.(*repository.Repoitem)) == capturedregex {
				tmpscope := repository.GetScope(ritem.Value.(*repository.Repoitem))
				if tmpscope != defaultscope {
					return true, tmpscope
				}
			}
		}
	}
	return false, ""
}

/*
Method for determining if strings starts and ends with round braces
*/
func startandendwithrb(somestring string) bool{
	return strings.HasPrefix(somestring,"(") && strings.HasSuffix(somestring,")")
}<commit_msg>found another bug, they keep piling up<commit_after>/*

Copyright 2015 Zola Mahlaza <adeebnqo@gmail.com>
22 January 2015

*/
package main

import (
	"code.google.com/p/gocc/ast"
	"container/list"
	"fmt"
	"github.com/AdeebNqo/sublimegen/repository"
	"strconv"
	"strings"
)

//----------------------------------------------------------------------
//
//   REGEX
//
//----------------------------------------------------------------------

/*

Function for disentangling a pattern to obtain it's regex

*/
func constructregexandfillgroups(alternatives []*ast.LexAlt) string {
	regex := ""
	for index, lexitem := range alternatives {
		tmpregex := getregex(lexitem)
		if index > 0 {
			tmpregex = "|" + tmpregex
		}
		regex += tmpregex
	}
	//regex += ")"
	return regex
}

/*

function for retrieving regex from individual lexalt item

return a string, the regex
*/
func getregex(lexitem *ast.LexAlt) string {
	regex := ""
	for _, term := range lexitem.Terms {
		regex += reallygetregex(term)
	}
	return regex
}

/*

Function for really retrieving regex from individual lexterm items.
This function essentially helps "getregex"

return a string, the regex
*/
func reallygetregex(lexterm interface{}) string {
	switch lexterm.(type) {
	case *ast.LexCharLit:
		{
			term := lexterm.(*ast.LexCharLit)
			termasstring := stripliteral(term.String())

			//The outside character classes are .^$*+?()[{\|
			//The inside character classes are ^-]\

			return Escape(termasstring)
		}
	case *ast.LexCharRange:
		{
			term := lexterm.(*ast.LexCharRange)
			from := reallygetregex(term.From)
			to := reallygetregex(term.To)
			retval := fmt.Sprintf("[%v-%v]", from, to)

			return retval
		}
	case *ast.LexGroupPattern:
		{
			term := lexterm.(*ast.LexGroupPattern)

			retval := "("
			for index, lexalt := range term.LexPattern.Alternatives {
				if index > 0 {
					retval += "|"
				}
				retval += getregex(lexalt)
			}
			retval += ")"
			return retval
		}
	case *ast.LexOptPattern:
		{

			term := lexterm.(*ast.LexOptPattern)

			alternatives := term.LexPattern.Alternatives

			if len(alternatives)==1{
			    terms := alternatives[0].Terms
			    if len(terms)==1{
			        switch terms[0].(type){
			            case *ast.LexCharLit:{
			                return fmt.Sprintf("%v?", getregex(alternatives[0]))
			            }
			            case *ast.LexDot:{
			                return fmt.Sprintf("%v?", getregex(alternatives[0]))
			            }
			        }
			    }
			}
			retval := "("
			for index, lexalt := range alternatives {
				if index > 0 {
					retval += "|"
				}
				retval += getregex(lexalt)
			}
			retval += ")?"
			return retval
		}
	case *ast.LexRepPattern:
		{
			term := lexterm.(*ast.LexRepPattern)

			alternatives := term.LexPattern.Alternatives

			if len(alternatives)==1{
			   terms := alternatives[0].Terms
			   if len(terms)==1{
			       switch terms[0].(type){
			           case *ast.LexCharLit:{
			               return fmt.Sprintf("%v*", getregex(alternatives[0]))
			           }
			           case *ast.LexDot:{
			               return fmt.Sprintf("%v*", getregex(alternatives[0]))
			           }
			       }
			   }
			}
			retval := "("
			for index, lexalt := range alternatives {
				if index > 0 {
					retval += "|"
				}
				retval += getregex(lexalt)
			}
			retval += ")*"
			return retval
		}
	case *ast.LexDot:
		{
			return "."
		}
	case *ast.LexRegDefId:
		{
			term := lexterm.(*ast.LexRegDefId)

			for val := repoitems.Front(); val != nil; val = val.Next() {
				rval := val.Value.(*repository.Repoitem)
				if repository.GetRealname(rval) == term.Id {
					if repository.Isregexempty(rval) {

						alternatives := repository.GetRighthandside(rval).Alternatives
						retval := ""
						for index, lexalt := range alternatives {
							if index > 0 {
								retval += "|"
							}
							retval += getregex(lexalt)
						}
						repository.Setregex(rval, retval)
						//return retval
						return fmt.Sprintf("(%s)",retval) //debug

					} else {
						//return repository.Getregex(rval)
						return "("+repository.Getregex(rval)+")"
					}
				}
			}
		}
	default:
		{
			return "err"
		}
	}
	return ""
}

/*

Method for escaping special regex characters

*/

func Escape(termasstring string) string {
	if termasstring == "/" {
		return "\\/"
	} else if termasstring == "$" {
		return "\\$"
	} else if termasstring == "*" {
		return "\\*"
	} else if termasstring == "[" {
		return "\\["
	} else if termasstring == "]" {
		return "\\]"
	} else if termasstring == "\\" {
		return "\\\\"
	} else if termasstring == " " {
		return "[ ]"
	} else if termasstring == "+" {
		return "\\+"
	} else if termasstring == "(" {
		return "\\("
	} else if termasstring == ")" {
		return "\\)"
	} else if termasstring == "{" {
		return "\\{"
	} else if termasstring == "}" {
		return "\\}"
	}
	return termasstring
}

/*

Method for strippinf the start and end characters from a token.
It is used mainly to turn 'foobar' to foobar.

*/

func stripliteral(somelit string) string {
	if somelit != "" {
		somelit = somelit[1 : len(somelit)-1]
	}
	return somelit
}

//----------------------------------------------------------------------
//
//   Groups
//
//----------------------------------------------------------------------

/*

This method is used to determine whether the current regex is
is multiline line or not. If it is, it will return true and the begin,
middle and end parts of the regex. This assumes that regex can be seperated
in three. If not, it will return false, and three empty strings.

*/
func determinebeginandend(someregex string) (bool, string, string, string) {
	var begin string
	var end string
	var middle string
	for index, somechar := range someregex {
		//we possibly found the middle part
		if somechar == '(' {
			slice := someregex[index:]
			if len(slice) == 0 {
				return false, "", "", ""
			} else {
				//collecting the middle part
				for innerindex, innersomechar := range slice {
					if innersomechar == ')' {
						middle += ")"

						possibleend := someregex[index+innerindex+1:]
						if len(possibleend) == 0 {
							return false, "", "", ""
						} else {
							if possibleend[0] == '?' || possibleend[0] == '+' || possibleend[0] == '*' {
								middle += string(possibleend[0])
								possibleend = possibleend[1:]
							}
							//collecting end part
							for _, endchar := range possibleend {
								if endchar == '(' || endchar == ')' {
									return false, "", "", ""
								}
								end += string(endchar)
							}
						}
					}
					if len(end) == 0 {
						//else increase middle
						middle += string(innersomechar)
					}
				}
			}
			break
		}else if somechar=='|'{
			return false, "", "", ""
		}
		//appending to the begin char
		begin += string(somechar)
	}
	if len(end) == 0 || len(begin) == 0 {
		return false, "", "", ""
	}
	return true, begin, middle, end
}

/*

This method is for identifiying groups from a regular expressions.
It is will return two lists, The first list contains identified
groups so far, each entry entry will look like the following:

    <somescope>|<number>

Here the somescope variable refers to the scope to be used, e.g constant.numeric
and the number is the number of the group within the regex.

Please note that this method is made to be called kinda-recursively. The second list
the levels are as follows:
is the list of groups in a group level. for instance given the regex (A(B)(C)(D(E))))
Level 1 -  (A(B)(C)(D(E)))
Level 2 - (B), (C), (D(E))
Level 3 - (E)

*/
func getgroups(currentregex string, originalregex string, groupcount int, scopecontainer *list.List, nextlayer *list.List) (*list.List, *list.List) {

	var matched bool
	var scope string

	if currentregex!=""{
        //fmt.Println("X---X")
        fmt.Println("curregex:",currentregex)
		matched, scope = retrievescopefromcapturegroup(currentregex, false)
        fmt.Println("matched:",matched)
        //fmt.Println("X---X")
	}
	if matched {
		groupcount += 1
		scopecontainer.PushBack(scope + "|" + strconv.Itoa(groupcount))
		return scopecontainer, nextlayer
	} else {

		count := 0
		regexlength := len(currentregex)
		stack := Stack{}

        hacked := false
        pos := strings.Index(currentregex,"(")
        for ;pos!= -1 && pos!=0 && currentregex[pos-1]=='\\';{
            hacked = true
            nextpos := strings.Index(currentregex[pos+1:],"(")
            if nextpos == -1{
                break
            }else{
                pos += 1+nextpos
            }
        }

        if pos!=-1{
            count+=1
            fmt.Println("start at pos: ",pos)
            for innerindex:=pos+1; innerindex<regexlength; innerindex++{
                innercurrcharacter := string(currentregex[innerindex])
                if innercurrcharacter=="("{
                    //found brace inner group, start by checking if it's not escaped
                    if innerindex-1<0 || currentregex[innerindex-1]!='\\'{
                        //it is not escaped
                        count +=1
                        stack.Push(innercurrcharacter)
                        //fmt.Println(innercurrcharacter,count) //debug
                    }else{
                        stack.Push(innercurrcharacter)
                    }
                }else if innercurrcharacter==")"{
                    if innerindex+1<regexlength{
                        //still within bounds of regex, that is, there is a next char
                        if currentregex[innerindex+1]=='*' || currentregex[innerindex+1]=='+' || currentregex[innerindex+1]=='?'{
                            //do decrease count, push it in
                            count -= 1

                            //TODO: Neeed to check if the only captured thing is the (*,?,+)'ed thing because if it is then we need to change pos to something further
                            if count!=0{
                                stack.Push(innercurrcharacter)
                            }
                        }else{
                            count -= 1
                            if count!=0{
                                stack.Push(innercurrcharacter)
                            }
                        }
                    }else{
                        count-=1;
                    }
                }else{
                    stack.Push(innercurrcharacter)
                }
                if count==0{
                    //the contents of the stack are the group elements

                    biggest := ""
                    for {
                        head := stack.Pop()
                        if head == nil {
                            break
                        }
                        biggest = head.(string) + biggest
                    }

                    //fmt.Println("X---X")
                    fmt.Println("group: ",biggest)
                    //trying to see if group can be matched
                    matched, scope = retrievescopefromcapturegroup(biggest, false)
                    fmt.Println("matched:",matched)
                    //fmt.Println("X---X")

                    if matched {
                            groupcount += 1
                            scopecontainer.PushBack(scope + "|" + strconv.Itoa(groupcount))
                    }
                    if !matched {
                        groupcount += 1
                        nextlayer.PushFront(biggest)
                        fmt.Println("added ff to next layer:",biggest)
                    }
                    if hacked{
                        currentregex = ""
                        hacked = false
                    }
                    if len(biggest) < regexlength {
                        if len(currentregex)>0{
                            scopecontainer, nextlayer = getgroups(currentregex[innerindex+1:], originalregex, groupcount, scopecontainer, nextlayer)
                        }
                    }
                    if nextlayer.Len() != 0 {
                        for it := nextlayer.Back(); it != nil; it = it.Prev() {
                            nextlayer.Remove(it)
                            itvalue := it.Value.(string)
                            scopecontainer, nextlayer = getgroups(itvalue, originalregex, groupcount, scopecontainer, nextlayer)
                        }
                    }
                    break
                }
            }
        }
	}
	return scopecontainer, nextlayer
}

/*

Inefficient method for retrieving scope of regex
*/
func retrievescopefromcapturegroup(capturedregex string, activate bool) (bool, string) {

	if capturedregex!=""{
		if activate==true {
			capturedregex = capturedregex[1 : len(capturedregex)-1]
		}
		for ritem := repoitems.Front(); ritem != nil; ritem = ritem.Next() {

			if repository.Getregex(ritem.Value.(*repository.Repoitem)) == capturedregex {
				tmpscope := repository.GetScope(ritem.Value.(*repository.Repoitem))
				if tmpscope != defaultscope {
					return true, tmpscope
				}
			}
		}
	}
	return false, ""
}

/*
Method for determining if strings starts and ends with round braces
*/
func startandendwithrb(somestring string) bool{
	return strings.HasPrefix(somestring,"(") && strings.HasSuffix(somestring,")")
}<|endoftext|>


<commit_before>/*
Copyright 2018 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 merge_test

import (
	"fmt"
	"reflect"
	"testing"

	"sigs.k8s.io/structured-merge-diff/fieldpath"
	"sigs.k8s.io/structured-merge-diff/merge"
	"sigs.k8s.io/structured-merge-diff/typed"
)

// State of the current test in terms of live object. One can check at
// any time that Live and Managers match the expectations.
type State struct {
	Live     *typed.TypedValue
	Parser   *typed.ParseableType
	Managers fieldpath.ManagedFields
	Updater  *merge.Updater
}

func (s *State) checkInit() error {
	if s.Live == nil {
		obj, err := s.Parser.New()
		if err != nil {
			return fmt.Errorf("failed to create new empty object: %v", err)
		}
		s.Live = &obj
	}
	return nil
}

// Update the current state with the passed in object
func (s *State) Update(obj typed.YAMLObject, manager string) error {
	if err := s.checkInit(); err != nil {
		return err
	}
	tv, err := s.Parser.FromYAML(obj)
	managers, err := s.Updater.Update(*s.Live, tv, s.Managers, manager)
	if err != nil {
		return err
	}
	s.Live = &tv
	s.Managers = managers

	return nil
}

// Apply the passed in object to the current state
func (s *State) Apply(obj typed.YAMLObject, manager string, force bool) error {
	if err := s.checkInit(); err != nil {
		return err
	}
	tv, err := s.Parser.FromYAML(obj)
	if err != nil {
		return err
	}
	new, managers, err := s.Updater.Apply(*s.Live, tv, s.Managers, manager, force)
	if err != nil {
		return err
	}
	s.Live = &new
	s.Managers = managers

	return nil
}

// CompareLive takes a YAML string and returns the comparison with the
// current live object or an error.
func (s *State) CompareLive(obj typed.YAMLObject) (*typed.Comparison, error) {
	if err := s.checkInit(); err != nil {
		return nil, err
	}
	tv, err := s.Parser.FromYAML(obj)
	if err != nil {
		return nil, err
	}
	return s.Live.Compare(tv)
}

// dummyConverter doesn't convert, it just returns the same exact object no matter what.
type dummyConverter struct{}

// Convert returns the object given in input, not doing any conversion.
func (dummyConverter) Convert(v typed.TypedValue, version fieldpath.APIVersion) (typed.TypedValue, error) {
	return v, nil
}

// Operation is a step that will run when building a table-driven test.
type Operation interface {
	run(*State) error
}

// Apply is a type of operation. It is a non-forced apply run by a
// manager with a given object. Since non-forced apply operation can
// conflict, the user can specify the expected conflicts. If conflicts
// don't match, an error will occur.
type Apply struct {
	Manager   string
	Object    typed.YAMLObject
	Conflicts merge.Conflicts
}

var _ Operation = &Apply{}

func (a Apply) run(state *State) error {
	err := state.Apply(a.Object, a.Manager, false)
	if (err != nil || a.Conflicts != nil) && !reflect.DeepEqual(err, a.Conflicts) {
		return fmt.Errorf("expected conflicts: %v, got %v", a.Conflicts, err)
	}
	return nil

}

// ForceApply is a type of operation. It is a forced-apply run by a
// manager with a given object. Any error will be returned.
type ForceApply struct {
	Manager string
	Object  typed.YAMLObject
}

var _ Operation = &ForceApply{}

func (f ForceApply) run(state *State) error {
	return state.Apply(f.Object, f.Manager, true)
}

// Update is a type of operation. It is a controller type of
// update. Errors are passed along.
type Update struct {
	Manager string
	Object  typed.YAMLObject
}

var _ Operation = &Update{}

func (u Update) run(state *State) error {
	return state.Update(u.Object, u.Manager)
}

// TestCase is the list of operations that need to be run, as well as
// the object/managedfields as they are supposed to look like after all
// the operations have been successfully performed. If Object/Managed is
// not specified, then the comparison is not performed (any object or
// managed field will pass). Any error (conflicts aside) happen while
// running the operation, that error will be returned right away.
type TestCase struct {
	// Ops is the list of operations to run sequentially
	Ops []Operation
	// Object, if not empty, is the object as it's expected to
	// be after all the operations are run.
	Object typed.YAMLObject
	// Managed, if not nil, is the ManagedFields as expected
	// after all operations are run.
	Managed fieldpath.ManagedFields
}

// Test runs the test-case using the given parser.
func (tc TestCase) Test(parser *typed.ParseableType) error {
	state := State{
		Updater: &merge.Updater{Converter: &dummyConverter{}},
		Parser:  parser,
	}
	// We currently don't have any test that converts, we can take
	// care of that later.
	for i, ops := range tc.Ops {
		err := ops.run(&state)
		if err != nil {
			return fmt.Errorf("failed operation %d: %v", i, err)
		}
	}

	// If LastObject was specified, compare it with LiveState
	if tc.Object != typed.YAMLObject("") {
		comparison, err := state.CompareLive(tc.Object)
		if err != nil {
			return fmt.Errorf("failed to compare live with config: %v", err)
		}
		if !comparison.IsSame() {
			return fmt.Errorf("expected live and config to be the same: %v", comparison)
		}
	}

	if tc.Managed != nil {
		if diff := state.Managers.Difference(tc.Managed); len(diff) != 0 {
			return fmt.Errorf("expected Managers to be %v, got %v", tc.Managed, state.Managers)
		}
	}

	return nil
}

// TestExample shows how to use the test framework
func TestExample(t *testing.T) {
	parser, err := typed.NewParser(`types:
- name: lists
  struct:
    fields:
    - name: list
      type:
        list:
          elementType:
            scalar: string
          elementRelationship: associative`)
	if err != nil {
		t.Fatalf("Failed to create parser: %v", err)
	}

	tc := TestCase{
		Ops: []Operation{
			Apply{
				Manager: "default",
				Object: `
list:
- a
- b
- c`,
			},
			Apply{
				Manager: "default",
				Object: `
list:
- a
- b
- c
- d`,
			},
		},
		Object: `list:
- a
- b
- c
- d`,
	}

	if err := tc.Test(parser.Type("lists")); err != nil {
		t.Fatalf("Test failed: %v", err)
	}
}
<commit_msg>Drop the example tests, we have enough examples<commit_after>/*
Copyright 2018 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 merge_test

import (
	"fmt"
	"reflect"

	"sigs.k8s.io/structured-merge-diff/fieldpath"
	"sigs.k8s.io/structured-merge-diff/merge"
	"sigs.k8s.io/structured-merge-diff/typed"
)

// State of the current test in terms of live object. One can check at
// any time that Live and Managers match the expectations.
type State struct {
	Live     *typed.TypedValue
	Parser   *typed.ParseableType
	Managers fieldpath.ManagedFields
	Updater  *merge.Updater
}

func (s *State) checkInit() error {
	if s.Live == nil {
		obj, err := s.Parser.New()
		if err != nil {
			return fmt.Errorf("failed to create new empty object: %v", err)
		}
		s.Live = &obj
	}
	return nil
}

// Update the current state with the passed in object
func (s *State) Update(obj typed.YAMLObject, manager string) error {
	if err := s.checkInit(); err != nil {
		return err
	}
	tv, err := s.Parser.FromYAML(obj)
	managers, err := s.Updater.Update(*s.Live, tv, s.Managers, manager)
	if err != nil {
		return err
	}
	s.Live = &tv
	s.Managers = managers

	return nil
}

// Apply the passed in object to the current state
func (s *State) Apply(obj typed.YAMLObject, manager string, force bool) error {
	if err := s.checkInit(); err != nil {
		return err
	}
	tv, err := s.Parser.FromYAML(obj)
	if err != nil {
		return err
	}
	new, managers, err := s.Updater.Apply(*s.Live, tv, s.Managers, manager, force)
	if err != nil {
		return err
	}
	s.Live = &new
	s.Managers = managers

	return nil
}

// CompareLive takes a YAML string and returns the comparison with the
// current live object or an error.
func (s *State) CompareLive(obj typed.YAMLObject) (*typed.Comparison, error) {
	if err := s.checkInit(); err != nil {
		return nil, err
	}
	tv, err := s.Parser.FromYAML(obj)
	if err != nil {
		return nil, err
	}
	return s.Live.Compare(tv)
}

// dummyConverter doesn't convert, it just returns the same exact object no matter what.
type dummyConverter struct{}

// Convert returns the object given in input, not doing any conversion.
func (dummyConverter) Convert(v typed.TypedValue, version fieldpath.APIVersion) (typed.TypedValue, error) {
	return v, nil
}

// Operation is a step that will run when building a table-driven test.
type Operation interface {
	run(*State) error
}

// Apply is a type of operation. It is a non-forced apply run by a
// manager with a given object. Since non-forced apply operation can
// conflict, the user can specify the expected conflicts. If conflicts
// don't match, an error will occur.
type Apply struct {
	Manager   string
	Object    typed.YAMLObject
	Conflicts merge.Conflicts
}

var _ Operation = &Apply{}

func (a Apply) run(state *State) error {
	err := state.Apply(a.Object, a.Manager, false)
	if (err != nil || a.Conflicts != nil) && !reflect.DeepEqual(err, a.Conflicts) {
		return fmt.Errorf("expected conflicts: %v, got %v", a.Conflicts, err)
	}
	return nil

}

// ForceApply is a type of operation. It is a forced-apply run by a
// manager with a given object. Any error will be returned.
type ForceApply struct {
	Manager string
	Object  typed.YAMLObject
}

var _ Operation = &ForceApply{}

func (f ForceApply) run(state *State) error {
	return state.Apply(f.Object, f.Manager, true)
}

// Update is a type of operation. It is a controller type of
// update. Errors are passed along.
type Update struct {
	Manager string
	Object  typed.YAMLObject
}

var _ Operation = &Update{}

func (u Update) run(state *State) error {
	return state.Update(u.Object, u.Manager)
}

// TestCase is the list of operations that need to be run, as well as
// the object/managedfields as they are supposed to look like after all
// the operations have been successfully performed. If Object/Managed is
// not specified, then the comparison is not performed (any object or
// managed field will pass). Any error (conflicts aside) happen while
// running the operation, that error will be returned right away.
type TestCase struct {
	// Ops is the list of operations to run sequentially
	Ops []Operation
	// Object, if not empty, is the object as it's expected to
	// be after all the operations are run.
	Object typed.YAMLObject
	// Managed, if not nil, is the ManagedFields as expected
	// after all operations are run.
	Managed fieldpath.ManagedFields
}

// Test runs the test-case using the given parser.
func (tc TestCase) Test(parser *typed.ParseableType) error {
	state := State{
		Updater: &merge.Updater{Converter: &dummyConverter{}},
		Parser:  parser,
	}
	// We currently don't have any test that converts, we can take
	// care of that later.
	for i, ops := range tc.Ops {
		err := ops.run(&state)
		if err != nil {
			return fmt.Errorf("failed operation %d: %v", i, err)
		}
	}

	// If LastObject was specified, compare it with LiveState
	if tc.Object != typed.YAMLObject("") {
		comparison, err := state.CompareLive(tc.Object)
		if err != nil {
			return fmt.Errorf("failed to compare live with config: %v", err)
		}
		if !comparison.IsSame() {
			return fmt.Errorf("expected live and config to be the same: %v", comparison)
		}
	}

	if tc.Managed != nil {
		if diff := state.Managers.Difference(tc.Managed); len(diff) != 0 {
			return fmt.Errorf("expected Managers to be %v, got %v", tc.Managed, state.Managers)
		}
	}

	return nil
}
<|endoftext|>