<commit_before>/*
Copyright 2014 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 versioning

import (
	"io"

	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// NewDefaultingCodecForScheme is a convenience method for callers that are using a scheme.
func NewDefaultingCodecForScheme(
	// TODO: I should be a scheme interface?
	scheme *runtime.Scheme,
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
) runtime.Codec {
	return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion, scheme.Name())
}

// NewCodec takes objects in their internal versions and converts them to external versions before
// serializing them. It assumes the serializer provided to it only deals with external versions.
// This class is also a serializer, but is generally used with a specific version.
func NewCodec(
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	convertor runtime.ObjectConvertor,
	creater runtime.ObjectCreater,
	typer runtime.ObjectTyper,
	defaulter runtime.ObjectDefaulter,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
	originalSchemeName string,
) runtime.Codec {
	internal := &codec{
		encoder:   encoder,
		decoder:   decoder,
		convertor: convertor,
		creater:   creater,
		typer:     typer,
		defaulter: defaulter,

		encodeVersion: encodeVersion,
		decodeVersion: decodeVersion,

		originalSchemeName: originalSchemeName,
	}
	return internal
}

type codec struct {
	encoder   runtime.Encoder
	decoder   runtime.Decoder
	convertor runtime.ObjectConvertor
	creater   runtime.ObjectCreater
	typer     runtime.ObjectTyper
	defaulter runtime.ObjectDefaulter

	encodeVersion runtime.GroupVersioner
	decodeVersion runtime.GroupVersioner

	// originalSchemeName is optional, but when filled in it holds the name of the scheme from which this codec originates
	originalSchemeName string
}

// Decode attempts a decode of the object, then tries to convert it to the internal version. If into is provided and the decoding is
// successful, the returned runtime.Object will be the value passed as into. Note that this may bypass conversion if you pass an
// into that matches the serialized version.
func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
	versioned, isVersioned := into.(*runtime.VersionedObjects)
	if isVersioned {
		into = versioned.Last()
	}

	obj, gvk, err := c.decoder.Decode(data, defaultGVK, into)
	if err != nil {
		return nil, gvk, err
	}

	if d, ok := obj.(runtime.NestedObjectDecoder); ok {
		if err := d.DecodeNestedObjects(DirectDecoder{c.decoder}); err != nil {
			return nil, gvk, err
		}
	}

	// if we specify a target, use generic conversion.
	if into != nil {
		if into == obj {
			if isVersioned {
				return versioned, gvk, nil
			}
			return into, gvk, nil
		}

		// perform defaulting if requested
		if c.defaulter != nil {
			// create a copy to ensure defaulting is not applied to the original versioned objects
			if isVersioned {
				versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
			}
			c.defaulter.Default(obj)
		} else {
			if isVersioned {
				versioned.Objects = []runtime.Object{obj}
			}
		}

		if err := c.convertor.Convert(obj, into, c.decodeVersion); err != nil {
			return nil, gvk, err
		}

		if isVersioned {
			versioned.Objects = append(versioned.Objects, into)
			return versioned, gvk, nil
		}
		return into, gvk, nil
	}

	// Convert if needed.
	if isVersioned {
		// create a copy, because ConvertToVersion does not guarantee non-mutation of objects
		versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
	}

	// perform defaulting if requested
	if c.defaulter != nil {
		c.defaulter.Default(obj)
	}

	out, err := c.convertor.ConvertToVersion(obj, c.decodeVersion)
	if err != nil {
		return nil, gvk, err
	}
	if isVersioned {
		if versioned.Last() != out {
			versioned.Objects = append(versioned.Objects, out)
		}
		return versioned, gvk, nil
	}
	return out, gvk, nil
}

// Encode ensures the provided object is output in the appropriate group and version, invoking
// conversion if necessary. Unversioned objects (according to the ObjectTyper) are output as is.
func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
	switch obj := obj.(type) {
	case *runtime.Unknown:
		return c.encoder.Encode(obj, w)
	case runtime.Unstructured:
		// An unstructured list can contain objects of multiple group version kinds. don't short-circuit just
		// because the top-level type matches our desired destination type. actually send the object to the converter
		// to give it a chance to convert the list items if needed.
		if _, ok := obj.(*unstructured.UnstructuredList); !ok {
			// avoid conversion roundtrip if GVK is the right one already or is empty (yes, this is a hack, but the old behaviour we rely on in kubectl)
			objGVK := obj.GetObjectKind().GroupVersionKind()
			if len(objGVK.Version) == 0 {
				return c.encoder.Encode(obj, w)
			}
			targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK})
			if !ok {
				return runtime.NewNotRegisteredGVKErrForTarget(c.originalSchemeName, objGVK, c.encodeVersion)
			}
			if targetGVK == objGVK {
				return c.encoder.Encode(obj, w)
			}
		}
	}

	gvks, isUnversioned, err := c.typer.ObjectKinds(obj)
	if err != nil {
		return err
	}

	if c.encodeVersion == nil || isUnversioned {
		if e, ok := obj.(runtime.NestedObjectEncoder); ok {
			if err := e.EncodeNestedObjects(DirectEncoder{Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
				return err
			}
		}
		objectKind := obj.GetObjectKind()
		old := objectKind.GroupVersionKind()
		objectKind.SetGroupVersionKind(gvks[0])
		err = c.encoder.Encode(obj, w)
		objectKind.SetGroupVersionKind(old)
		return err
	}

	// Perform a conversion if necessary
	objectKind := obj.GetObjectKind()
	old := objectKind.GroupVersionKind()
	out, err := c.convertor.ConvertToVersion(obj, c.encodeVersion)
	if err != nil {
		return err
	}

	if e, ok := out.(runtime.NestedObjectEncoder); ok {
		if err := e.EncodeNestedObjects(DirectEncoder{Version: c.encodeVersion, Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
			return err
		}
	}

	// Conversion is responsible for setting the proper group, version, and kind onto the outgoing object
	err = c.encoder.Encode(out, w)
	// restore the old GVK, in case conversion returned the same object
	objectKind.SetGroupVersionKind(old)
	return err
}

// DirectEncoder serializes an object and ensures the GVK is set.
type DirectEncoder struct {
	Version runtime.GroupVersioner
	runtime.Encoder
	runtime.ObjectTyper
}

// Encode does not do conversion. It sets the gvk during serialization.
func (e DirectEncoder) Encode(obj runtime.Object, stream io.Writer) error {
	gvks, _, err := e.ObjectTyper.ObjectKinds(obj)
	if err != nil {
		if runtime.IsNotRegisteredError(err) {
			return e.Encoder.Encode(obj, stream)
		}
		return err
	}
	kind := obj.GetObjectKind()
	oldGVK := kind.GroupVersionKind()
	gvk := gvks[0]
	if e.Version != nil {
		preferredGVK, ok := e.Version.KindForGroupVersionKinds(gvks)
		if ok {
			gvk = preferredGVK
		}
	}
	kind.SetGroupVersionKind(gvk)
	err = e.Encoder.Encode(obj, stream)
	kind.SetGroupVersionKind(oldGVK)
	return err
}

// DirectDecoder clears the group version kind of a deserialized object.
type DirectDecoder struct {
	runtime.Decoder
}

// Decode does not do conversion. It removes the gvk during deserialization.
func (d DirectDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
	obj, gvk, err := d.Decoder.Decode(data, defaults, into)
	if obj != nil {
		kind := obj.GetObjectKind()
		// clearing the gvk is just a convention of a codec
		kind.SetGroupVersionKind(schema.GroupVersionKind{})
	}
	return obj, gvk, err
}
<commit_msg>Avoid short-circuiting conversion when decoding into opinionated unstructured objects<commit_after>/*
Copyright 2014 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 versioning

import (
	"io"
	"reflect"

	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// NewDefaultingCodecForScheme is a convenience method for callers that are using a scheme.
func NewDefaultingCodecForScheme(
	// TODO: I should be a scheme interface?
	scheme *runtime.Scheme,
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
) runtime.Codec {
	return NewCodec(encoder, decoder, runtime.UnsafeObjectConvertor(scheme), scheme, scheme, scheme, encodeVersion, decodeVersion, scheme.Name())
}

// NewCodec takes objects in their internal versions and converts them to external versions before
// serializing them. It assumes the serializer provided to it only deals with external versions.
// This class is also a serializer, but is generally used with a specific version.
func NewCodec(
	encoder runtime.Encoder,
	decoder runtime.Decoder,
	convertor runtime.ObjectConvertor,
	creater runtime.ObjectCreater,
	typer runtime.ObjectTyper,
	defaulter runtime.ObjectDefaulter,
	encodeVersion runtime.GroupVersioner,
	decodeVersion runtime.GroupVersioner,
	originalSchemeName string,
) runtime.Codec {
	internal := &codec{
		encoder:   encoder,
		decoder:   decoder,
		convertor: convertor,
		creater:   creater,
		typer:     typer,
		defaulter: defaulter,

		encodeVersion: encodeVersion,
		decodeVersion: decodeVersion,

		originalSchemeName: originalSchemeName,
	}
	return internal
}

type codec struct {
	encoder   runtime.Encoder
	decoder   runtime.Decoder
	convertor runtime.ObjectConvertor
	creater   runtime.ObjectCreater
	typer     runtime.ObjectTyper
	defaulter runtime.ObjectDefaulter

	encodeVersion runtime.GroupVersioner
	decodeVersion runtime.GroupVersioner

	// originalSchemeName is optional, but when filled in it holds the name of the scheme from which this codec originates
	originalSchemeName string
}

// Decode attempts a decode of the object, then tries to convert it to the internal version. If into is provided and the decoding is
// successful, the returned runtime.Object will be the value passed as into. Note that this may bypass conversion if you pass an
// into that matches the serialized version.
func (c *codec) Decode(data []byte, defaultGVK *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
	versioned, isVersioned := into.(*runtime.VersionedObjects)
	if isVersioned {
		into = versioned.Last()
	}

	// If the into object is unstructured and expresses an opinion about its group/version,
	// create a new instance of the type so we always exercise the conversion path (skips short-circuiting on `into == obj`)
	decodeInto := into
	if into != nil {
		if _, ok := into.(runtime.Unstructured); ok && !into.GetObjectKind().GroupVersionKind().GroupVersion().Empty() {
			decodeInto = reflect.New(reflect.TypeOf(into).Elem()).Interface().(runtime.Object)
		}
	}

	obj, gvk, err := c.decoder.Decode(data, defaultGVK, decodeInto)
	if err != nil {
		return nil, gvk, err
	}

	if d, ok := obj.(runtime.NestedObjectDecoder); ok {
		if err := d.DecodeNestedObjects(DirectDecoder{c.decoder}); err != nil {
			return nil, gvk, err
		}
	}

	// if we specify a target, use generic conversion.
	if into != nil {
		if into == obj {
			if isVersioned {
				return versioned, gvk, nil
			}
			return into, gvk, nil
		}

		// perform defaulting if requested
		if c.defaulter != nil {
			// create a copy to ensure defaulting is not applied to the original versioned objects
			if isVersioned {
				versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
			}
			c.defaulter.Default(obj)
		} else {
			if isVersioned {
				versioned.Objects = []runtime.Object{obj}
			}
		}

		if err := c.convertor.Convert(obj, into, c.decodeVersion); err != nil {
			return nil, gvk, err
		}

		if isVersioned {
			versioned.Objects = append(versioned.Objects, into)
			return versioned, gvk, nil
		}
		return into, gvk, nil
	}

	// Convert if needed.
	if isVersioned {
		// create a copy, because ConvertToVersion does not guarantee non-mutation of objects
		versioned.Objects = []runtime.Object{obj.DeepCopyObject()}
	}

	// perform defaulting if requested
	if c.defaulter != nil {
		c.defaulter.Default(obj)
	}

	out, err := c.convertor.ConvertToVersion(obj, c.decodeVersion)
	if err != nil {
		return nil, gvk, err
	}
	if isVersioned {
		if versioned.Last() != out {
			versioned.Objects = append(versioned.Objects, out)
		}
		return versioned, gvk, nil
	}
	return out, gvk, nil
}

// Encode ensures the provided object is output in the appropriate group and version, invoking
// conversion if necessary. Unversioned objects (according to the ObjectTyper) are output as is.
func (c *codec) Encode(obj runtime.Object, w io.Writer) error {
	switch obj := obj.(type) {
	case *runtime.Unknown:
		return c.encoder.Encode(obj, w)
	case runtime.Unstructured:
		// An unstructured list can contain objects of multiple group version kinds. don't short-circuit just
		// because the top-level type matches our desired destination type. actually send the object to the converter
		// to give it a chance to convert the list items if needed.
		if _, ok := obj.(*unstructured.UnstructuredList); !ok {
			// avoid conversion roundtrip if GVK is the right one already or is empty (yes, this is a hack, but the old behaviour we rely on in kubectl)
			objGVK := obj.GetObjectKind().GroupVersionKind()
			if len(objGVK.Version) == 0 {
				return c.encoder.Encode(obj, w)
			}
			targetGVK, ok := c.encodeVersion.KindForGroupVersionKinds([]schema.GroupVersionKind{objGVK})
			if !ok {
				return runtime.NewNotRegisteredGVKErrForTarget(c.originalSchemeName, objGVK, c.encodeVersion)
			}
			if targetGVK == objGVK {
				return c.encoder.Encode(obj, w)
			}
		}
	}

	gvks, isUnversioned, err := c.typer.ObjectKinds(obj)
	if err != nil {
		return err
	}

	if c.encodeVersion == nil || isUnversioned {
		if e, ok := obj.(runtime.NestedObjectEncoder); ok {
			if err := e.EncodeNestedObjects(DirectEncoder{Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
				return err
			}
		}
		objectKind := obj.GetObjectKind()
		old := objectKind.GroupVersionKind()
		objectKind.SetGroupVersionKind(gvks[0])
		err = c.encoder.Encode(obj, w)
		objectKind.SetGroupVersionKind(old)
		return err
	}

	// Perform a conversion if necessary
	objectKind := obj.GetObjectKind()
	old := objectKind.GroupVersionKind()
	out, err := c.convertor.ConvertToVersion(obj, c.encodeVersion)
	if err != nil {
		return err
	}

	if e, ok := out.(runtime.NestedObjectEncoder); ok {
		if err := e.EncodeNestedObjects(DirectEncoder{Version: c.encodeVersion, Encoder: c.encoder, ObjectTyper: c.typer}); err != nil {
			return err
		}
	}

	// Conversion is responsible for setting the proper group, version, and kind onto the outgoing object
	err = c.encoder.Encode(out, w)
	// restore the old GVK, in case conversion returned the same object
	objectKind.SetGroupVersionKind(old)
	return err
}

// DirectEncoder serializes an object and ensures the GVK is set.
type DirectEncoder struct {
	Version runtime.GroupVersioner
	runtime.Encoder
	runtime.ObjectTyper
}

// Encode does not do conversion. It sets the gvk during serialization.
func (e DirectEncoder) Encode(obj runtime.Object, stream io.Writer) error {
	gvks, _, err := e.ObjectTyper.ObjectKinds(obj)
	if err != nil {
		if runtime.IsNotRegisteredError(err) {
			return e.Encoder.Encode(obj, stream)
		}
		return err
	}
	kind := obj.GetObjectKind()
	oldGVK := kind.GroupVersionKind()
	gvk := gvks[0]
	if e.Version != nil {
		preferredGVK, ok := e.Version.KindForGroupVersionKinds(gvks)
		if ok {
			gvk = preferredGVK
		}
	}
	kind.SetGroupVersionKind(gvk)
	err = e.Encoder.Encode(obj, stream)
	kind.SetGroupVersionKind(oldGVK)
	return err
}

// DirectDecoder clears the group version kind of a deserialized object.
type DirectDecoder struct {
	runtime.Decoder
}

// Decode does not do conversion. It removes the gvk during deserialization.
func (d DirectDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
	obj, gvk, err := d.Decoder.Decode(data, defaults, into)
	if obj != nil {
		kind := obj.GetObjectKind()
		// clearing the gvk is just a convention of a codec
		kind.SetGroupVersionKind(schema.GroupVersionKind{})
	}
	return obj, gvk, err
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 agent

import (
	"os"
	"os/signal"
	"syscall"

	"github.com/redhat-cip/skydive/agent"
	"github.com/redhat-cip/skydive/config"
	"github.com/redhat-cip/skydive/logging"

	"github.com/spf13/cobra"
)

var Agent = &cobra.Command{
	Use:          "agent",
	Short:        "Skydive agent",
	Long:         "Skydive agent",
	SilenceUsage: true,
	Run: func(cmd *cobra.Command, args []string) {
		logging.GetLogger().Notice("Skydive Agent starting...")
		agent := agent.NewAgent()
		agent.Start()

		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
		<-ch

		agent.Stop()

		logging.GetLogger().Notice("Skydive Agent stopped.")
	},
}

func init() {
	Agent.Flags().String("listen", "127.0.0.1:8081", "address and port for the agent API")
	config.GetConfig().BindPFlag("agent.listen", Agent.Flags().Lookup("listen"))

	Agent.Flags().String("ovsdb", "127.0.0.1:6400", "ovsdb connection")
	config.GetConfig().BindPFlag("ovs.ovsdb", Agent.Flags().Lookup("ovsdb"))

	Agent.Flags().String("graph-backend", "memory", "graph backend")
	config.GetConfig().BindPFlag("graph.backend", Agent.Flags().Lookup("graph-backend"))

	Agent.Flags().String("gremlin", "127.0.0.1:8182", "gremlin server")
	config.GetConfig().BindPFlag("graph.gremlin", Agent.Flags().Lookup("gremlin"))

	Agent.Flags().String("sflow-listen", "127.0.0.1:6345", "listen parameter for the sflow agent")
	config.GetConfig().BindPFlag("sflow.listen", Agent.Flags().Lookup("sflow-listen"))

	Agent.Flags().Int("flowtable-expire", 10, "expiration time for flowtable entries")
	config.GetConfig().BindPFlag("agent.flowtable_expire", Agent.Flags().Lookup("flowtable-expire"))
}
<commit_msg>Remove agent gremlin graph backend param since it's always in-memory<commit_after>/*
 * Copyright (C) 2015 Red Hat, Inc.
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 agent

import (
	"os"
	"os/signal"
	"syscall"

	"github.com/redhat-cip/skydive/agent"
	"github.com/redhat-cip/skydive/config"
	"github.com/redhat-cip/skydive/logging"

	"github.com/spf13/cobra"
)

var Agent = &cobra.Command{
	Use:          "agent",
	Short:        "Skydive agent",
	Long:         "Skydive agent",
	SilenceUsage: true,
	Run: func(cmd *cobra.Command, args []string) {
		logging.GetLogger().Notice("Skydive Agent starting...")
		agent := agent.NewAgent()
		agent.Start()

		ch := make(chan os.Signal)
		signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
		<-ch

		agent.Stop()

		logging.GetLogger().Notice("Skydive Agent stopped.")
	},
}

func init() {
	Agent.Flags().String("listen", "127.0.0.1:8081", "address and port for the agent API")
	config.GetConfig().BindPFlag("agent.listen", Agent.Flags().Lookup("listen"))

	Agent.Flags().String("ovsdb", "127.0.0.1:6400", "ovsdb connection")
	config.GetConfig().BindPFlag("ovs.ovsdb", Agent.Flags().Lookup("ovsdb"))

	Agent.Flags().String("sflow-listen", "127.0.0.1:6345", "listen parameter for the sflow agent")
	config.GetConfig().BindPFlag("sflow.listen", Agent.Flags().Lookup("sflow-listen"))

	Agent.Flags().Int("flowtable-expire", 10, "expiration time for flowtable entries")
	config.GetConfig().BindPFlag("agent.flowtable_expire", Agent.Flags().Lookup("flowtable-expire"))
}
<|endoftext|>


<commit_before>/*
 * MinIO Cloud Storage, (C) 2015, 2016, 2017 MinIO, Inc.
 *
 * 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 cmd

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/minio/minio/cmd/crypto"
	xhttp "github.com/minio/minio/cmd/http"
	"github.com/minio/minio/pkg/bucket/lifecycle"
)

// Returns a hexadecimal representation of time at the
// time response is sent to the client.
func mustGetRequestID(t time.Time) string {
	return fmt.Sprintf("%X", t.UnixNano())
}

// setEventStreamHeaders to allow proxies to avoid buffering proxy responses
func setEventStreamHeaders(w http.ResponseWriter) {
	w.Header().Set(xhttp.ContentType, "text/event-stream")
	w.Header().Set(xhttp.CacheControl, "no-cache") // nginx to turn off buffering
	w.Header().Set("X-Accel-Buffering", "no")      // nginx to turn off buffering
}

// Write http common headers
func setCommonHeaders(w http.ResponseWriter) {
	// Set the "Server" http header.
	w.Header().Set(xhttp.ServerInfo, "MinIO")

	// Set `x-amz-bucket-region` only if region is set on the server
	// by default minio uses an empty region.
	if region := globalServerRegion; region != "" {
		w.Header().Set(xhttp.AmzBucketRegion, region)
	}
	w.Header().Set(xhttp.AcceptRanges, "bytes")

	// Remove sensitive information
	crypto.RemoveSensitiveHeaders(w.Header())
}

// Encodes the response headers into XML format.
func encodeResponse(response interface{}) []byte {
	var bytesBuffer bytes.Buffer
	bytesBuffer.WriteString(xml.Header)
	e := xml.NewEncoder(&bytesBuffer)
	e.Encode(response)
	return bytesBuffer.Bytes()
}

// Encodes the response headers into JSON format.
func encodeResponseJSON(response interface{}) []byte {
	var bytesBuffer bytes.Buffer
	e := json.NewEncoder(&bytesBuffer)
	e.Encode(response)
	return bytesBuffer.Bytes()
}

// Write parts count
func setPartsCountHeaders(w http.ResponseWriter, objInfo ObjectInfo) {
	if strings.Contains(objInfo.ETag, "-") && len(objInfo.Parts) > 0 {
		w.Header()[xhttp.AmzMpPartsCount] = []string{strconv.Itoa(len(objInfo.Parts))}
	}
}

// Write object header
func setObjectHeaders(w http.ResponseWriter, objInfo ObjectInfo, rs *HTTPRangeSpec, opts ObjectOptions) (err error) {
	// set common headers
	setCommonHeaders(w)

	// Set last modified time.
	lastModified := objInfo.ModTime.UTC().Format(http.TimeFormat)
	w.Header().Set(xhttp.LastModified, lastModified)

	// Set Etag if available.
	if objInfo.ETag != "" {
		w.Header()[xhttp.ETag] = []string{"\"" + objInfo.ETag + "\""}
	}

	if objInfo.ContentType != "" {
		w.Header().Set(xhttp.ContentType, objInfo.ContentType)
	}

	if objInfo.ContentEncoding != "" {
		w.Header().Set(xhttp.ContentEncoding, objInfo.ContentEncoding)
	}

	if !objInfo.Expires.IsZero() {
		w.Header().Set(xhttp.Expires, objInfo.Expires.UTC().Format(http.TimeFormat))
	}

	if globalCacheConfig.Enabled {
		w.Header().Set(xhttp.XCache, objInfo.CacheStatus.String())
		w.Header().Set(xhttp.XCacheLookup, objInfo.CacheLookupStatus.String())
	}

	// Set tag count if object has tags
	if len(objInfo.UserTags) > 0 {
		tags, _ := url.ParseQuery(objInfo.UserTags)
		if len(tags) > 0 {
			w.Header()[xhttp.AmzTagCount] = []string{strconv.Itoa(len(tags))}
		}
	}

	// Set all other user defined metadata.
	for k, v := range objInfo.UserDefined {
		if strings.HasPrefix(strings.ToLower(k), ReservedMetadataPrefixLower) {
			// Do not need to send any internal metadata
			// values to client.
			continue
		}

		// https://github.com/google/security-research/security/advisories/GHSA-76wf-9vgp-pj7w
		if equals(k, xhttp.AmzMetaUnencryptedContentLength, xhttp.AmzMetaUnencryptedContentMD5) {
			continue
		}

		var isSet bool
		for _, userMetadataPrefix := range userMetadataKeyPrefixes {
			if !strings.HasPrefix(strings.ToLower(k), strings.ToLower(userMetadataPrefix)) {
				continue
			}
			w.Header()[strings.ToLower(k)] = []string{v}
			isSet = true
			break
		}

		if !isSet {
			w.Header().Set(k, v)
		}
	}

	var start, rangeLen int64
	totalObjectSize, err := objInfo.GetActualSize()
	if err != nil {
		return err
	}

	// For providing ranged content
	start, rangeLen, err = rs.GetOffsetLength(totalObjectSize)
	if err != nil {
		return err
	}

	if rs == nil && opts.PartNumber > 0 {
		rs = partNumberToRangeSpec(objInfo, opts.PartNumber)
	}

	// Set content length.
	w.Header().Set(xhttp.ContentLength, strconv.FormatInt(rangeLen, 10))
	if rs != nil {
		contentRange := fmt.Sprintf("bytes %d-%d/%d", start, start+rangeLen-1, totalObjectSize)
		w.Header().Set(xhttp.ContentRange, contentRange)
	}

	// Set the relevant version ID as part of the response header.
	if objInfo.VersionID != "" {
		w.Header()[xhttp.AmzVersionID] = []string{objInfo.VersionID}
	}
	if objInfo.ReplicationStatus.String() != "" {
		w.Header()[xhttp.AmzBucketReplicationStatus] = []string{objInfo.ReplicationStatus.String()}
	}
	if lc, err := globalLifecycleSys.Get(objInfo.Bucket); err == nil {
		ruleID, expiryTime := lc.PredictExpiryTime(lifecycle.ObjectOpts{
			Name:         objInfo.Name,
			UserTags:     objInfo.UserTags,
			VersionID:    objInfo.VersionID,
			ModTime:      objInfo.ModTime,
			IsLatest:     objInfo.IsLatest,
			DeleteMarker: objInfo.DeleteMarker,
		})
		if !expiryTime.IsZero() {
			w.Header()[xhttp.AmzExpiration] = []string{
				fmt.Sprintf(`expiry-date="%s", rule-id="%s"`, expiryTime.Format(http.TimeFormat), ruleID),
			}
		}
		if objInfo.TransitionStatus == lifecycle.TransitionComplete {
			w.Header()[xhttp.AmzStorageClass] = []string{objInfo.StorageClass}
		}
	}

	return nil
}
<commit_msg>lifecycle:Fix args passed to determine expiry header (#11567)<commit_after>/*
 * MinIO Cloud Storage, (C) 2015, 2016, 2017 MinIO, Inc.
 *
 * 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 cmd

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"github.com/minio/minio/cmd/crypto"
	xhttp "github.com/minio/minio/cmd/http"
	"github.com/minio/minio/pkg/bucket/lifecycle"
)

// Returns a hexadecimal representation of time at the
// time response is sent to the client.
func mustGetRequestID(t time.Time) string {
	return fmt.Sprintf("%X", t.UnixNano())
}

// setEventStreamHeaders to allow proxies to avoid buffering proxy responses
func setEventStreamHeaders(w http.ResponseWriter) {
	w.Header().Set(xhttp.ContentType, "text/event-stream")
	w.Header().Set(xhttp.CacheControl, "no-cache") // nginx to turn off buffering
	w.Header().Set("X-Accel-Buffering", "no")      // nginx to turn off buffering
}

// Write http common headers
func setCommonHeaders(w http.ResponseWriter) {
	// Set the "Server" http header.
	w.Header().Set(xhttp.ServerInfo, "MinIO")

	// Set `x-amz-bucket-region` only if region is set on the server
	// by default minio uses an empty region.
	if region := globalServerRegion; region != "" {
		w.Header().Set(xhttp.AmzBucketRegion, region)
	}
	w.Header().Set(xhttp.AcceptRanges, "bytes")

	// Remove sensitive information
	crypto.RemoveSensitiveHeaders(w.Header())
}

// Encodes the response headers into XML format.
func encodeResponse(response interface{}) []byte {
	var bytesBuffer bytes.Buffer
	bytesBuffer.WriteString(xml.Header)
	e := xml.NewEncoder(&bytesBuffer)
	e.Encode(response)
	return bytesBuffer.Bytes()
}

// Encodes the response headers into JSON format.
func encodeResponseJSON(response interface{}) []byte {
	var bytesBuffer bytes.Buffer
	e := json.NewEncoder(&bytesBuffer)
	e.Encode(response)
	return bytesBuffer.Bytes()
}

// Write parts count
func setPartsCountHeaders(w http.ResponseWriter, objInfo ObjectInfo) {
	if strings.Contains(objInfo.ETag, "-") && len(objInfo.Parts) > 0 {
		w.Header()[xhttp.AmzMpPartsCount] = []string{strconv.Itoa(len(objInfo.Parts))}
	}
}

// Write object header
func setObjectHeaders(w http.ResponseWriter, objInfo ObjectInfo, rs *HTTPRangeSpec, opts ObjectOptions) (err error) {
	// set common headers
	setCommonHeaders(w)

	// Set last modified time.
	lastModified := objInfo.ModTime.UTC().Format(http.TimeFormat)
	w.Header().Set(xhttp.LastModified, lastModified)

	// Set Etag if available.
	if objInfo.ETag != "" {
		w.Header()[xhttp.ETag] = []string{"\"" + objInfo.ETag + "\""}
	}

	if objInfo.ContentType != "" {
		w.Header().Set(xhttp.ContentType, objInfo.ContentType)
	}

	if objInfo.ContentEncoding != "" {
		w.Header().Set(xhttp.ContentEncoding, objInfo.ContentEncoding)
	}

	if !objInfo.Expires.IsZero() {
		w.Header().Set(xhttp.Expires, objInfo.Expires.UTC().Format(http.TimeFormat))
	}

	if globalCacheConfig.Enabled {
		w.Header().Set(xhttp.XCache, objInfo.CacheStatus.String())
		w.Header().Set(xhttp.XCacheLookup, objInfo.CacheLookupStatus.String())
	}

	// Set tag count if object has tags
	if len(objInfo.UserTags) > 0 {
		tags, _ := url.ParseQuery(objInfo.UserTags)
		if len(tags) > 0 {
			w.Header()[xhttp.AmzTagCount] = []string{strconv.Itoa(len(tags))}
		}
	}

	// Set all other user defined metadata.
	for k, v := range objInfo.UserDefined {
		if strings.HasPrefix(strings.ToLower(k), ReservedMetadataPrefixLower) {
			// Do not need to send any internal metadata
			// values to client.
			continue
		}

		// https://github.com/google/security-research/security/advisories/GHSA-76wf-9vgp-pj7w
		if equals(k, xhttp.AmzMetaUnencryptedContentLength, xhttp.AmzMetaUnencryptedContentMD5) {
			continue
		}

		var isSet bool
		for _, userMetadataPrefix := range userMetadataKeyPrefixes {
			if !strings.HasPrefix(strings.ToLower(k), strings.ToLower(userMetadataPrefix)) {
				continue
			}
			w.Header()[strings.ToLower(k)] = []string{v}
			isSet = true
			break
		}

		if !isSet {
			w.Header().Set(k, v)
		}
	}

	var start, rangeLen int64
	totalObjectSize, err := objInfo.GetActualSize()
	if err != nil {
		return err
	}

	// For providing ranged content
	start, rangeLen, err = rs.GetOffsetLength(totalObjectSize)
	if err != nil {
		return err
	}

	if rs == nil && opts.PartNumber > 0 {
		rs = partNumberToRangeSpec(objInfo, opts.PartNumber)
	}

	// Set content length.
	w.Header().Set(xhttp.ContentLength, strconv.FormatInt(rangeLen, 10))
	if rs != nil {
		contentRange := fmt.Sprintf("bytes %d-%d/%d", start, start+rangeLen-1, totalObjectSize)
		w.Header().Set(xhttp.ContentRange, contentRange)
	}

	// Set the relevant version ID as part of the response header.
	if objInfo.VersionID != "" {
		w.Header()[xhttp.AmzVersionID] = []string{objInfo.VersionID}
	}
	if objInfo.ReplicationStatus.String() != "" {
		w.Header()[xhttp.AmzBucketReplicationStatus] = []string{objInfo.ReplicationStatus.String()}
	}
	if lc, err := globalLifecycleSys.Get(objInfo.Bucket); err == nil {
		ruleID, expiryTime := lc.PredictExpiryTime(lifecycle.ObjectOpts{
			Name:             objInfo.Name,
			UserTags:         objInfo.UserTags,
			VersionID:        objInfo.VersionID,
			ModTime:          objInfo.ModTime,
			IsLatest:         objInfo.IsLatest,
			DeleteMarker:     objInfo.DeleteMarker,
			SuccessorModTime: objInfo.SuccessorModTime,
		})
		if !expiryTime.IsZero() {
			w.Header()[xhttp.AmzExpiration] = []string{
				fmt.Sprintf(`expiry-date="%s", rule-id="%s"`, expiryTime.Format(http.TimeFormat), ruleID),
			}
		}
		if objInfo.TransitionStatus == lifecycle.TransitionComplete {
			w.Header()[xhttp.AmzStorageClass] = []string{objInfo.StorageClass}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"borg"
	"borg/store"
	"flag"
	"log"
	"os"
)

// Flags
var (
	id         *string = flag.String("i", "", "Node id to use.")
	listenAddr *string = flag.String("l", ":8040", "The address to bind to.")
	attachAddr *string = flag.String("a", "", "The address to bind to.")
)

// Globals
var (
	logger *log.Logger = log.New(os.Stderr, nil, "borgd: ", log.Lok)
)

func main() {
	flag.Parse()
	s := store.New(logger)
	b := borg.New(*id, *listenAddr, s, logger)

	//adds := make(chan store.Event)
	adds := s.Watch("/service", store.Add)
	go func() {
		for ev := range adds {
			logger.Logf("oh, %s/%s has appeared", ev.Path, ev.Body)
		}
	}()

	if *attachAddr == "" {
		b.Init()
	} else {
		b.Join(*attachAddr)
	}
	b.RunForever()
}
<commit_msg>rudimentary process management<commit_after>package main

import (
	"borg"
	"borg/store"
	"flag"
	"log"
	"os"
	"strings"
)

// Flags
var (
	id         *string = flag.String("i", "", "Node id to use.")
	listenAddr *string = flag.String("l", ":8040", "The address to bind to.")
	attachAddr *string = flag.String("a", "", "The address to bind to.")
)

// Globals
var (
	logger *log.Logger = log.New(os.Stderr, nil, "borgd: ", log.Lok)
)

func acquire(path string) {
	// TODO acquire a lock
	// N.B. this should block
}

func release(path string) {
	// TODO release lock
}

func run(s *store.Store, path string) {
	for {
		acquire(path)
		cmd, ok := s.Lookup(path)
		if !ok {
			return
		}

		// TODO better tokenization (e.g. quoted strings, variables)
		args := strings.Split(cmd, " ", -1)
		logger.Logf("starting %s", cmd)
		pid, err := os.ForkExec(args[0], args, nil, "/", nil)
		if err != nil {
			logger.Logf("fatal: %v", err)
			return
		}
		logger.Logf("started process %d", pid)
		w, err := os.Wait(pid, 0)
		if err != nil {
			logger.Logf("wtf: %v", err)
			return
		}
		logger.Logf("process %d exited with %v", pid, w)
		release(path)
	}
}

func main() {
	flag.Parse()
	s := store.New(logger)
	b := borg.New(*id, *listenAddr, s, logger)

	//adds := make(chan store.Event)
	adds := s.Watch("/service", store.Add)
	go func() {
		for ev := range adds {
			path := ev.Path + "/" + ev.Body
			logger.Logf("oh, %s has appeared", path)
			go run(s, path)
		}
	}()

	if *attachAddr == "" {
		b.Init()
	} else {
		b.Join(*attachAddr)
	}
	b.RunForever()
}
<|endoftext|>


<commit_before>// Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.

package cmd

import (
	"strings"
	"testing"

	"github.com/wso2/wum-uc/constant"
	"github.com/wso2/wum-uc/util"
)

func TestGetUpdateName(t *testing.T) {
	updateNumber := "0001"
	kernelVersion := "4.4.0"
	updateDescriptor := util.UpdateDescriptor{
		Update_number: updateNumber,
		Platform_version: kernelVersion,
	}
	updateName := getUpdateName(&updateDescriptor, constant.UPDATE_NAME_PREFIX)
	expected := constant.UPDATE_NAME_PREFIX + "-" + kernelVersion + "-" + updateNumber
	if updateName != expected {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, updateName)
	}
}

func TestAddToRootNode(t *testing.T) {
	//Add new file
	isDir := false
	hash := "hash1"
	root := createNewNode()
	AddToRootNode(&root, strings.Split("a/b/c.jar", "/"), isDir, hash)

	nodeName := "a"
	nodeA, exists := root.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}
	if nodeA.isDir == false {
		t.Errorf("Test failed, expected: %d, actual: %d", false, nodeA.isDir)
	}

	nodeName = "b"
	nodeB, exists := nodeA.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}
	if nodeB.isDir == false {
		t.Errorf("Test failed, expected: %d, actual: %d", false, nodeB.isDir)
	}

	nodeName = "c.jar"
	nodeC, exists := nodeB.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}

	if nodeC.md5Hash != hash {
		t.Errorf("Test failed, expected: %d, actual: %d", hash, nodeC.md5Hash)
	}

	if nodeC.isDir != isDir {
		t.Errorf("Test failed, expected: %d, actual: %d", hash, nodeC.md5Hash)
	}

	//Add new file
	isDir = false
	hash = "hash2"
	AddToRootNode(&root, strings.Split("a/b/d.jar", "/"), isDir, hash)
	nodeName = "a"
	nodeA, exists = root.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}
	if nodeA.isDir == false {
		t.Errorf("Test failed, expected: %d, actual: %d", false, nodeA.isDir)
	}

	nodeName = "b"
	nodeB, exists = nodeA.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}
	if nodeB.isDir == false {
		t.Errorf("Test failed, expected: %d, actual: %d", false, nodeB.isDir)
	}

	nodeName = "d.jar"
	nodeD, exists := nodeB.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}

	if nodeD.md5Hash != hash {
		t.Errorf("Test failed, expected: %d, actual: %d", hash, nodeD.md5Hash)
	}

	if nodeD.isDir != isDir {
		t.Errorf("Test failed, expected: %d, actual: %d", hash, nodeD.md5Hash)
	}

}

func TestPathExists(t *testing.T) {
	root := createNewNode()
	AddToRootNode(&root, strings.Split("a/b/c.jar", "/"), false, "hash1")

	exists := PathExists(&root, "a/b/c.jar", false)
	expected := true
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}

	exists = PathExists(&root, "a/b", true)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}

	exists = PathExists(&root, "a", true)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}

	exists = PathExists(&root, "a/b/d.jar", false)
	expected = false
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}

	AddToRootNode(&root, strings.Split("a/b/d.jar", "/"), false, "hash2")

	exists = PathExists(&root, "a/b/d.jar", false)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}

	exists = PathExists(&root, "a/d.jar", false)
	expected = false
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}

	AddToRootNode(&root, strings.Split("a/d.jar", "/"), false, "hash3")

	exists = PathExists(&root, "a/d.jar", false)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}

	exists = PathExists(&root, "d.jar", false)
	expected = false
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}

	AddToRootNode(&root, strings.Split("d.jar", "/"), false, "hash3")

	exists = PathExists(&root, "d.jar", false)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %d, actual: %d", expected, exists)
	}
}
<commit_msg>Change incorrect verbs<commit_after>// Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.

package cmd

import (
	"strings"
	"testing"

	"github.com/wso2/wum-uc/constant"
	"github.com/wso2/wum-uc/util"
)

func TestGetUpdateName(t *testing.T) {
	updateNumber := "0001"
	kernelVersion := "4.4.0"
	updateDescriptor := util.UpdateDescriptor{
		Update_number: updateNumber,
		Platform_version: kernelVersion,
	}
	updateName := getUpdateName(&updateDescriptor, constant.UPDATE_NAME_PREFIX)
	expected := constant.UPDATE_NAME_PREFIX + "-" + kernelVersion + "-" + updateNumber
	if updateName != expected {
		t.Errorf("Test failed, expected: %s, actual: %s", expected, updateName)
	}
}

func TestAddToRootNode(t *testing.T) {
	//Add new file
	isDir := false
	hash := "hash1"
	root := createNewNode()
	AddToRootNode(&root, strings.Split("a/b/c.jar", "/"), isDir, hash)

	nodeName := "a"
	nodeA, exists := root.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}
	if nodeA.isDir == false {
		t.Errorf("Test failed, expected: %v, actual: %v", false, nodeA.isDir)
	}

	nodeName = "b"
	nodeB, exists := nodeA.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}
	if nodeB.isDir == false {
		t.Errorf("Test failed, expected: %v, actual: %v", false, nodeB.isDir)
	}

	nodeName = "c.jar"
	nodeC, exists := nodeB.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}

	if nodeC.md5Hash != hash {
		t.Errorf("Test failed, expected: %v, actual: %v", hash, nodeC.md5Hash)
	}

	if nodeC.isDir != isDir {
		t.Errorf("Test failed, expected: %v, actual: %v", hash, nodeC.md5Hash)
	}

	//Add new file
	isDir = false
	hash = "hash2"
	AddToRootNode(&root, strings.Split("a/b/d.jar", "/"), isDir, hash)
	nodeName = "a"
	nodeA, exists = root.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}
	if nodeA.isDir == false {
		t.Errorf("Test failed, expected: %v, actual: %v", false, nodeA.isDir)
	}

	nodeName = "b"
	nodeB, exists = nodeA.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}
	if nodeB.isDir == false {
		t.Errorf("Test failed, expected: %v, actual: %v", false, nodeB.isDir)
	}

	nodeName = "d.jar"
	nodeD, exists := nodeB.childNodes[nodeName]
	if !exists {
		t.Errorf("Test failed, node '%v' not found.", nodeName)
	}

	if nodeD.md5Hash != hash {
		t.Errorf("Test failed, expected: %v, actual: %v", hash, nodeD.md5Hash)
	}

	if nodeD.isDir != isDir {
		t.Errorf("Test failed, expected: %v, actual: %v", hash, nodeD.md5Hash)
	}

}

func TestPathExists(t *testing.T) {
	root := createNewNode()
	AddToRootNode(&root, strings.Split("a/b/c.jar", "/"), false, "hash1")

	exists := PathExists(&root, "a/b/c.jar", false)
	expected := true
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}

	exists = PathExists(&root, "a/b", true)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}

	exists = PathExists(&root, "a", true)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}

	exists = PathExists(&root, "a/b/d.jar", false)
	expected = false
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}

	AddToRootNode(&root, strings.Split("a/b/d.jar", "/"), false, "hash2")

	exists = PathExists(&root, "a/b/d.jar", false)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}

	exists = PathExists(&root, "a/d.jar", false)
	expected = false
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}

	AddToRootNode(&root, strings.Split("a/d.jar", "/"), false, "hash3")

	exists = PathExists(&root, "a/d.jar", false)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}

	exists = PathExists(&root, "d.jar", false)
	expected = false
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}

	AddToRootNode(&root, strings.Split("d.jar", "/"), false, "hash3")

	exists = PathExists(&root, "d.jar", false)
	expected = true
	if expected != exists {
		t.Errorf("Test failed, expected: %v, actual: %v", expected, exists)
	}
}
<|endoftext|>


<commit_before>// Copyright 2019 CUE 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 cmd

import (
	"fmt"
	"math/rand"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/spf13/cobra"
)

func newModCmd(c *Command) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "mod <cmd> [arguments]",
		Short: "module maintenace",
		Long: `
`,
		RunE: mkRunE(c, func(cmd *Command, args []string) error {
			stderr := cmd.Stderr()
			if len(args) == 0 {
				fmt.Fprintln(stderr, "mod must be run as one of its subcommands")
			} else {
				fmt.Fprintf(stderr, "get must be run as one of its subcommands: unknown subcommand %q\n", args[0])
			}
			fmt.Fprintln(stderr, "Run 'cue help mod' for known subcommands.")
			os.Exit(1) // TODO: get rid of this
			return nil
		}),
	}

	cmd.AddCommand(newModInitCmd(c))
	return cmd
}

func newModInitCmd(c *Command) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "init [module]",
		Short: "initialize new module in current director",
		Long: `Init initializes a cue.mod directory in the current directory,
in effect creating a new module rooted at the current directory.
The cue.mod directory must not already exist.
A legacy cue.mod file in the current directory is moved
to the new subdirectory.

A module name is optional, but if it is not given a packages
within the module cannot imported another package defined
in the module.
`,
		RunE: mkRunE(c, runModInit),
	}

	cmd.Flags().BoolP(string(flagForce), "f", false, "force moving old-style cue.mod file")

	return cmd
}

func runModInit(cmd *Command, args []string) (err error) {
	defer func() {
		if err != nil {
			// TODO: Refactor Cobra usage to do something more principled
			fmt.Fprintln(cmd.OutOrStderr(), err)
			os.Exit(1)
		}
	}()

	module := ""
	if len(args) > 0 {
		if len(args) != 1 {
			return fmt.Errorf("too many arguments")
		}
		module := args[0]
		u, err := url.Parse("https://" + module)
		if err != nil {
			return fmt.Errorf("invalid module name: %v", module)
		}
		if h := u.Hostname(); !strings.Contains(h, ".") {
			return fmt.Errorf("invalid host name %q", h)
		}
	}

	cwd, err := os.Getwd()
	if err != nil {
		return err
	}

	mod := filepath.Join(cwd, "cue.mod")

	info, err := os.Stat(mod)

	// Detect old setups and backport it if requested.
	if err == nil && !info.IsDir() {
		// This path backports
		if !flagForce.Bool(cmd) {
			return fmt.Errorf("detected old-style config file; use --force to upgrade")
		}
		return backport(mod, cwd)
	}

	if err == nil {
		return fmt.Errorf("cue.mod directory already exists")
	}

	err = os.Mkdir(mod, 0755)
	if err != nil && !os.IsExist(err) {
		return err
	}

	f, err := os.Create(filepath.Join(mod, "module.cue"))
	if err != nil {
		return err
	}
	defer f.Close()

	// Set module even if it is empty, making it easier for users to fill it in.
	_, err = fmt.Fprintf(f, "module: %q\n", module)

	if err = os.Mkdir(filepath.Join(mod, "usr"), 0755); err != nil {
		return err
	}
	if err = os.Mkdir(filepath.Join(mod, "pkg"), 0755); err != nil {
		return err
	}

	return err
}

// backport backports an old cue.mod setup to a new one.
func backport(mod, cwd string) error {
	tmp := filepath.Join(cwd, fmt.Sprintf("_%x_cue.mod", rand.Int()))
	err := os.Rename(mod, tmp)
	if err != nil {
		return err
	}

	err = os.Mkdir(filepath.Join(cwd, "cue.mod"), 0755)
	if err != nil {
		os.Rename(tmp, mod)
		return err
	}

	err = os.Rename(tmp, filepath.Join(cwd, "cue.mod", "module.cue"))
	if err != nil {
		return err
	}

	err = os.Rename(filepath.Join(cwd, "pkg"), filepath.Join(cwd, "cue.mod", "gen"))
	if err != nil && !os.IsNotExist(err) {
		return err
	}

	if err = os.Mkdir(filepath.Join(mod, "usr"), 0755); err != nil {
		return err
	}
	if err = os.Mkdir(filepath.Join(mod, "pkg"), 0755); err != nil {
		return err
	}

	return nil
}
<commit_msg>cmd/cue/cmd: correct module output<commit_after>// Copyright 2019 CUE 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 cmd

import (
	"fmt"
	"math/rand"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"github.com/spf13/cobra"
)

func newModCmd(c *Command) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "mod <cmd> [arguments]",
		Short: "module maintenace",
		Long: `
`,
		RunE: mkRunE(c, func(cmd *Command, args []string) error {
			stderr := cmd.Stderr()
			if len(args) == 0 {
				fmt.Fprintln(stderr, "mod must be run as one of its subcommands")
			} else {
				fmt.Fprintf(stderr, "get must be run as one of its subcommands: unknown subcommand %q\n", args[0])
			}
			fmt.Fprintln(stderr, "Run 'cue help mod' for known subcommands.")
			os.Exit(1) // TODO: get rid of this
			return nil
		}),
	}

	cmd.AddCommand(newModInitCmd(c))
	return cmd
}

func newModInitCmd(c *Command) *cobra.Command {
	cmd := &cobra.Command{
		Use:   "init [module]",
		Short: "initialize new module in current director",
		Long: `Init initializes a cue.mod directory in the current directory,
in effect creating a new module rooted at the current directory.
The cue.mod directory must not already exist.
A legacy cue.mod file in the current directory is moved
to the new subdirectory.

A module name is optional, but if it is not given a packages
within the module cannot imported another package defined
in the module.
`,
		RunE: mkRunE(c, runModInit),
	}

	cmd.Flags().BoolP(string(flagForce), "f", false, "force moving old-style cue.mod file")

	return cmd
}

func runModInit(cmd *Command, args []string) (err error) {
	defer func() {
		if err != nil {
			// TODO: Refactor Cobra usage to do something more principled
			fmt.Fprintln(cmd.OutOrStderr(), err)
			os.Exit(1)
		}
	}()

	module := ""
	if len(args) > 0 {
		if len(args) != 1 {
			return fmt.Errorf("too many arguments")
		}
		module = args[0]
		u, err := url.Parse("https://" + module)
		if err != nil {
			return fmt.Errorf("invalid module name: %v", module)
		}
		if h := u.Hostname(); !strings.Contains(h, ".") {
			return fmt.Errorf("invalid host name %q", h)
		}
	}

	cwd, err := os.Getwd()
	if err != nil {
		return err
	}

	mod := filepath.Join(cwd, "cue.mod")

	info, err := os.Stat(mod)

	// Detect old setups and backport it if requested.
	if err == nil && !info.IsDir() {
		// This path backports
		if !flagForce.Bool(cmd) {
			return fmt.Errorf("detected old-style config file; use --force to upgrade")
		}
		return backport(mod, cwd)
	}

	if err == nil {
		return fmt.Errorf("cue.mod directory already exists")
	}

	err = os.Mkdir(mod, 0755)
	if err != nil && !os.IsExist(err) {
		return err
	}

	f, err := os.Create(filepath.Join(mod, "module.cue"))
	if err != nil {
		return err
	}
	defer f.Close()

	// Set module even if it is empty, making it easier for users to fill it in.
	_, err = fmt.Fprintf(f, "module: %q\n", module)

	if err = os.Mkdir(filepath.Join(mod, "usr"), 0755); err != nil {
		return err
	}
	if err = os.Mkdir(filepath.Join(mod, "pkg"), 0755); err != nil {
		return err
	}

	return err
}

// backport backports an old cue.mod setup to a new one.
func backport(mod, cwd string) error {
	tmp := filepath.Join(cwd, fmt.Sprintf("_%x_cue.mod", rand.Int()))
	err := os.Rename(mod, tmp)
	if err != nil {
		return err
	}

	err = os.Mkdir(filepath.Join(cwd, "cue.mod"), 0755)
	if err != nil {
		os.Rename(tmp, mod)
		return err
	}

	err = os.Rename(tmp, filepath.Join(cwd, "cue.mod", "module.cue"))
	if err != nil {
		return err
	}

	err = os.Rename(filepath.Join(cwd, "pkg"), filepath.Join(cwd, "cue.mod", "gen"))
	if err != nil && !os.IsNotExist(err) {
		return err
	}

	if err = os.Mkdir(filepath.Join(mod, "usr"), 0755); err != nil {
		return err
	}
	if err = os.Mkdir(filepath.Join(mod, "pkg"), 0755); err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements access to gccgo-generated export data.

package main

import (
	"debug/elf"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"code.google.com/p/go.tools/go/gccgoimporter"
	"code.google.com/p/go.tools/go/importer"
	"code.google.com/p/go.tools/go/types"
)

func init() {
	incpaths := []string{"/"}

	// importer for default gccgo
	var inst gccgoimporter.GccgoInstallation
	inst.InitFromDriver("gccgo")
	register("gccgo", inst.GetImporter(incpaths))

	// importer for gccgo using condensed export format (experimental)
	register("gccgo-new", getNewImporter(append(append(incpaths, inst.SearchPaths()...), ".")))
}

// This function is an adjusted variant of gccgoimporter.GccgoInstallation.GetImporter.
func getNewImporter(searchpaths []string) types.Importer {
	return func(imports map[string]*types.Package, pkgpath string) (pkg *types.Package, err error) {
		if pkgpath == "unsafe" {
			return types.Unsafe, nil
		}

		fpath, err := findExportFile(searchpaths, pkgpath)
		if err != nil {
			return
		}

		reader, closer, err := openExportFile(fpath)
		if err != nil {
			return nil, err
		}
		defer closer.Close()

		// TODO(gri) At the moment we just read the entire file.
		// We should change importer.ImportData to take an io.Reader instead.
		data, err := ioutil.ReadAll(reader)
		if err != nil && err != io.EOF {
			return nil, err
		}

		return importer.ImportData(packages, data)
	}
}

// This function is an exact copy of gccgoimporter.findExportFile.
func findExportFile(searchpaths []string, pkgpath string) (string, error) {
	for _, spath := range searchpaths {
		pkgfullpath := filepath.Join(spath, pkgpath)
		pkgdir, name := filepath.Split(pkgfullpath)

		for _, filepath := range [...]string{
			pkgfullpath,
			pkgfullpath + ".gox",
			pkgdir + "lib" + name + ".so",
			pkgdir + "lib" + name + ".a",
			pkgfullpath + ".o",
		} {
			println("trying", filepath)
			fi, err := os.Stat(filepath)
			if err == nil && !fi.IsDir() {
				return filepath, nil
			}
		}
	}

	return "", fmt.Errorf("%s: could not find export data (tried %s)", pkgpath, strings.Join(searchpaths, ":"))
}

// This function is an exact copy of gccgoimporter.openExportFile.
func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
	f, err := os.Open(fpath)
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			f.Close()
		}
	}()
	closer = f

	var magic [4]byte
	_, err = f.ReadAt(magic[:], 0)
	if err != nil {
		return
	}

	if string(magic[:]) == "v1;\n" {
		// Raw export data.
		reader = f
		return
	}

	ef, err := elf.NewFile(f)
	if err != nil {
		return
	}

	sec := ef.Section(".go_export")
	if sec == nil {
		err = fmt.Errorf("%s: .go_export section not found", fpath)
		return
	}

	reader = sec.Open()
	return
}
<commit_msg>go.tools/cmd/godex: remove spurious println<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file implements access to gccgo-generated export data.

package main

import (
	"debug/elf"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"code.google.com/p/go.tools/go/gccgoimporter"
	"code.google.com/p/go.tools/go/importer"
	"code.google.com/p/go.tools/go/types"
)

func init() {
	incpaths := []string{"/"}

	// importer for default gccgo
	var inst gccgoimporter.GccgoInstallation
	inst.InitFromDriver("gccgo")
	register("gccgo", inst.GetImporter(incpaths))

	// importer for gccgo using condensed export format (experimental)
	register("gccgo-new", getNewImporter(append(append(incpaths, inst.SearchPaths()...), ".")))
}

// This function is an adjusted variant of gccgoimporter.GccgoInstallation.GetImporter.
func getNewImporter(searchpaths []string) types.Importer {
	return func(imports map[string]*types.Package, pkgpath string) (pkg *types.Package, err error) {
		if pkgpath == "unsafe" {
			return types.Unsafe, nil
		}

		fpath, err := findExportFile(searchpaths, pkgpath)
		if err != nil {
			return
		}

		reader, closer, err := openExportFile(fpath)
		if err != nil {
			return nil, err
		}
		defer closer.Close()

		// TODO(gri) At the moment we just read the entire file.
		// We should change importer.ImportData to take an io.Reader instead.
		data, err := ioutil.ReadAll(reader)
		if err != nil && err != io.EOF {
			return nil, err
		}

		return importer.ImportData(packages, data)
	}
}

// This function is an exact copy of gccgoimporter.findExportFile.
func findExportFile(searchpaths []string, pkgpath string) (string, error) {
	for _, spath := range searchpaths {
		pkgfullpath := filepath.Join(spath, pkgpath)
		pkgdir, name := filepath.Split(pkgfullpath)

		for _, filepath := range [...]string{
			pkgfullpath,
			pkgfullpath + ".gox",
			pkgdir + "lib" + name + ".so",
			pkgdir + "lib" + name + ".a",
			pkgfullpath + ".o",
		} {
			fi, err := os.Stat(filepath)
			if err == nil && !fi.IsDir() {
				return filepath, nil
			}
		}
	}

	return "", fmt.Errorf("%s: could not find export data (tried %s)", pkgpath, strings.Join(searchpaths, ":"))
}

// This function is an exact copy of gccgoimporter.openExportFile.
func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err error) {
	f, err := os.Open(fpath)
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			f.Close()
		}
	}()
	closer = f

	var magic [4]byte
	_, err = f.ReadAt(magic[:], 0)
	if err != nil {
		return
	}

	if string(magic[:]) == "v1;\n" {
		// Raw export data.
		reader = f
		return
	}

	ef, err := elf.NewFile(f)
	if err != nil {
		return
	}

	sec := ef.Section(".go_export")
	if sec == nil {
		err = fmt.Errorf("%s: .go_export section not found", fpath)
		return
	}

	reader = sec.Open()
	return
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/bazelbuild/bazel-watcher/internal/ibazel"
	"github.com/bazelbuild/bazel-watcher/internal/ibazel/log"
)

var Version = "Development"

var overrideableStartupFlags []string = []string{
	"--bazelrc",
	"--home_rc",
	"--nohome_rc",
	"--output_base",
}

var overrideableBazelFlags []string = []string{
	"--action_env",
	"--announce_rc",
	"--aspects",
	"--build_tag_filters=",
	"--build_tests_only",
	"--compilation_mode",
	"--compile_one_dependency",
	"--config=",
	"--copt=",
	"--curses=no",
	"--cxxopt",
	"-c",
	"--define=",
	"--dynamic_mode=",
	"--features=",
	"--flaky_test_attempts=",
	"--keep_going",
	"-k",
	"--nocache_test_results",
	"--nostamp",
	"--output_groups=",
	"--override_repository=",
	"--platforms",
	"--repo_env",
	"--runs_per_test=",
	"--run_under=",
	"--show_result=",
	"--stamp",
	"--strategy=",
	"--test_arg=",
	"--test_env=",
	"--test_filter=",
	"--test_output=",
	"--test_tag_filters=",
	"--test_timeout=",
	// Custom Starlark build settings
	// https://docs.bazel.build/versions/master/skylark/config.html#using-build-settings-on-the-command-line
	"--//",
	"--no//",
}

var debounceDuration = flag.Duration("debounce", 100*time.Millisecond, "Debounce duration")
var logToFile = flag.String("log_to_file", "-", "Log iBazel stderr to a file instead of os.Stderr")

func usage() {
	fmt.Fprintf(os.Stderr, `iBazel - Version %s

A file watcher for Bazel. Whenever a source file used in a specified
target changes, run, build, or test the specified targets.

Usage:

ibazel build|test|run [flags] targets...

Example:

ibazel test //path/to/my/testing:target
ibazel test //path/to/my/testing/targets/...
ibazel run //path/to/my/runnable:target -- --arguments --for_your=binary
ibazel build //path/to/my/buildable:target

Supported Bazel startup flags:
  %s

Supported Bazel command flags:
  %s

To add to this list, edit
https://github.com/bazelbuild/bazel-watcher/blob/master/ibazel/main.go

iBazel flags:
`, Version, strings.Join(overrideableStartupFlags, "\n  "), strings.Join(overrideableBazelFlags, "\n  "))
	flag.PrintDefaults()
}

func isOverrideable(arg string, overrideables []string) bool {
	for _, overrideable := range overrideables {
		if strings.HasPrefix(arg, overrideable) {
			return true
		}
	}
	return false
}

func isOverrideableStartupFlag(arg string) bool {
	return isOverrideable(arg, overrideableStartupFlags)
}

func isOverrideableBazelFlag(arg string) bool {
	return isOverrideable(arg, overrideableBazelFlags)
}

func parseArgs(in []string) (targets, startupArgs, bazelArgs, args []string) {
	afterDoubleDash := false
	for _, arg := range in {
		if afterDoubleDash {
			// Put it in the extra args section if we are after a double dash.
			args = append(args, arg)
		} else {
			// Check to see if this token is a double dash.
			if arg == "--" {
				afterDoubleDash = true
				continue
			}

			// Check to see if this startup option or command flag is on the bazel whitelist of flags.
			if isOverrideableStartupFlag(arg) {
				startupArgs = append(startupArgs, arg)
			} else if isOverrideableBazelFlag(arg) {
				bazelArgs = append(bazelArgs, arg)
			} else {
				// If none of those things then it's probably a target.
				targets = append(targets, arg)
			}
		}
	}
	return
}

// main entrypoint for IBazel.
func main() {
	flag.Usage = usage
	flag.Parse()

	if *logToFile != "-" {
		var err error
		logFile, err := os.OpenFile(*logToFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			panic(err)
		}
		log.SetLogger(log.NewWriterLogger(logFile))
	}

	if len(flag.Args()) < 2 {
		usage()
		return
	}

	command := strings.ToLower(flag.Args()[0])
	args := flag.Args()[1:]
	os.Setenv("IBAZEL", "true")

	i, err := ibazel.New(Version)
	if err != nil {
		log.Fatalf("Error creating iBazel: %s", err)
	}
	i.SetDebounceDuration(*debounceDuration)
	defer i.Cleanup()

	// increase the number of files that this process can
	// have open.
	err = setUlimit()
	if err != nil {
		log.Errorf("error setting higher file descriptor limit for this process: %v", err)
	}

	handle(i, command, args)
}

func handle(i *ibazel.IBazel, command string, args []string) {
	targets, startupArgs, bazelArgs, args := parseArgs(args)
	i.SetStartupArgs(startupArgs)
	i.SetBazelArgs(bazelArgs)

	switch command {
	case "build":
		i.Build(targets...)
	case "test":
		i.Test(targets...)
	case "run":
		// Run only takes one target.
		i.Run(targets[0], args)
	default:
		fmt.Fprintf(os.Stderr, "Asked me to perform %q. I don't know how to do that.", command)
		usage()
		return
	}
}
<commit_msg>Adds --target_pattern_file into the iBazel proxied flags list<commit_after>// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/bazelbuild/bazel-watcher/internal/ibazel"
	"github.com/bazelbuild/bazel-watcher/internal/ibazel/log"
)

var Version = "Development"

var overrideableStartupFlags []string = []string{
	"--bazelrc",
	"--home_rc",
	"--nohome_rc",
	"--output_base",
}

var overrideableBazelFlags []string = []string{
	"--action_env",
	"--announce_rc",
	"--aspects",
	"--build_tag_filters=",
	"--build_tests_only",
	"--compilation_mode",
	"--compile_one_dependency",
	"--config=",
	"--copt=",
	"--curses=no",
	"--cxxopt",
	"-c",
	"--define=",
	"--dynamic_mode=",
	"--features=",
	"--flaky_test_attempts=",
	"--keep_going",
	"-k",
	"--nocache_test_results",
	"--nostamp",
	"--output_groups=",
	"--override_repository=",
	"--platforms",
	"--repo_env",
	"--runs_per_test=",
	"--run_under=",
	"--show_result=",
	"--stamp",
	"--strategy=",
	"--target_pattern_file=",
	"--test_arg=",
	"--test_env=",
	"--test_filter=",
	"--test_output=",
	"--test_tag_filters=",
	"--test_timeout=",
	// Custom Starlark build settings
	// https://docs.bazel.build/versions/master/skylark/config.html#using-build-settings-on-the-command-line
	"--//",
	"--no//",
}

var debounceDuration = flag.Duration("debounce", 100*time.Millisecond, "Debounce duration")
var logToFile = flag.String("log_to_file", "-", "Log iBazel stderr to a file instead of os.Stderr")

func usage() {
	fmt.Fprintf(os.Stderr, `iBazel - Version %s

A file watcher for Bazel. Whenever a source file used in a specified
target changes, run, build, or test the specified targets.

Usage:

ibazel build|test|run [flags] targets...

Example:

ibazel test //path/to/my/testing:target
ibazel test //path/to/my/testing/targets/...
ibazel run //path/to/my/runnable:target -- --arguments --for_your=binary
ibazel build //path/to/my/buildable:target

Supported Bazel startup flags:
  %s

Supported Bazel command flags:
  %s

To add to this list, edit
https://github.com/bazelbuild/bazel-watcher/blob/master/ibazel/main.go

iBazel flags:
`, Version, strings.Join(overrideableStartupFlags, "\n  "), strings.Join(overrideableBazelFlags, "\n  "))
	flag.PrintDefaults()
}

func isOverrideable(arg string, overrideables []string) bool {
	for _, overrideable := range overrideables {
		if strings.HasPrefix(arg, overrideable) {
			return true
		}
	}
	return false
}

func isOverrideableStartupFlag(arg string) bool {
	return isOverrideable(arg, overrideableStartupFlags)
}

func isOverrideableBazelFlag(arg string) bool {
	return isOverrideable(arg, overrideableBazelFlags)
}

func parseArgs(in []string) (targets, startupArgs, bazelArgs, args []string) {
	afterDoubleDash := false
	for _, arg := range in {
		if afterDoubleDash {
			// Put it in the extra args section if we are after a double dash.
			args = append(args, arg)
		} else {
			// Check to see if this token is a double dash.
			if arg == "--" {
				afterDoubleDash = true
				continue
			}

			// Check to see if this startup option or command flag is on the bazel whitelist of flags.
			if isOverrideableStartupFlag(arg) {
				startupArgs = append(startupArgs, arg)
			} else if isOverrideableBazelFlag(arg) {
				bazelArgs = append(bazelArgs, arg)
			} else {
				// If none of those things then it's probably a target.
				targets = append(targets, arg)
			}
		}
	}
	return
}

// main entrypoint for IBazel.
func main() {
	flag.Usage = usage
	flag.Parse()

	if *logToFile != "-" {
		var err error
		logFile, err := os.OpenFile(*logToFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
		if err != nil {
			panic(err)
		}
		log.SetLogger(log.NewWriterLogger(logFile))
	}

	if len(flag.Args()) < 2 {
		usage()
		return
	}

	command := strings.ToLower(flag.Args()[0])
	args := flag.Args()[1:]
	os.Setenv("IBAZEL", "true")

	i, err := ibazel.New(Version)
	if err != nil {
		log.Fatalf("Error creating iBazel: %s", err)
	}
	i.SetDebounceDuration(*debounceDuration)
	defer i.Cleanup()

	// increase the number of files that this process can
	// have open.
	err = setUlimit()
	if err != nil {
		log.Errorf("error setting higher file descriptor limit for this process: %v", err)
	}

	handle(i, command, args)
}

func handle(i *ibazel.IBazel, command string, args []string) {
	targets, startupArgs, bazelArgs, args := parseArgs(args)
	i.SetStartupArgs(startupArgs)
	i.SetBazelArgs(bazelArgs)

	switch command {
	case "build":
		i.Build(targets...)
	case "test":
		i.Test(targets...)
	case "run":
		// Run only takes one target.
		i.Run(targets[0], args)
	default:
		fmt.Fprintf(os.Stderr, "Asked me to perform %q. I don't know how to do that.", command)
		usage()
		return
	}
}
<|endoftext|>


<commit_before>// The influx command is a CLI client to InfluxDB.
package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/influxdata/influxdb/client"
	"github.com/influxdata/influxdb/cmd/influx/cli"
	"strings"
)

// These variables are populated via the Go linker.
var (
	version string
)

const (
	// defaultFormat is the default format of the results when issuing queries
	defaultFormat = "column"

	// defaultPrecision is the default timestamp format of the results when issuing queries
	defaultPrecision = "ns"

	// defaultPPS is the default points per second that the import will throttle at
	// by default it's 0, which means it will not throttle
	defaultPPS = 0
)

func init() {
	// If version is not set, make that clear.
	if version == "" {
		version = "unknown"
	}
}

func main() {
	c := cli.New(version)

	fs := flag.NewFlagSet("InfluxDB shell version "+version, flag.ExitOnError)
	fs.StringVar(&c.Host, "host", client.DefaultHost, "Influxdb host to connect to.")
	fs.IntVar(&c.Port, "port", client.DefaultPort, "Influxdb port to connect to.")
	fs.StringVar(&c.ClientConfig.UnixSocket, "socket", "", "Influxdb unix socket to connect to.")
	fs.StringVar(&c.ClientConfig.Username, "username", "", "Username to connect to the server.")
	fs.StringVar(&c.ClientConfig.Password, "password", "", `Password to connect to the server.  Leaving blank will prompt for password (--password="").`)
	fs.StringVar(&c.Database, "database", c.Database, "Database to connect to the server.")
	fs.BoolVar(&c.Ssl, "ssl", false, "Use https for connecting to cluster.")
	fs.BoolVar(&c.ClientConfig.UnsafeSsl, "unsafeSsl", false, "Set this when connecting to the cluster using https and not use SSL verification.")
	fs.StringVar(&c.Format, "format", defaultFormat, "Format specifies the format of the server responses:  json, csv, or column.")
	fs.StringVar(&c.ClientConfig.Precision, "precision", defaultPrecision, "Precision specifies the format of the timestamp:  rfc3339,h,m,s,ms,u or ns.")
	fs.StringVar(&c.ClientConfig.WriteConsistency, "consistency", "all", "Set write consistency level: any, one, quorum, or all.")
	fs.BoolVar(&c.Pretty, "pretty", false, "Turns on pretty print for the json format.")
	fs.StringVar(&c.Execute, "execute", c.Execute, "Execute command and quit.")
	fs.BoolVar(&c.ShowVersion, "version", false, "Displays the InfluxDB version.")
	fs.BoolVar(&c.Import, "import", false, "Import a previous database.")
	fs.IntVar(&c.ImporterConfig.PPS, "pps", defaultPPS, "How many points per second the import will allow.  By default it is zero and will not throttle importing.")
	fs.StringVar(&c.ImporterConfig.Path, "path", "", "path to the file to import")
	fs.BoolVar(&c.ImporterConfig.Compressed, "compressed", false, "set to true if the import file is compressed")

	// Define our own custom usage to print
	fs.Usage = func() {
		fmt.Println(`Usage of influx:
  -version
       Display the version and exit.
  -host 'host name'
       Host to connect to.
  -port 'port #'
       Port to connect to.
  -socket 'unix domain socket'
       Unix socket to connect to.
  -database 'database name'
       Database to connect to the server.
  -password 'password'
      Password to connect to the server.  Leaving blank will prompt for password (--password '').
  -username 'username'
       Username to connect to the server.
  -ssl
        Use https for requests.
  -unsafeSsl
        Set this when connecting to the cluster using https and not use SSL verification.
  -execute 'command'
       Execute command and quit.
  -format 'json|csv|column'
       Format specifies the format of the server responses:  json, csv, or column.
  -precision 'rfc3339|h|m|s|ms|u|ns'
       Precision specifies the format of the timestamp:  rfc3339, h, m, s, ms, u or ns.
  -consistency 'any|one|quorum|all'
       Set write consistency level: any, one, quorum, or all
  -pretty
       Turns on pretty print for the json format.
  -import
       Import a previous database export from file
  -pps
       How many points per second the import will allow.  By default it is zero and will not throttle importing.
  -path
       Path to file to import
  -compressed
       Set to true if the import file is compressed

Examples:

    # Use influx in a non-interactive mode to query the database "metrics" and pretty print json:
    $ influx -database 'metrics' -execute 'select * from cpu' -format 'json' -pretty

    # Connect to a specific database on startup and set database context:
    $ influx -database 'metrics' -host 'localhost' -port '8086'
`)
	}
	fs.Parse(os.Args[1:])

	argsNotParsed := fs.Args()
	if len(argsNotParsed) > 0 {
		fmt.Fprintf(os.Stderr, "unknown arguments: %s\n", strings.Join(argsNotParsed, " "))
		fs.Usage()
		os.Exit(1)
	}

	if c.ShowVersion {
		c.Version()
		os.Exit(0)
	}

	if err := c.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}
<commit_msg>Group the "strings" import with the other stdlib imports<commit_after>// The influx command is a CLI client to InfluxDB.
package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/influxdata/influxdb/client"
	"github.com/influxdata/influxdb/cmd/influx/cli"
)

// These variables are populated via the Go linker.
var (
	version string
)

const (
	// defaultFormat is the default format of the results when issuing queries
	defaultFormat = "column"

	// defaultPrecision is the default timestamp format of the results when issuing queries
	defaultPrecision = "ns"

	// defaultPPS is the default points per second that the import will throttle at
	// by default it's 0, which means it will not throttle
	defaultPPS = 0
)

func init() {
	// If version is not set, make that clear.
	if version == "" {
		version = "unknown"
	}
}

func main() {
	c := cli.New(version)

	fs := flag.NewFlagSet("InfluxDB shell version "+version, flag.ExitOnError)
	fs.StringVar(&c.Host, "host", client.DefaultHost, "Influxdb host to connect to.")
	fs.IntVar(&c.Port, "port", client.DefaultPort, "Influxdb port to connect to.")
	fs.StringVar(&c.ClientConfig.UnixSocket, "socket", "", "Influxdb unix socket to connect to.")
	fs.StringVar(&c.ClientConfig.Username, "username", "", "Username to connect to the server.")
	fs.StringVar(&c.ClientConfig.Password, "password", "", `Password to connect to the server.  Leaving blank will prompt for password (--password="").`)
	fs.StringVar(&c.Database, "database", c.Database, "Database to connect to the server.")
	fs.BoolVar(&c.Ssl, "ssl", false, "Use https for connecting to cluster.")
	fs.BoolVar(&c.ClientConfig.UnsafeSsl, "unsafeSsl", false, "Set this when connecting to the cluster using https and not use SSL verification.")
	fs.StringVar(&c.Format, "format", defaultFormat, "Format specifies the format of the server responses:  json, csv, or column.")
	fs.StringVar(&c.ClientConfig.Precision, "precision", defaultPrecision, "Precision specifies the format of the timestamp:  rfc3339,h,m,s,ms,u or ns.")
	fs.StringVar(&c.ClientConfig.WriteConsistency, "consistency", "all", "Set write consistency level: any, one, quorum, or all.")
	fs.BoolVar(&c.Pretty, "pretty", false, "Turns on pretty print for the json format.")
	fs.StringVar(&c.Execute, "execute", c.Execute, "Execute command and quit.")
	fs.BoolVar(&c.ShowVersion, "version", false, "Displays the InfluxDB version.")
	fs.BoolVar(&c.Import, "import", false, "Import a previous database.")
	fs.IntVar(&c.ImporterConfig.PPS, "pps", defaultPPS, "How many points per second the import will allow.  By default it is zero and will not throttle importing.")
	fs.StringVar(&c.ImporterConfig.Path, "path", "", "path to the file to import")
	fs.BoolVar(&c.ImporterConfig.Compressed, "compressed", false, "set to true if the import file is compressed")

	// Define our own custom usage to print
	fs.Usage = func() {
		fmt.Println(`Usage of influx:
  -version
       Display the version and exit.
  -host 'host name'
       Host to connect to.
  -port 'port #'
       Port to connect to.
  -socket 'unix domain socket'
       Unix socket to connect to.
  -database 'database name'
       Database to connect to the server.
  -password 'password'
      Password to connect to the server.  Leaving blank will prompt for password (--password '').
  -username 'username'
       Username to connect to the server.
  -ssl
        Use https for requests.
  -unsafeSsl
        Set this when connecting to the cluster using https and not use SSL verification.
  -execute 'command'
       Execute command and quit.
  -format 'json|csv|column'
       Format specifies the format of the server responses:  json, csv, or column.
  -precision 'rfc3339|h|m|s|ms|u|ns'
       Precision specifies the format of the timestamp:  rfc3339, h, m, s, ms, u or ns.
  -consistency 'any|one|quorum|all'
       Set write consistency level: any, one, quorum, or all
  -pretty
       Turns on pretty print for the json format.
  -import
       Import a previous database export from file
  -pps
       How many points per second the import will allow.  By default it is zero and will not throttle importing.
  -path
       Path to file to import
  -compressed
       Set to true if the import file is compressed

Examples:

    # Use influx in a non-interactive mode to query the database "metrics" and pretty print json:
    $ influx -database 'metrics' -execute 'select * from cpu' -format 'json' -pretty

    # Connect to a specific database on startup and set database context:
    $ influx -database 'metrics' -host 'localhost' -port '8086'
`)
	}
	fs.Parse(os.Args[1:])

	argsNotParsed := fs.Args()
	if len(argsNotParsed) > 0 {
		fmt.Fprintf(os.Stderr, "unknown arguments: %s\n", strings.Join(argsNotParsed, " "))
		fs.Usage()
		os.Exit(1)
	}

	if c.ShowVersion {
		c.Version()
		os.Exit(0)
	}

	if err := c.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"encoding/gob"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/zyedidia/micro/v2/internal/buffer"
	"github.com/zyedidia/micro/v2/internal/config"
)

func shouldContinue() bool {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("Continue [Y/n]: ")
	text, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println(err)
		return false
	}

	if len(text) <= 1 {
		// default continue
		return true
	}

	return strings.ToLower(text)[0] == 'y'
}

// CleanConfig performs cleanup in the user's configuration directory
func CleanConfig() {
	fmt.Println("Cleaning your configuration directory at", config.ConfigDir)
	fmt.Printf("Please consider backing up %s before continuing\n", config.ConfigDir)

	if !shouldContinue() {
		fmt.Println("Stopping early")
		return
	}

	// detect unused options
	var unusedOptions []string
	defaultSettings := config.DefaultAllSettings()
	for k := range config.GlobalSettings {
		if _, ok := defaultSettings[k]; !ok {
			valid := false
			for _, p := range config.Plugins {
				if strings.HasPrefix(k, p.Name+".") || k == p.Name {
					valid = true
				}
			}
			if !valid {
				unusedOptions = append(unusedOptions, k)
			}
		}
	}

	if len(unusedOptions) > 0 {
		fmt.Println("The following options are unused:")

		sort.Strings(unusedOptions)

		for _, s := range unusedOptions {
			fmt.Printf("%s (value: %v)\n", s, config.GlobalSettings[s])
		}

		fmt.Printf("These options will be removed from %s\n", filepath.Join(config.ConfigDir, "settings.json"))

		if shouldContinue() {
			for _, s := range unusedOptions {
				delete(config.GlobalSettings, s)
			}

			err := config.OverwriteSettings(filepath.Join(config.ConfigDir, "settings.json"))
			if err != nil {
				fmt.Println("Error writing settings.json file: " + err.Error())
			}

			fmt.Println("Removed unused options")
			fmt.Print("\n\n")
		}
	}

	// detect incorrectly formatted buffer/ files
	files, err := ioutil.ReadDir(filepath.Join(config.ConfigDir, "buffers"))
	if err == nil {
		var badFiles []string
		var buffer buffer.SerializedBuffer
		for _, f := range files {
			fname := filepath.Join(config.ConfigDir, "buffers", f.Name())
			file, e := os.Open(fname)

			if e == nil {
				defer file.Close()

				decoder := gob.NewDecoder(file)
				err = decoder.Decode(&buffer)

				if err != nil && f.Name() != "history" {
					badFiles = append(badFiles, fname)
				}
			}
		}

		if len(badFiles) > 0 {
			fmt.Printf("Detected %d files with an invalid format in %s\n", len(badFiles), filepath.Join(config.ConfigDir, "buffers"))
			fmt.Println("These files store cursor and undo history.")
			fmt.Printf("Removing badly formatted files in %s\n", filepath.Join(config.ConfigDir, "buffers"))

			if shouldContinue() {
				for _, f := range badFiles {
					err := os.Remove(f)
					if err != nil {
						fmt.Println(err)
						continue
					}
				}

				fmt.Println("Removed badly formatted files")
				fmt.Print("\n\n")
			}
		}
	}

	// detect plugins/ directory
	plugins := filepath.Join(config.ConfigDir, "plugins")
	if stat, err := os.Stat(plugins); err == nil && stat.IsDir() {
		fmt.Printf("Found directory %s\n", plugins)
		fmt.Printf("Plugins should now be stored in %s\n", filepath.Join(config.ConfigDir, "plug"))
		fmt.Printf("Removing %s\n", plugins)

		if shouldContinue() {
			os.RemoveAll(plugins)
		}

		fmt.Print("\n\n")
	}

	fmt.Println("Done cleaning")
}
<commit_msg>Clean default settings in micro -clean<commit_after>package main

import (
	"bufio"
	"encoding/gob"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/zyedidia/micro/v2/internal/buffer"
	"github.com/zyedidia/micro/v2/internal/config"
)

func shouldContinue() bool {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("Continue [Y/n]: ")
	text, err := reader.ReadString('\n')
	if err != nil {
		fmt.Println(err)
		return false
	}

	if len(text) <= 1 {
		// default continue
		return true
	}

	return strings.ToLower(text)[0] == 'y'
}

// CleanConfig performs cleanup in the user's configuration directory
func CleanConfig() {
	fmt.Println("Cleaning your configuration directory at", config.ConfigDir)
	fmt.Printf("Please consider backing up %s before continuing\n", config.ConfigDir)

	if !shouldContinue() {
		fmt.Println("Stopping early")
		return
	}

	fmt.Println("Cleaning default settings")
	config.WriteSettings(filepath.Join(config.ConfigDir, "settings.json"))

	// detect unused options
	var unusedOptions []string
	defaultSettings := config.DefaultAllSettings()
	for k := range config.GlobalSettings {
		if _, ok := defaultSettings[k]; !ok {
			valid := false
			for _, p := range config.Plugins {
				if strings.HasPrefix(k, p.Name+".") || k == p.Name {
					valid = true
				}
			}
			if !valid {
				unusedOptions = append(unusedOptions, k)
			}
		}
	}

	if len(unusedOptions) > 0 {
		fmt.Println("The following options are unused:")

		sort.Strings(unusedOptions)

		for _, s := range unusedOptions {
			fmt.Printf("%s (value: %v)\n", s, config.GlobalSettings[s])
		}

		fmt.Printf("These options will be removed from %s\n", filepath.Join(config.ConfigDir, "settings.json"))

		if shouldContinue() {
			for _, s := range unusedOptions {
				delete(config.GlobalSettings, s)
			}

			err := config.OverwriteSettings(filepath.Join(config.ConfigDir, "settings.json"))
			if err != nil {
				fmt.Println("Error writing settings.json file: " + err.Error())
			}

			fmt.Println("Removed unused options")
			fmt.Print("\n\n")
		}
	}

	// detect incorrectly formatted buffer/ files
	files, err := ioutil.ReadDir(filepath.Join(config.ConfigDir, "buffers"))
	if err == nil {
		var badFiles []string
		var buffer buffer.SerializedBuffer
		for _, f := range files {
			fname := filepath.Join(config.ConfigDir, "buffers", f.Name())
			file, e := os.Open(fname)

			if e == nil {
				defer file.Close()

				decoder := gob.NewDecoder(file)
				err = decoder.Decode(&buffer)

				if err != nil && f.Name() != "history" {
					badFiles = append(badFiles, fname)
				}
			}
		}

		if len(badFiles) > 0 {
			fmt.Printf("Detected %d files with an invalid format in %s\n", len(badFiles), filepath.Join(config.ConfigDir, "buffers"))
			fmt.Println("These files store cursor and undo history.")
			fmt.Printf("Removing badly formatted files in %s\n", filepath.Join(config.ConfigDir, "buffers"))

			if shouldContinue() {
				for _, f := range badFiles {
					err := os.Remove(f)
					if err != nil {
						fmt.Println(err)
						continue
					}
				}

				fmt.Println("Removed badly formatted files")
				fmt.Print("\n\n")
			}
		}
	}

	// detect plugins/ directory
	plugins := filepath.Join(config.ConfigDir, "plugins")
	if stat, err := os.Stat(plugins); err == nil && stat.IsDir() {
		fmt.Printf("Found directory %s\n", plugins)
		fmt.Printf("Plugins should now be stored in %s\n", filepath.Join(config.ConfigDir, "plug"))
		fmt.Printf("Removing %s\n", plugins)

		if shouldContinue() {
			os.RemoveAll(plugins)
		}

		fmt.Print("\n\n")
	}

	fmt.Println("Done cleaning")
}
<|endoftext|>