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

package commands

import (
	"bytes"
	"go/scanner"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"golang.org/x/tools/imports"

	"nvim-go/gb"
	"nvim-go/nvim"
)

var (
	fmtAsync  = "go#fmt#async"
	vFmtAsync interface{}
)

var options = imports.Options{
	AllErrors: true,
	Comments:  true,
	TabIndent: true,
	TabWidth:  8,
}

func init() {
	plugin.HandleCommand("Gofmt", &plugin.CommandOptions{Range: "%", Eval: "expand('%:p:h')"}, Fmt)
	plugin.HandleAutocmd("BufWritePre", &plugin.AutocmdOptions{Pattern: "*.go", Eval: "expand('%:p:h')"}, fmtOnBufWritePre)
}

func fmtOnBufWritePre(v *vim.Vim, dir string) error {
	v.Var(fmtAsync, &vFmtAsync)
	if vFmtAsync.(int64) == int64(1) {
		go Fmt(v, [2]int{0, 0}, dir)
		return nil
	} else {
		return Fmt(v, [2]int{0, 0}, dir)
	}
}

func Fmt(v *vim.Vim, r [2]int, dir string) error {
	defer gb.WithGoBuildForPath(dir)()

	var (
		b vim.Buffer
		w vim.Window
	)
	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return err
	}

	bufName, err := v.BufferName(b)

	in, err := v.BufferLines(b, 0, -1, true)
	if err != nil {
		return err
	}

	buf, err := imports.Process("", bytes.Join(in, []byte{'\n'}), &options)
	if err != nil {
		var loclist []*nvim.ErrorlistData

		if e, ok := err.(scanner.Error); ok {
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: bufName,
				LNum:     e.Pos.Line,
				Col:      e.Pos.Column,
				Text:     e.Msg,
			})
		} else if el, ok := err.(scanner.ErrorList); ok {
			for _, e := range el {
				loclist = append(loclist, &nvim.ErrorlistData{
					FileName: bufName,
					LNum:     e.Pos.Line,
					Col:      e.Pos.Column,
					Text:     e.Msg,
				})
			}
		}
		if err := nvim.SetLoclist(p, loclist); err != nil {
			return nvim.Echomsg(v, "Gofmt: %v", err)
		}
		return nvim.OpenLoclist(p, w, loclist, true)
	} else {
		nvim.CloseLoclist(v)
	}

	out := bytes.Split(bytes.TrimSuffix(buf, []byte{'\n'}), []byte{'\n'})

	return minUpdate(v, b, in, out)
}

func minUpdate(v *vim.Vim, b vim.Buffer, in [][]byte, out [][]byte) error {
	// Find matching head lines.
	n := len(out)
	if len(in) < len(out) {
		n = len(in)
	}
	head := 0
	for ; head < n; head++ {
		if !bytes.Equal(in[head], out[head]) {
			break
		}
	}

	// Nothing to do?
	if head == len(in) && head == len(out) {
		return nil
	}

	// Find matching tail lines.
	n -= head
	tail := 0
	for ; tail < n; tail++ {
		if !bytes.Equal(in[len(in)-tail-1], out[len(out)-tail-1]) {
			break
		}
	}

	// Update the buffer.
	start := head
	end := len(in) - tail
	repl := out[head : len(out)-tail]

	return v.SetBufferLines(b, start, end, true, repl)
}
<commit_msg>Fix Gofmt to get env use eval<commit_after>// Copyright 2015 Gary Burd. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package commands

import (
	"bytes"
	"go/scanner"

	"github.com/garyburd/neovim-go/vim"
	"github.com/garyburd/neovim-go/vim/plugin"
	"golang.org/x/tools/imports"

	"nvim-go/gb"
	"nvim-go/nvim"
)

var options = imports.Options{
	AllErrors: true,
	Comments:  true,
	TabIndent: true,
	TabWidth:  8,
}

func init() {
	plugin.HandleCommand("Gofmt", &plugin.CommandOptions{Eval: "expand('%:p:h')"}, Fmt)
	plugin.HandleAutocmd("BufWritePre", &plugin.AutocmdOptions{Pattern: "*.go", Eval: "[expand('%:p:h'), expand('%:p'), g:go#fmt#async]"}, fmtAutocmdBuild)
}

type onFmtEval struct {
	Cwd      string `msgpack:",array"`
	File     string
	EnvAsync int64
}

func fmtAutocmdBuild(v *vim.Vim, eval onFmtEval) error {
	if eval.EnvAsync == int64(1) {
		go Fmt(v, eval)
		return nil
	} else {
		return Fmt(v, eval)
	}
}

func Fmt(v *vim.Vim, eval onFmtEval) error {
	defer gb.WithGoBuildForPath(eval.Cwd)()

	var (
		b vim.Buffer
		w vim.Window
	)
	p := v.NewPipeline()
	p.CurrentBuffer(&b)
	p.CurrentWindow(&w)
	if err := p.Wait(); err != nil {
		return err
	}

	bufName, err := v.BufferName(b)
	if err != nil {
		return err
	}

	in, err := v.BufferLines(b, 0, -1, true)
	if err != nil {
		return err
	}

	buf, err := imports.Process("", bytes.Join(in, []byte{'\n'}), &options)
	if err != nil {
		var loclist []*nvim.ErrorlistData

		if e, ok := err.(scanner.Error); ok {
			loclist = append(loclist, &nvim.ErrorlistData{
				FileName: bufName,
				LNum:     e.Pos.Line,
				Col:      e.Pos.Column,
				Text:     e.Msg,
			})
		} else if el, ok := err.(scanner.ErrorList); ok {
			for _, e := range el {
				loclist = append(loclist, &nvim.ErrorlistData{
					FileName: bufName,
					LNum:     e.Pos.Line,
					Col:      e.Pos.Column,
					Text:     e.Msg,
				})
			}
		}
		if err := nvim.SetLoclist(p, loclist); err != nil {
			return nvim.Echomsg(v, "Gofmt: %v", err)
		}
		return nvim.OpenLoclist(p, w, loclist, true)
	} else {
		nvim.CloseLoclist(v)
	}

	out := bytes.Split(bytes.TrimSuffix(buf, []byte{'\n'}), []byte{'\n'})

	return minUpdate(v, b, in, out)
}

func minUpdate(v *vim.Vim, b vim.Buffer, in [][]byte, out [][]byte) error {
	// Find matching head lines.
	n := len(out)
	if len(in) < len(out) {
		n = len(in)
	}
	head := 0
	for ; head < n; head++ {
		if !bytes.Equal(in[head], out[head]) {
			break
		}
	}

	// Nothing to do?
	if head == len(in) && head == len(out) {
		return nil
	}

	// Find matching tail lines.
	n -= head
	tail := 0
	for ; tail < n; tail++ {
		if !bytes.Equal(in[len(in)-tail-1], out[len(out)-tail-1]) {
			break
		}
	}

	// Update the buffer.
	start := head
	end := len(in) - tail
	repl := out[head : len(out)-tail]

	return v.SetBufferLines(b, start, end, true, repl)
}
<|endoftext|>


<commit_before>package vow

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"os/exec"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
)

var errKilled = errors.New("promise has already been killed")

var (
	statusFailed     = "\r|" + red("Failed") + "     |\n"
	statusPassed     = "\r|" + green("Passed") + "     |\n"
	statusInProgress = "|" + yellow("In Progress") + "|"
)

type promise struct {
	cmdMtx sync.Mutex
	cmd    *exec.Cmd
	killed *int32
}

func newPromise(name string, args ...string) *promise {
	return &promise{
		cmd:    exec.Command(name, args...),
		killed: new(int32),
	}
}

func (p *promise) Run(w io.Writer, verbose bool) (err error) {
	if p.isKilled() {
		return errKilled
	}

	var buf bytes.Buffer
	p.cmd.Stdout = &buf
	p.cmd.Stderr = &buf

	fmt.Fprintf(
		w,
		"%s %s",
		statusInProgress,
		strings.Join(p.cmd.Args, " "),
	)

	p.cmdMtx.Lock()
	if err := p.cmd.Start(); err != nil {
		p.cmdMtx.Unlock()
		p.writeIfAlive(w, []byte(statusFailed))
		p.writeIfAlive(w, []byte(err.Error()+"\n"))
		return err
	}
	p.cmdMtx.Unlock()

	err = p.cmd.Wait()
	if err != nil {
		p.writeIfAlive(w, []byte(statusFailed))
	} else {
		p.writeIfAlive(w, []byte(statusPassed))
	}

	if verbose || err != nil {
		p.writeIfAlive(w, buf.Bytes())
	}
	return err
}

func (p *promise) writeIfAlive(w io.Writer, b []byte) {
	if p.isKilled() {
		return
	}
	w.Write([]byte(b))
}

func (p *promise) isKilled() bool {
	return atomic.LoadInt32(p.killed) == 1
}

func (p *promise) kill() {
	atomic.StoreInt32(p.killed, 1)
	p.cmdMtx.Lock()
	if p.cmd.Process != nil {
		p.cmd.Process.Signal(syscall.SIGTERM)
	}
	p.cmdMtx.Unlock()
}
<commit_msg>explicitly ignoring error when cmd is writing to Writer<commit_after>package vow

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"os/exec"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
)

var errKilled = errors.New("promise has already been killed")

var (
	statusFailed     = "\r|" + red("Failed") + "     |\n"
	statusPassed     = "\r|" + green("Passed") + "     |\n"
	statusInProgress = "|" + yellow("In Progress") + "|"
)

type promise struct {
	cmdMtx sync.Mutex
	cmd    *exec.Cmd
	killed *int32
}

func newPromise(name string, args ...string) *promise {
	return &promise{
		cmd:    exec.Command(name, args...),
		killed: new(int32),
	}
}

func (p *promise) Run(w io.Writer, verbose bool) (err error) {
	if p.isKilled() {
		return errKilled
	}

	var buf bytes.Buffer
	p.cmd.Stdout = &buf
	p.cmd.Stderr = &buf

	fmt.Fprintf(
		w,
		"%s %s",
		statusInProgress,
		strings.Join(p.cmd.Args, " "),
	)

	p.cmdMtx.Lock()
	if err := p.cmd.Start(); err != nil {
		p.cmdMtx.Unlock()
		p.writeIfAlive(w, []byte(statusFailed))
		p.writeIfAlive(w, []byte(err.Error()+"\n"))
		return err
	}
	p.cmdMtx.Unlock()

	err = p.cmd.Wait()
	if err != nil {
		p.writeIfAlive(w, []byte(statusFailed))
	} else {
		p.writeIfAlive(w, []byte(statusPassed))
	}

	if verbose || err != nil {
		p.writeIfAlive(w, buf.Bytes())
	}
	return err
}

func (p *promise) writeIfAlive(w io.Writer, b []byte) {
	if p.isKilled() {
		return
	}
	// ignoring error since there is not much we can do
	_, _ = w.Write(b)
}

func (p *promise) isKilled() bool {
	return atomic.LoadInt32(p.killed) == 1
}

func (p *promise) kill() {
	atomic.StoreInt32(p.killed, 1)
	p.cmdMtx.Lock()
	if p.cmd.Process != nil {
		p.cmd.Process.Signal(syscall.SIGTERM)
	}
	p.cmdMtx.Unlock()
}
<|endoftext|>


<commit_before>/**
 * 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 builder

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	log "github.com/sirupsen/logrus"

	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/newt/toolchain"
	"mynewt.apache.org/newt/util"
)

const CMAKELISTS_FILENAME string = "CMakeLists.txt"

func CmakeListsPath() string {
	return project.GetProject().BasePath + "/" + CMAKELISTS_FILENAME
}

func EscapeName(name string) string {
	return strings.Replace(name, "/", "_", -1)
}

func replaceBackslashes(path string) string {
	return strings.Replace(path, "\\", "/", -1)
}

func replaceBackslashesSlice(elements []string) {
	for e := range elements {
		elements[e] = replaceBackslashes(elements[e])
	}
}

func trimProjectPath(path string) string {
	proj := interfaces.GetProject()
	path = strings.TrimPrefix(path, proj.Path()+"/")
	return path
}

func trimProjectPathSlice(elements []string) {
	for e := range elements {
		elements[e] = trimProjectPath(elements[e])
	}
}

func extractIncludes(flags *[]string, includes *[]string, other *[]string) {
	for _, f := range *flags {
		if strings.HasPrefix(f, "-I") {
			*includes = append(*includes, strings.TrimPrefix(f, "-I"))
		} else {
			*other = append(*other, f)
		}
	}
}

func CmakeSourceObjectWrite(w io.Writer, cj toolchain.CompilerJob,
	includeDirs *[]string, linkFlags *[]string) {
	c := cj.Compiler

	flags := []string{}
	otherFlags := []string{}

	switch cj.CompilerType {
	case toolchain.COMPILER_TYPE_C:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
	case toolchain.COMPILER_TYPE_ASM:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().Aflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Aflags...)
	case toolchain.COMPILER_TYPE_CPP:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().CXXflags...)
		flags = append(flags, c.GetLocalCompilerInfo().CXXflags...)
	}

	*linkFlags = append(*linkFlags, c.GetCompilerInfo().Lflags...)
	*linkFlags = append(*linkFlags, c.GetLocalCompilerInfo().Lflags...)

	extractIncludes(&flags, includeDirs, &otherFlags)
	cj.Filename = trimProjectPath(cj.Filename)

	// Sort and remove duplicate flags
	otherFlags = util.SortFields(otherFlags...)

	fmt.Fprintf(w, `set_property(SOURCE %s APPEND_STRING
														PROPERTY
														COMPILE_FLAGS
														"%s")`,
		cj.Filename,
		strings.Replace(strings.Join(otherFlags, " "), "\"", "\\\\\\\"", -1))
	fmt.Fprintln(w)
}

func (b *Builder) CMakeBuildPackageWrite(w io.Writer, bpkg *BuildPackage,
	linkFlags *[]string) (*BuildPackage, error) {
	entries, err := b.collectCompileEntriesBpkg(bpkg)
	if err != nil {
		return nil, err
	}

	if len(entries) <= 0 {
		return nil, nil
	}

	otherIncludes := []string{}
	files := []string{}

	for _, s := range entries {
		filename := filepath.ToSlash(s.Filename)
		if s.Compiler.ShouldIgnoreFile(filename) {
			log.Infof("Ignoring %s because package dictates it.\n", filename)
			continue
		}

		CmakeSourceObjectWrite(w, s, &otherIncludes, linkFlags)
		s.Filename = trimProjectPath(s.Filename)
		files = append(files, s.Filename)
	}

	if len(files) <= 0 {
		return nil, nil
	}

	pkgName := bpkg.rpkg.Lpkg.Name()

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Generating CMakeLists.txt for %s\n", pkgName)
	fmt.Fprintf(w, "# Generating CMakeLists.txt for %s\n\n", pkgName)
	fmt.Fprintf(w, "add_library(%s %s)\n\n",
		EscapeName(pkgName),
		strings.Join(files, " "))

	archivePath := replaceBackslashes(trimProjectPath(filepath.Dir(b.ArchivePath(bpkg))))
	CmakeCompilerInfoWrite(w, archivePath, bpkg, entries[0], otherIncludes)

	return bpkg, nil
}

func (b *Builder) CMakeTargetWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	bpkgs := b.sortedBuildPackages()
	var compileFlags []string
	var linkFlags []string

	c := targetCompiler
	c.AddInfo(b.GetCompilerInfo())

	builtPackages := []*BuildPackage{}
	for _, bpkg := range bpkgs {
		builtPackage, err := b.CMakeBuildPackageWrite(w, bpkg, &linkFlags)
		if err != nil {
			return err
		}

		if builtPackage != nil {
			builtPackages = append(builtPackages, builtPackage)
		}
	}

	elfName := "cmake_" + filepath.Base(b.AppElfPath())
	fmt.Fprintf(w, "# Generating code for %s\n\n", elfName)

	var targetObjectsBuffer bytes.Buffer

	for _, bpkg := range builtPackages {
		targetObjectsBuffer.WriteString(fmt.Sprintf("%s ",
			EscapeName(bpkg.rpkg.Lpkg.Name())))
	}

	elfOutputDir := replaceBackslashes(trimProjectPath(filepath.Dir(b.AppElfPath())))
	fmt.Fprintf(w, "file(WRITE %s \"\")\n", replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))
	fmt.Fprintf(w, "add_executable(%s %s)\n\n", elfName,
		replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))

	if c.GetLdResolveCircularDeps() {
		fmt.Fprintf(w, "target_link_libraries(%s -Wl,--start-group %s -Wl,--end-group)\n",
			elfName, targetObjectsBuffer.String())
	} else {
		fmt.Fprintf(w, "target_link_libraries(%s %s)\n",
			elfName, targetObjectsBuffer.String())
	}

	compileFlags = append(compileFlags, c.GetCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetCompilerInfo().CXXflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().CXXflags...)
	compileFlags = util.SortFields(compileFlags...)

	fmt.Fprintf(w, `set_property(TARGET %s APPEND_STRING
														PROPERTY
														COMPILE_FLAGS
														"%s")`,
		elfName,
		strings.Replace(strings.Join(compileFlags, " "), "\"", "\\\\\\\"", -1))
	fmt.Fprintln(w)

	lFlags := append(c.GetCompilerInfo().Lflags, c.GetLocalCompilerInfo().Lflags...)
	lFlags = append(lFlags, linkFlags...)
	lFlags = util.SortFields(lFlags...)

	for _, ld := range c.LinkerScripts {
		lFlags = append(lFlags, "-T"+ld)
	}

	var cFlags []string
	cFlags = append(cFlags, c.GetCompilerInfo().Cflags...)
	cFlags = append(cFlags, c.GetLocalCompilerInfo().Cflags...)
	cFlags = util.SortFields(cFlags...)
	lFlags = append(lFlags, cFlags...)

	var cxxFlags []string
	cxxFlags = append(cxxFlags, c.GetCompilerInfo().CXXflags...)
	cxxFlags = append(cxxFlags, c.GetLocalCompilerInfo().CXXflags...)
	cxxFlags = util.SortFields(cxxFlags...)
	lFlags = append(lFlags, cxxFlags...)

	fmt.Fprintf(w, `set_target_properties(%s
							PROPERTIES
							ARCHIVE_OUTPUT_DIRECTORY %s
							LIBRARY_OUTPUT_DIRECTORY %s
							RUNTIME_OUTPUT_DIRECTORY %s
							LINK_FLAGS "%s"
							LINKER_LANGUAGE C)`,
		elfName,
		elfOutputDir,
		elfOutputDir,
		elfOutputDir,
		strings.Replace(strings.Join(lFlags, " "), "\"", "\\\\\\\"", -1))

	fmt.Fprintln(w)

	libs := strings.Join(getLibsFromLinkerFlags(lFlags), " ")
	fmt.Fprintf(w, "# Workaround for gcc linker woes\n")
	fmt.Fprintf(w, "set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} %s\")\n", libs)
	fmt.Fprintln(w)

	return nil
}

func getLibsFromLinkerFlags(lflags []string) []string {
	libs := []string{}

	for _, flag := range lflags {
		if strings.HasPrefix(flag, "-l") {
			libs = append(libs, flag)
		}
	}

	return libs
}

func CmakeCompilerInfoWrite(w io.Writer, archiveFile string, bpkg *BuildPackage,
	cj toolchain.CompilerJob, otherIncludes []string) {
	c := cj.Compiler

	var includes []string

	includes = append(includes, c.GetCompilerInfo().Includes...)
	includes = append(includes, c.GetLocalCompilerInfo().Includes...)
	includes = append(includes, otherIncludes...)

	// Sort and remove duplicate flags
	includes = util.SortFields(includes...)
	trimProjectPathSlice(includes)
	replaceBackslashesSlice(includes)

	fmt.Fprintf(w, `set_target_properties(%s
							PROPERTIES
							ARCHIVE_OUTPUT_DIRECTORY %s
							LIBRARY_OUTPUT_DIRECTORY %s
							RUNTIME_OUTPUT_DIRECTORY %s)`,
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		archiveFile,
		archiveFile,
		archiveFile,
	)
	fmt.Fprintln(w)
	fmt.Fprintf(w, "target_include_directories(%s PUBLIC %s)\n\n",
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		strings.Join(includes, " "))
}

func (t *TargetBuilder) CMakeTargetBuilderWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	if err := t.PrepBuild(); err != nil {
		return err
	}

	/* Build the Apps */
	project.ResetDeps(t.AppList)

	targetCompiler.LinkerScripts = t.bspPkg.LinkerScripts

	if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
		return err
	}

	if err := t.AppBuilder.CMakeTargetWrite(w, targetCompiler); err != nil {
		return err
	}

	return nil
}

func CmakeCompilerWrite(w io.Writer, c *toolchain.Compiler) {
	/* Since CMake 3 it is required to set a full path to the compiler */
	/* TODO: get rid of the prefix to /usr/bin */
	fmt.Fprintln(w, "set(CMAKE_SYSTEM_NAME Generic)")
	fmt.Fprintln(w, "set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)")
	fmt.Fprintf(w, "set(CMAKE_C_COMPILER %s)\n", c.GetCcPath())
	fmt.Fprintf(w, "set(CMAKE_CXX_COMPILER %s)\n", c.GetCppPath())
	fmt.Fprintf(w, "set(CMAKE_ASM_COMPILER %s)\n", c.GetAsPath())
	/* TODO: cmake returns error on link */
	//fmt.Fprintf(w, "set(CMAKE_AR %s)\n", c.GetArPath())
	fmt.Fprintln(w)
}

func CmakeHeaderWrite(w io.Writer, c *toolchain.Compiler, targetName string) {
	fmt.Fprintln(w, "cmake_minimum_required(VERSION 3.7)\n")
	CmakeCompilerWrite(w, c)
	fmt.Fprintf(w, "project(%s VERSION 0.0.0 LANGUAGES C CXX ASM)\n\n", targetName)
	fmt.Fprintln(w, "SET(CMAKE_C_FLAGS_BACKUP  \"${CMAKE_C_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_CXX_FLAGS_BACKUP  \"${CMAKE_CXX_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_ASM_FLAGS_BACKUP  \"${CMAKE_ASM_FLAGS}\")")
	fmt.Fprintln(w)
}

func CMakeTargetGenerate(target *target.Target) error {
	CmakeFileHandle, err := os.Create(CmakeListsPath())
	if err != nil {
		return util.ChildNewtError(err)
	}

	var b = bytes.Buffer{}
	w := bufio.NewWriter(&b)
	defer CmakeFileHandle.Close()

	targetBuilder, err := NewTargetBuilder(target)
	if err != nil {
		return err
	}

	targetCompiler, err := targetBuilder.NewCompiler("", "")
	if err != nil {
		return err
	}

	CmakeHeaderWrite(w, targetCompiler, target.ShortName())

	if err := targetBuilder.CMakeTargetBuilderWrite(w, targetCompiler); err != nil {
		return err
	}

	w.Flush()

	CmakeFileHandle.Write(b.Bytes())
	return nil
}
<commit_msg>cmake: print warning if any custom commands<commit_after>/**
 * 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 builder

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	log "github.com/sirupsen/logrus"

	"mynewt.apache.org/newt/newt/interfaces"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/newt/toolchain"
	"mynewt.apache.org/newt/util"
)

const CMAKELISTS_FILENAME string = "CMakeLists.txt"

func CmakeListsPath() string {
	return project.GetProject().BasePath + "/" + CMAKELISTS_FILENAME
}

func EscapeName(name string) string {
	return strings.Replace(name, "/", "_", -1)
}

func replaceBackslashes(path string) string {
	return strings.Replace(path, "\\", "/", -1)
}

func replaceBackslashesSlice(elements []string) {
	for e := range elements {
		elements[e] = replaceBackslashes(elements[e])
	}
}

func trimProjectPath(path string) string {
	proj := interfaces.GetProject()
	path = strings.TrimPrefix(path, proj.Path()+"/")
	return path
}

func trimProjectPathSlice(elements []string) {
	for e := range elements {
		elements[e] = trimProjectPath(elements[e])
	}
}

func extractIncludes(flags *[]string, includes *[]string, other *[]string) {
	for _, f := range *flags {
		if strings.HasPrefix(f, "-I") {
			*includes = append(*includes, strings.TrimPrefix(f, "-I"))
		} else {
			*other = append(*other, f)
		}
	}
}

func CmakeSourceObjectWrite(w io.Writer, cj toolchain.CompilerJob,
	includeDirs *[]string, linkFlags *[]string) {
	c := cj.Compiler

	flags := []string{}
	otherFlags := []string{}

	switch cj.CompilerType {
	case toolchain.COMPILER_TYPE_C:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
	case toolchain.COMPILER_TYPE_ASM:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().Aflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Aflags...)
	case toolchain.COMPILER_TYPE_CPP:
		flags = append(flags, c.GetCompilerInfo().Cflags...)
		flags = append(flags, c.GetLocalCompilerInfo().Cflags...)
		flags = append(flags, c.GetCompilerInfo().CXXflags...)
		flags = append(flags, c.GetLocalCompilerInfo().CXXflags...)
	}

	*linkFlags = append(*linkFlags, c.GetCompilerInfo().Lflags...)
	*linkFlags = append(*linkFlags, c.GetLocalCompilerInfo().Lflags...)

	extractIncludes(&flags, includeDirs, &otherFlags)
	cj.Filename = trimProjectPath(cj.Filename)

	// Sort and remove duplicate flags
	otherFlags = util.SortFields(otherFlags...)

	fmt.Fprintf(w, `set_property(SOURCE %s APPEND_STRING
														PROPERTY
														COMPILE_FLAGS
														"%s")`,
		cj.Filename,
		strings.Replace(strings.Join(otherFlags, " "), "\"", "\\\\\\\"", -1))
	fmt.Fprintln(w)
}

func (b *Builder) CMakeBuildPackageWrite(w io.Writer, bpkg *BuildPackage,
	linkFlags *[]string) (*BuildPackage, error) {
	entries, err := b.collectCompileEntriesBpkg(bpkg)
	if err != nil {
		return nil, err
	}

	if len(entries) <= 0 {
		return nil, nil
	}

	otherIncludes := []string{}
	files := []string{}

	for _, s := range entries {
		filename := filepath.ToSlash(s.Filename)
		if s.Compiler.ShouldIgnoreFile(filename) {
			log.Infof("Ignoring %s because package dictates it.\n", filename)
			continue
		}

		CmakeSourceObjectWrite(w, s, &otherIncludes, linkFlags)
		s.Filename = trimProjectPath(s.Filename)
		files = append(files, s.Filename)
	}

	if len(files) <= 0 {
		return nil, nil
	}

	pkgName := bpkg.rpkg.Lpkg.Name()

	util.StatusMessage(util.VERBOSITY_DEFAULT, "Generating CMakeLists.txt for %s\n", pkgName)
	fmt.Fprintf(w, "# Generating CMakeLists.txt for %s\n\n", pkgName)
	fmt.Fprintf(w, "add_library(%s %s)\n\n",
		EscapeName(pkgName),
		strings.Join(files, " "))

	archivePath := replaceBackslashes(trimProjectPath(filepath.Dir(b.ArchivePath(bpkg))))
	CmakeCompilerInfoWrite(w, archivePath, bpkg, entries[0], otherIncludes)

	return bpkg, nil
}

func (b *Builder) CMakeTargetWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	bpkgs := b.sortedBuildPackages()
	var compileFlags []string
	var linkFlags []string

	c := targetCompiler
	c.AddInfo(b.GetCompilerInfo())

	builtPackages := []*BuildPackage{}
	for _, bpkg := range bpkgs {
		builtPackage, err := b.CMakeBuildPackageWrite(w, bpkg, &linkFlags)
		if err != nil {
			return err
		}

		if builtPackage != nil {
			builtPackages = append(builtPackages, builtPackage)
		}
	}

	elfName := "cmake_" + filepath.Base(b.AppElfPath())
	fmt.Fprintf(w, "# Generating code for %s\n\n", elfName)

	var targetObjectsBuffer bytes.Buffer

	for _, bpkg := range builtPackages {
		targetObjectsBuffer.WriteString(fmt.Sprintf("%s ",
			EscapeName(bpkg.rpkg.Lpkg.Name())))
	}

	elfOutputDir := replaceBackslashes(trimProjectPath(filepath.Dir(b.AppElfPath())))
	fmt.Fprintf(w, "file(WRITE %s \"\")\n", replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))
	fmt.Fprintf(w, "add_executable(%s %s)\n\n", elfName,
		replaceBackslashes(filepath.Join(elfOutputDir, "null.c")))

	if c.GetLdResolveCircularDeps() {
		fmt.Fprintf(w, "target_link_libraries(%s -Wl,--start-group %s -Wl,--end-group)\n",
			elfName, targetObjectsBuffer.String())
	} else {
		fmt.Fprintf(w, "target_link_libraries(%s %s)\n",
			elfName, targetObjectsBuffer.String())
	}

	compileFlags = append(compileFlags, c.GetCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().Cflags...)
	compileFlags = append(compileFlags, c.GetCompilerInfo().CXXflags...)
	compileFlags = append(compileFlags, c.GetLocalCompilerInfo().CXXflags...)
	compileFlags = util.SortFields(compileFlags...)

	fmt.Fprintf(w, `set_property(TARGET %s APPEND_STRING
														PROPERTY
														COMPILE_FLAGS
														"%s")`,
		elfName,
		strings.Replace(strings.Join(compileFlags, " "), "\"", "\\\\\\\"", -1))
	fmt.Fprintln(w)

	lFlags := append(c.GetCompilerInfo().Lflags, c.GetLocalCompilerInfo().Lflags...)
	lFlags = append(lFlags, linkFlags...)
	lFlags = util.SortFields(lFlags...)

	for _, ld := range c.LinkerScripts {
		lFlags = append(lFlags, "-T"+ld)
	}

	var cFlags []string
	cFlags = append(cFlags, c.GetCompilerInfo().Cflags...)
	cFlags = append(cFlags, c.GetLocalCompilerInfo().Cflags...)
	cFlags = util.SortFields(cFlags...)
	lFlags = append(lFlags, cFlags...)

	var cxxFlags []string
	cxxFlags = append(cxxFlags, c.GetCompilerInfo().CXXflags...)
	cxxFlags = append(cxxFlags, c.GetLocalCompilerInfo().CXXflags...)
	cxxFlags = util.SortFields(cxxFlags...)
	lFlags = append(lFlags, cxxFlags...)

	fmt.Fprintf(w, `set_target_properties(%s
							PROPERTIES
							ARCHIVE_OUTPUT_DIRECTORY %s
							LIBRARY_OUTPUT_DIRECTORY %s
							RUNTIME_OUTPUT_DIRECTORY %s
							LINK_FLAGS "%s"
							LINKER_LANGUAGE C)`,
		elfName,
		elfOutputDir,
		elfOutputDir,
		elfOutputDir,
		strings.Replace(strings.Join(lFlags, " "), "\"", "\\\\\\\"", -1))

	fmt.Fprintln(w)

	libs := strings.Join(getLibsFromLinkerFlags(lFlags), " ")
	fmt.Fprintf(w, "# Workaround for gcc linker woes\n")
	fmt.Fprintf(w, "set(CMAKE_C_LINK_EXECUTABLE \"${CMAKE_C_LINK_EXECUTABLE} %s\")\n", libs)
	fmt.Fprintln(w)

	return nil
}

func getLibsFromLinkerFlags(lflags []string) []string {
	libs := []string{}

	for _, flag := range lflags {
		if strings.HasPrefix(flag, "-l") {
			libs = append(libs, flag)
		}
	}

	return libs
}

func CmakeCompilerInfoWrite(w io.Writer, archiveFile string, bpkg *BuildPackage,
	cj toolchain.CompilerJob, otherIncludes []string) {
	c := cj.Compiler

	var includes []string

	includes = append(includes, c.GetCompilerInfo().Includes...)
	includes = append(includes, c.GetLocalCompilerInfo().Includes...)
	includes = append(includes, otherIncludes...)

	// Sort and remove duplicate flags
	includes = util.SortFields(includes...)
	trimProjectPathSlice(includes)
	replaceBackslashesSlice(includes)

	fmt.Fprintf(w, `set_target_properties(%s
							PROPERTIES
							ARCHIVE_OUTPUT_DIRECTORY %s
							LIBRARY_OUTPUT_DIRECTORY %s
							RUNTIME_OUTPUT_DIRECTORY %s)`,
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		archiveFile,
		archiveFile,
		archiveFile,
	)
	fmt.Fprintln(w)
	fmt.Fprintf(w, "target_include_directories(%s PUBLIC %s)\n\n",
		EscapeName(bpkg.rpkg.Lpkg.Name()),
		strings.Join(includes, " "))
}

func (t *TargetBuilder) CMakeTargetBuilderWrite(w io.Writer, targetCompiler *toolchain.Compiler) error {
	if err := t.PrepBuild(); err != nil {
		return err
	}

	if len(t.res.PreBuildCmdCfg.StageFuncs) > 0 ||
		len(t.res.PreLinkCmdCfg.StageFuncs) > 0 ||
		len(t.res.PostBuildCmdCfg.StageFuncs) > 0 {

		util.OneTimeWarning(
			"custom commands not included in cmake output (unsupported)")
	}

	/* Build the Apps */
	project.ResetDeps(t.AppList)

	targetCompiler.LinkerScripts = t.bspPkg.LinkerScripts

	if err := t.bspPkg.Reload(t.AppBuilder.cfg.SettingValues()); err != nil {
		return err
	}

	if err := t.AppBuilder.CMakeTargetWrite(w, targetCompiler); err != nil {
		return err
	}

	return nil
}

func CmakeCompilerWrite(w io.Writer, c *toolchain.Compiler) {
	/* Since CMake 3 it is required to set a full path to the compiler */
	/* TODO: get rid of the prefix to /usr/bin */
	fmt.Fprintln(w, "set(CMAKE_SYSTEM_NAME Generic)")
	fmt.Fprintln(w, "set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)")
	fmt.Fprintf(w, "set(CMAKE_C_COMPILER %s)\n", c.GetCcPath())
	fmt.Fprintf(w, "set(CMAKE_CXX_COMPILER %s)\n", c.GetCppPath())
	fmt.Fprintf(w, "set(CMAKE_ASM_COMPILER %s)\n", c.GetAsPath())
	/* TODO: cmake returns error on link */
	//fmt.Fprintf(w, "set(CMAKE_AR %s)\n", c.GetArPath())
	fmt.Fprintln(w)
}

func CmakeHeaderWrite(w io.Writer, c *toolchain.Compiler, targetName string) {
	fmt.Fprintln(w, "cmake_minimum_required(VERSION 3.7)\n")
	CmakeCompilerWrite(w, c)
	fmt.Fprintf(w, "project(%s VERSION 0.0.0 LANGUAGES C CXX ASM)\n\n", targetName)
	fmt.Fprintln(w, "SET(CMAKE_C_FLAGS_BACKUP  \"${CMAKE_C_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_CXX_FLAGS_BACKUP  \"${CMAKE_CXX_FLAGS}\")")
	fmt.Fprintln(w, "SET(CMAKE_ASM_FLAGS_BACKUP  \"${CMAKE_ASM_FLAGS}\")")
	fmt.Fprintln(w)
}

func CMakeTargetGenerate(target *target.Target) error {
	CmakeFileHandle, err := os.Create(CmakeListsPath())
	if err != nil {
		return util.ChildNewtError(err)
	}

	var b = bytes.Buffer{}
	w := bufio.NewWriter(&b)
	defer CmakeFileHandle.Close()

	targetBuilder, err := NewTargetBuilder(target)
	if err != nil {
		return err
	}

	targetCompiler, err := targetBuilder.NewCompiler("", "")
	if err != nil {
		return err
	}

	CmakeHeaderWrite(w, targetCompiler, target.ShortName())

	if err := targetBuilder.CMakeTargetBuilderWrite(w, targetCompiler); err != nil {
		return err
	}

	w.Flush()

	CmakeFileHandle.Write(b.Bytes())
	return nil
}
<|endoftext|>


<commit_before>package number

import (
	"fmt"
	"math/rand"
)

// Probabilty represents a probability value (a number in the range 0..1 inclusive).
//
// A value of zero means that an event is guaranteed not to happen. A value of
// 1 means it is guaranteed to occur.
type Probability float64

const (
	// ProbabilityOne is a convenient constant representing a probability of
	// one, that is an event with a probability of one is a certainty.
	ProbabilityOne Probability = 1

	// ProbabilityEven is a convenient constant representing a probability of
	// 0.5 (used to model an event that has a 50/50 chance of occurring).
	ProbabilityEven = 0.5

	// ProbabilityZero is a convenient constant representing a probability of
	// zero, that is an event that will never happen (it is an impossibility).
	ProbabilityZero = 0
)

// NewProbability creates a new Probability value.
func NewProbability(probability float64) (Probability, error) {
	if probability < 0 || probability > 1 {
		return ProbabilityZero, fmt.Errorf("Probability must be in the range 0..1 inclusive, got%v", probability)
	}
	return Probability(probability), nil
}

// NewEvent generates an event according to the probability value.
//
// In other words NextEvent returns True with a probability of p, false with a
// probability of 1 - p.
func (p Probability) NextEvent(rng *rand.Rand) bool {
	// Don't bother generating an random value if the result is guaranteed.
	return p == 1 || rng.Float64() < float64(p)
}

// The Complement of a probability p is 1 - p. For example if p = 0.75, the
// complement is 0.25.
func (p Probability) Complement() Probability {
	return Probability(1 - p)
}
<commit_msg>Precreate convenient Probability values in init()<commit_after>package number

import (
	"fmt"
	"math/rand"
)

// Probabilty represents a probability value (a number in the range 0..1 inclusive).
//
// A value of zero means that an event is guaranteed not to happen. A value of
// 1 means it is guaranteed to occur.
type Probability float64

var (
	// ProbabilityOne is a convenient constant representing a probability of
	// one, that is an event with a probability of one is a certainty.
	ProbabilityOne Probability

	// ProbabilityEven is a convenient constant representing a probability of
	// 0.5 (used to model an event that has a 50/50 chance of occurring).
	ProbabilityEven Probability

	// ProbabilityZero is a convenient constant representing a probability of
	// zero, that is an event that will never happen (it is an impossibility).
	ProbabilityZero Probability
)

func init() {
	ProbabilityOne, _ = NewProbability(1)
	ProbabilityEven, _ = NewProbability(0.5)
	ProbabilityZero, _ = NewProbability(0)
}

// NewProbability creates a new Probability value.
func NewProbability(probability float64) (Probability, error) {
	if probability < 0 || probability > 1 {
		return ProbabilityZero, fmt.Errorf("Probability must be in the range 0..1 inclusive, got%v", probability)
	}
	return Probability(probability), nil
}

// NewEvent generates an event according to the probability value.
//
// In other words NextEvent returns True with a probability of p, false with a
// probability of 1 - p.
func (p Probability) NextEvent(rng *rand.Rand) bool {
	// Don't bother generating an random value if the result is guaranteed.
	return p == 1 || rng.Float64() < float64(p)
}

// The Complement of a probability p is 1 - p. For example if p = 0.75, the
// complement is 0.25.
func (p Probability) Complement() Probability {
	return Probability(1 - p)
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes 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 rest

import (
	"fmt"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/api/validation"
	"k8s.io/kubernetes/pkg/runtime"
	"k8s.io/kubernetes/pkg/util/validation/field"
)

// RESTUpdateStrategy defines the minimum validation, accepted input, and
// name generation behavior to update an object that follows Kubernetes
// API conventions. A resource may have many UpdateStrategies, depending on
// the call pattern in use.
type RESTUpdateStrategy interface {
	runtime.ObjectTyper
	// NamespaceScoped returns true if the object must be within a namespace.
	NamespaceScoped() bool
	// AllowCreateOnUpdate returns true if the object can be created by a PUT.
	AllowCreateOnUpdate() bool
	// PrepareForUpdate is invoked on update before validation to normalize
	// the object.  For example: remove fields that are not to be persisted,
	// sort order-insensitive list fields, etc.  This should not remove fields
	// whose presence would be considered a validation error.
	PrepareForUpdate(obj, old runtime.Object)
	// ValidateUpdate is invoked after default fields in the object have been
	// filled in before the object is persisted.  This method should not mutate
	// the object.
	ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList
	// Canonicalize is invoked after validation has succeeded but before the
	// object has been persisted.  This method may mutate the object.
	Canonicalize(obj runtime.Object)
	// AllowUnconditionalUpdate returns true if the object can be updated
	// unconditionally (irrespective of the latest resource version), when
	// there is no resource version specified in the object.
	AllowUnconditionalUpdate() bool
}

// TODO: add other common fields that require global validation.
func validateCommonFields(obj, old runtime.Object) (field.ErrorList, error) {
	allErrs := field.ErrorList{}
	objectMeta, err := api.ObjectMetaFor(obj)
	if err != nil {
		return nil, fmt.Errorf("failed to get new object metadata: %v", err)
	}
	oldObjectMeta, err := api.ObjectMetaFor(old)
	if err != nil {
		return nil, fmt.Errorf("failed to get old object metadata: %v", err)
	}
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta, field.NewPath("metadata"))...)

	return allErrs, nil
}

// BeforeUpdate ensures that common operations for all resources are performed on update. It only returns
// errors that can be converted to api.Status. It will invoke update validation with the provided existing
// and updated objects.
func BeforeUpdate(strategy RESTUpdateStrategy, ctx api.Context, obj, old runtime.Object) error {
	objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
	if kerr != nil {
		return kerr
	}
	if strategy.NamespaceScoped() {
		if !api.ValidNamespace(ctx, objectMeta) {
			return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
		}
	} else {
		objectMeta.Namespace = api.NamespaceNone
	}

	strategy.PrepareForUpdate(obj, old)

	// Ensure some common fields, like UID, are validated for all resources.
	errs, err := validateCommonFields(obj, old)
	if err != nil {
		return errors.NewInternalError(err)
	}

	errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...)
	if len(errs) > 0 {
		return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs)
	}

	strategy.Canonicalize(obj)

	return nil
}

// TransformFunc is a function to transform and return newObj
type TransformFunc func(ctx api.Context, newObj runtime.Object, oldObj runtime.Object) (transformedNewObj runtime.Object, err error)

// defaultUpdatedObjectInfo implements UpdatedObjectInfo
type defaultUpdatedObjectInfo struct {
	// obj is the updated object
	obj runtime.Object

	// copier makes a copy of the object before returning it.
	// this allows repeated calls to UpdatedObject() to return
	// pristine data, even if the returned value is mutated.
	copier runtime.ObjectCopier

	// transformers is an optional list of transforming functions that modify or
	// replace obj using information from the context, old object, or other sources.
	transformers []TransformFunc
}

// DefaultUpdatedObjectInfo returns an UpdatedObjectInfo impl based on the specified object.
func DefaultUpdatedObjectInfo(obj runtime.Object, copier runtime.ObjectCopier, transformers ...TransformFunc) UpdatedObjectInfo {
	return &defaultUpdatedObjectInfo{obj, copier, transformers}
}

// Preconditions satisfies the UpdatedObjectInfo interface.
func (i *defaultUpdatedObjectInfo) Preconditions() *api.Preconditions {
	// Attempt to get the UID out of the object
	accessor, err := meta.Accessor(i.obj)
	if err != nil {
		// If no UID can be read, no preconditions are possible
		return nil
	}

	// If empty, no preconditions needed
	uid := accessor.GetUID()
	if len(uid) == 0 {
		return nil
	}

	return &api.Preconditions{UID: &uid}
}

// UpdatedObject satisfies the UpdatedObjectInfo interface.
// It returns a copy of the held obj, passed through any configured transformers.
func (i *defaultUpdatedObjectInfo) UpdatedObject(ctx api.Context, oldObj runtime.Object) (runtime.Object, error) {
	var err error
	// Start with the configured object
	newObj := i.obj

	// If the original is non-nil (might be nil if the first transformer builds the object from the oldObj), make a copy,
	// so we don't return the original. BeforeUpdate can mutate the returned object, doing things like clearing ResourceVersion.
	// If we're re-called, we need to be able to return the pristine version.
	if newObj != nil {
		newObj, err = i.copier.Copy(newObj)
		if err != nil {
			return nil, err
		}
	}

	// Allow any configured transformers to update the new object
	for _, transformer := range i.transformers {
		newObj, err = transformer(ctx, newObj, oldObj)
		if err != nil {
			return nil, err
		}
	}

	return newObj, nil
}
<commit_msg>Add WrapUpdatedObjectInfo helper<commit_after>/*
Copyright 2014 The Kubernetes 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 rest

import (
	"fmt"

	"k8s.io/kubernetes/pkg/api"
	"k8s.io/kubernetes/pkg/api/errors"
	"k8s.io/kubernetes/pkg/api/meta"
	"k8s.io/kubernetes/pkg/api/validation"
	"k8s.io/kubernetes/pkg/runtime"
	"k8s.io/kubernetes/pkg/util/validation/field"
)

// RESTUpdateStrategy defines the minimum validation, accepted input, and
// name generation behavior to update an object that follows Kubernetes
// API conventions. A resource may have many UpdateStrategies, depending on
// the call pattern in use.
type RESTUpdateStrategy interface {
	runtime.ObjectTyper
	// NamespaceScoped returns true if the object must be within a namespace.
	NamespaceScoped() bool
	// AllowCreateOnUpdate returns true if the object can be created by a PUT.
	AllowCreateOnUpdate() bool
	// PrepareForUpdate is invoked on update before validation to normalize
	// the object.  For example: remove fields that are not to be persisted,
	// sort order-insensitive list fields, etc.  This should not remove fields
	// whose presence would be considered a validation error.
	PrepareForUpdate(obj, old runtime.Object)
	// ValidateUpdate is invoked after default fields in the object have been
	// filled in before the object is persisted.  This method should not mutate
	// the object.
	ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList
	// Canonicalize is invoked after validation has succeeded but before the
	// object has been persisted.  This method may mutate the object.
	Canonicalize(obj runtime.Object)
	// AllowUnconditionalUpdate returns true if the object can be updated
	// unconditionally (irrespective of the latest resource version), when
	// there is no resource version specified in the object.
	AllowUnconditionalUpdate() bool
}

// TODO: add other common fields that require global validation.
func validateCommonFields(obj, old runtime.Object) (field.ErrorList, error) {
	allErrs := field.ErrorList{}
	objectMeta, err := api.ObjectMetaFor(obj)
	if err != nil {
		return nil, fmt.Errorf("failed to get new object metadata: %v", err)
	}
	oldObjectMeta, err := api.ObjectMetaFor(old)
	if err != nil {
		return nil, fmt.Errorf("failed to get old object metadata: %v", err)
	}
	allErrs = append(allErrs, validation.ValidateObjectMetaUpdate(objectMeta, oldObjectMeta, field.NewPath("metadata"))...)

	return allErrs, nil
}

// BeforeUpdate ensures that common operations for all resources are performed on update. It only returns
// errors that can be converted to api.Status. It will invoke update validation with the provided existing
// and updated objects.
func BeforeUpdate(strategy RESTUpdateStrategy, ctx api.Context, obj, old runtime.Object) error {
	objectMeta, kind, kerr := objectMetaAndKind(strategy, obj)
	if kerr != nil {
		return kerr
	}
	if strategy.NamespaceScoped() {
		if !api.ValidNamespace(ctx, objectMeta) {
			return errors.NewBadRequest("the namespace of the provided object does not match the namespace sent on the request")
		}
	} else {
		objectMeta.Namespace = api.NamespaceNone
	}

	strategy.PrepareForUpdate(obj, old)

	// Ensure some common fields, like UID, are validated for all resources.
	errs, err := validateCommonFields(obj, old)
	if err != nil {
		return errors.NewInternalError(err)
	}

	errs = append(errs, strategy.ValidateUpdate(ctx, obj, old)...)
	if len(errs) > 0 {
		return errors.NewInvalid(kind.GroupKind(), objectMeta.Name, errs)
	}

	strategy.Canonicalize(obj)

	return nil
}

// TransformFunc is a function to transform and return newObj
type TransformFunc func(ctx api.Context, newObj runtime.Object, oldObj runtime.Object) (transformedNewObj runtime.Object, err error)

// defaultUpdatedObjectInfo implements UpdatedObjectInfo
type defaultUpdatedObjectInfo struct {
	// obj is the updated object
	obj runtime.Object

	// copier makes a copy of the object before returning it.
	// this allows repeated calls to UpdatedObject() to return
	// pristine data, even if the returned value is mutated.
	copier runtime.ObjectCopier

	// transformers is an optional list of transforming functions that modify or
	// replace obj using information from the context, old object, or other sources.
	transformers []TransformFunc
}

// DefaultUpdatedObjectInfo returns an UpdatedObjectInfo impl based on the specified object.
func DefaultUpdatedObjectInfo(obj runtime.Object, copier runtime.ObjectCopier, transformers ...TransformFunc) UpdatedObjectInfo {
	return &defaultUpdatedObjectInfo{obj, copier, transformers}
}

// Preconditions satisfies the UpdatedObjectInfo interface.
func (i *defaultUpdatedObjectInfo) Preconditions() *api.Preconditions {
	// Attempt to get the UID out of the object
	accessor, err := meta.Accessor(i.obj)
	if err != nil {
		// If no UID can be read, no preconditions are possible
		return nil
	}

	// If empty, no preconditions needed
	uid := accessor.GetUID()
	if len(uid) == 0 {
		return nil
	}

	return &api.Preconditions{UID: &uid}
}

// UpdatedObject satisfies the UpdatedObjectInfo interface.
// It returns a copy of the held obj, passed through any configured transformers.
func (i *defaultUpdatedObjectInfo) UpdatedObject(ctx api.Context, oldObj runtime.Object) (runtime.Object, error) {
	var err error
	// Start with the configured object
	newObj := i.obj

	// If the original is non-nil (might be nil if the first transformer builds the object from the oldObj), make a copy,
	// so we don't return the original. BeforeUpdate can mutate the returned object, doing things like clearing ResourceVersion.
	// If we're re-called, we need to be able to return the pristine version.
	if newObj != nil {
		newObj, err = i.copier.Copy(newObj)
		if err != nil {
			return nil, err
		}
	}

	// Allow any configured transformers to update the new object
	for _, transformer := range i.transformers {
		newObj, err = transformer(ctx, newObj, oldObj)
		if err != nil {
			return nil, err
		}
	}

	return newObj, nil
}

// wrappedUpdatedObjectInfo allows wrapping an existing objInfo and
// chaining additional transformations/checks on the result of UpdatedObject()
type wrappedUpdatedObjectInfo struct {
	// obj is the updated object
	objInfo UpdatedObjectInfo

	// transformers is an optional list of transforming functions that modify or
	// replace obj using information from the context, old object, or other sources.
	transformers []TransformFunc
}

// WrapUpdatedObjectInfo returns an UpdatedObjectInfo impl that delegates to
// the specified objInfo, then calls the passed transformers
func WrapUpdatedObjectInfo(objInfo UpdatedObjectInfo, transformers ...TransformFunc) UpdatedObjectInfo {
	return &wrappedUpdatedObjectInfo{objInfo, transformers}
}

// Preconditions satisfies the UpdatedObjectInfo interface.
func (i *wrappedUpdatedObjectInfo) Preconditions() *api.Preconditions {
	return i.objInfo.Preconditions()
}

// UpdatedObject satisfies the UpdatedObjectInfo interface.
// It delegates to the wrapped objInfo and passes the result through any configured transformers.
func (i *wrappedUpdatedObjectInfo) UpdatedObject(ctx api.Context, oldObj runtime.Object) (runtime.Object, error) {
	newObj, err := i.objInfo.UpdatedObject(ctx, oldObj)
	if err != nil {
		return newObj, err
	}

	// Allow any configured transformers to update the new object or error
	for _, transformer := range i.transformers {
		newObj, err = transformer(ctx, newObj, oldObj)
		if err != nil {
			return nil, err
		}
	}

	return newObj, nil
}
<|endoftext|>


<commit_before>package apiserver

import (
	"fmt"
	"sync"
)

var MAXWATCHERS = 10

type WatchChannelDistributor struct {
	inputChannel   chan *Report
	outputChannels []chan *Report
	mux            sync.Mutex
}

func NewWatchChannelDistributor(input chan *Report) *WatchChannelDistributor {
	return &WatchChannelDistributor{
		inputChannel:   input,
		outputChannels: make([]chan *Report, 0),
	}
}

func (w *WatchChannelDistributor) Run() {
	for {
		select {
		case report := <-w.inputChannel:
			for i := 0; i < len(w.outputChannels); i++ {
				if w.outputChannels[i] != nil {
					w.outputChannels[i] <- report
				}

			}

		}
	}
}

func (w *WatchChannelDistributor) AddChannel(ch chan *Report) (int, error) {
	w.mux.Lock()
	defer w.mux.Unlock()

	if len(w.outputChannels) > MAXWATCHERS {
		return -1, fmt.Errorf("Maximal number of watches exceeded")
	}
	for i := 0; i < len(w.outputChannels); i++ {
		if w.outputChannels[i] == nil {
			w.outputChannels[i] = ch
			return i, nil
		}
	}
	w.outputChannels = append(w.outputChannels, ch)
	return len(w.outputChannels) - 1, nil
}

func (w *WatchChannelDistributor) RemoveChannel(pos int) {
	w.mux.Lock()
	defer w.mux.Unlock()
	close(w.outputChannels[pos])
	w.outputChannels[pos] = nil
}
<commit_msg>Apiserver Watch - fix checking of maximum watchers<commit_after>package apiserver

import (
	"fmt"
	"sync"
)

var MAXWATCHERS = 10

type WatchChannelDistributor struct {
	inputChannel   chan *Report
	outputChannels []chan *Report
	mux            sync.Mutex
}

func NewWatchChannelDistributor(input chan *Report) *WatchChannelDistributor {
	return &WatchChannelDistributor{
		inputChannel:   input,
		outputChannels: make([]chan *Report, 0),
	}
}

func (w *WatchChannelDistributor) Run() {
	for {
		select {
		case report := <-w.inputChannel:
			for i := 0; i < len(w.outputChannels); i++ {
				if w.outputChannels[i] != nil {
					w.outputChannels[i] <- report
				}

			}

		}
	}
}

func (w *WatchChannelDistributor) AddChannel(ch chan *Report) (int, error) {
	w.mux.Lock()
	defer w.mux.Unlock()

	for i := 0; i < len(w.outputChannels); i++ {
		if w.outputChannels[i] == nil {
			w.outputChannels[i] = ch
			return i, nil
		}
	}
	if len(w.outputChannels) >= MAXWATCHERS {
		return -1, fmt.Errorf("Maximal number of watches exceeded\n")
	}
	w.outputChannels = append(w.outputChannels, ch)
	return len(w.outputChannels) - 1, nil
}

func (w *WatchChannelDistributor) RemoveChannel(pos int) {
	w.mux.Lock()
	defer w.mux.Unlock()
	close(w.outputChannels[pos])
	w.outputChannels[pos] = nil
}
<|endoftext|>


<commit_before>package cmds

import (
	"github.com/urfave/cli"
)

type Server struct {
	Log                 string
	ClusterCIDR         string
	ClusterSecret       string
	ServiceCIDR         string
	ClusterDNS          string
	HTTPSPort           int
	HTTPPort            int
	DataDir             string
	DisableAgent        bool
	KubeConfigOutput    string
	KubeConfigMode      string
	KnownIPs            cli.StringSlice
	BindAddress         string
	ExtraAPIArgs        cli.StringSlice
	ExtraSchedulerArgs  cli.StringSlice
	ExtraControllerArgs cli.StringSlice
	Rootless            bool
}

var ServerConfig Server

func NewServerCommand(action func(*cli.Context) error) cli.Command {
	return cli.Command{
		Name:      "server",
		Usage:     "Run management server",
		UsageText: appName + " server [OPTIONS]",
		Action:    action,
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:        "bind-address",
				Usage:       "k3s bind address",
				Destination: &ServerConfig.BindAddress,
			},
			cli.IntFlag{
				Name:        "https-listen-port",
				Usage:       "HTTPS listen port",
				Value:       6443,
				Destination: &ServerConfig.HTTPSPort,
			},
			cli.IntFlag{
				Name:        "http-listen-port",
				Usage:       "HTTP listen port (for /healthz, HTTPS redirect, and port for TLS terminating LB)",
				Value:       0,
				Destination: &ServerConfig.HTTPPort,
			},
			cli.StringFlag{
				Name:        "data-dir,d",
				Usage:       "Folder to hold state default /var/lib/rancher/k3s or ${HOME}/.rancher/k3s if not root",
				Destination: &ServerConfig.DataDir,
			},
			cli.BoolFlag{
				Name:        "disable-agent",
				Usage:       "Do not run a local agent and register a local kubelet",
				Destination: &ServerConfig.DisableAgent,
			},
			cli.StringFlag{
				Name:        "log,l",
				Usage:       "Log to file",
				Destination: &ServerConfig.Log,
			},
			cli.StringFlag{
				Name:        "cluster-cidr",
				Usage:       "Network CIDR to use for pod IPs",
				Destination: &ServerConfig.ClusterCIDR,
				Value:       "10.42.0.0/16",
			},
			cli.StringFlag{
				Name:        "cluster-secret",
				Usage:       "Shared secret used to bootstrap a cluster",
				Destination: &ServerConfig.ClusterSecret,
				EnvVar:      "K3S_CLUSTER_SECRET",
			},
			cli.StringFlag{
				Name:        "service-cidr",
				Usage:       "Network CIDR to use for services IPs",
				Destination: &ServerConfig.ServiceCIDR,
				Value:       "10.43.0.0/16",
			},
			cli.StringFlag{
				Name:        "cluster-dns",
				Usage:       "Cluster IP for coredns service. Should be in your service-cidr range",
				Destination: &ServerConfig.ClusterDNS,
				Value:       "",
			},
			cli.StringSliceFlag{
				Name:  "no-deploy",
				Usage: "Do not deploy packaged components (valid items: coredns, servicelb, traefik)",
			},
			cli.StringFlag{
				Name:        "write-kubeconfig,o",
				Usage:       "Write kubeconfig for admin client to this file",
				Destination: &ServerConfig.KubeConfigOutput,
				EnvVar:      "K3S_KUBECONFIG_OUTPUT",
			},
			cli.StringFlag{
				Name:        "write-kubeconfig-mode",
				Usage:       "Write kubeconfig with this mode",
				Destination: &ServerConfig.KubeConfigMode,
				EnvVar:      "K3S_KUBECONFIG_MODE",
			},
			cli.StringSliceFlag{
				Name:  "tls-san",
				Usage: "Add additional hostname or IP as a Subject Alternative Name in the TLS cert",
				Value: &ServerConfig.KnownIPs,
			},
			cli.StringSliceFlag{
				Name:  "kube-apiserver-arg",
				Usage: "Customized flag for kube-apiserver process",
				Value: &ServerConfig.ExtraAPIArgs,
			},
			cli.StringSliceFlag{
				Name:  "kube-scheduler-arg",
				Usage: "Customized flag for kube-scheduler process",
				Value: &ServerConfig.ExtraSchedulerArgs,
			},
			cli.StringSliceFlag{
				Name:  "kube-controller-arg",
				Usage: "Customized flag for kube-controller-manager process",
				Value: &ServerConfig.ExtraControllerArgs,
			},
			cli.BoolFlag{
				Name:        "rootless",
				Usage:       "(experimental) Run rootless",
				Destination: &ServerConfig.Rootless,
			},
			NodeIPFlag,
			NodeNameFlag,
			DockerFlag,
			FlannelFlag,
			CRIEndpointFlag,
			ResolvConfFlag,
			ExtraKubeletArgs,
			ExtraKubeProxyArgs,
		},
	}
}
<commit_msg>Fix comment of bind address<commit_after>package cmds

import (
	"github.com/urfave/cli"
)

type Server struct {
	Log                 string
	ClusterCIDR         string
	ClusterSecret       string
	ServiceCIDR         string
	ClusterDNS          string
	HTTPSPort           int
	HTTPPort            int
	DataDir             string
	DisableAgent        bool
	KubeConfigOutput    string
	KubeConfigMode      string
	KnownIPs            cli.StringSlice
	BindAddress         string
	ExtraAPIArgs        cli.StringSlice
	ExtraSchedulerArgs  cli.StringSlice
	ExtraControllerArgs cli.StringSlice
	Rootless            bool
}

var ServerConfig Server

func NewServerCommand(action func(*cli.Context) error) cli.Command {
	return cli.Command{
		Name:      "server",
		Usage:     "Run management server",
		UsageText: appName + " server [OPTIONS]",
		Action:    action,
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:        "bind-address",
				Usage:       "k3s bind address (default: localhost)",
				Destination: &ServerConfig.BindAddress,
			},
			cli.IntFlag{
				Name:        "https-listen-port",
				Usage:       "HTTPS listen port",
				Value:       6443,
				Destination: &ServerConfig.HTTPSPort,
			},
			cli.IntFlag{
				Name:        "http-listen-port",
				Usage:       "HTTP listen port (for /healthz, HTTPS redirect, and port for TLS terminating LB)",
				Value:       0,
				Destination: &ServerConfig.HTTPPort,
			},
			cli.StringFlag{
				Name:        "data-dir,d",
				Usage:       "Folder to hold state default /var/lib/rancher/k3s or ${HOME}/.rancher/k3s if not root",
				Destination: &ServerConfig.DataDir,
			},
			cli.BoolFlag{
				Name:        "disable-agent",
				Usage:       "Do not run a local agent and register a local kubelet",
				Destination: &ServerConfig.DisableAgent,
			},
			cli.StringFlag{
				Name:        "log,l",
				Usage:       "Log to file",
				Destination: &ServerConfig.Log,
			},
			cli.StringFlag{
				Name:        "cluster-cidr",
				Usage:       "Network CIDR to use for pod IPs",
				Destination: &ServerConfig.ClusterCIDR,
				Value:       "10.42.0.0/16",
			},
			cli.StringFlag{
				Name:        "cluster-secret",
				Usage:       "Shared secret used to bootstrap a cluster",
				Destination: &ServerConfig.ClusterSecret,
				EnvVar:      "K3S_CLUSTER_SECRET",
			},
			cli.StringFlag{
				Name:        "service-cidr",
				Usage:       "Network CIDR to use for services IPs",
				Destination: &ServerConfig.ServiceCIDR,
				Value:       "10.43.0.0/16",
			},
			cli.StringFlag{
				Name:        "cluster-dns",
				Usage:       "Cluster IP for coredns service. Should be in your service-cidr range",
				Destination: &ServerConfig.ClusterDNS,
				Value:       "",
			},
			cli.StringSliceFlag{
				Name:  "no-deploy",
				Usage: "Do not deploy packaged components (valid items: coredns, servicelb, traefik)",
			},
			cli.StringFlag{
				Name:        "write-kubeconfig,o",
				Usage:       "Write kubeconfig for admin client to this file",
				Destination: &ServerConfig.KubeConfigOutput,
				EnvVar:      "K3S_KUBECONFIG_OUTPUT",
			},
			cli.StringFlag{
				Name:        "write-kubeconfig-mode",
				Usage:       "Write kubeconfig with this mode",
				Destination: &ServerConfig.KubeConfigMode,
				EnvVar:      "K3S_KUBECONFIG_MODE",
			},
			cli.StringSliceFlag{
				Name:  "tls-san",
				Usage: "Add additional hostname or IP as a Subject Alternative Name in the TLS cert",
				Value: &ServerConfig.KnownIPs,
			},
			cli.StringSliceFlag{
				Name:  "kube-apiserver-arg",
				Usage: "Customized flag for kube-apiserver process",
				Value: &ServerConfig.ExtraAPIArgs,
			},
			cli.StringSliceFlag{
				Name:  "kube-scheduler-arg",
				Usage: "Customized flag for kube-scheduler process",
				Value: &ServerConfig.ExtraSchedulerArgs,
			},
			cli.StringSliceFlag{
				Name:  "kube-controller-arg",
				Usage: "Customized flag for kube-controller-manager process",
				Value: &ServerConfig.ExtraControllerArgs,
			},
			cli.BoolFlag{
				Name:        "rootless",
				Usage:       "(experimental) Run rootless",
				Destination: &ServerConfig.Rootless,
			},
			NodeIPFlag,
			NodeNameFlag,
			DockerFlag,
			FlannelFlag,
			CRIEndpointFlag,
			ResolvConfFlag,
			ExtraKubeletArgs,
			ExtraKubeProxyArgs,
		},
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

package gob

import (
	"bytes";
"fmt";		// DELETE
	"gob";
	"os";
	"reflect";
	"strings";
	"testing";
	"unsafe";
)

type ET2 struct {
	x string;
}

type ET1 struct {
	a int;
	et2 *ET2;
	next *ET1;
}

func TestBasicEncoder(t *testing.T) {
	b := new(bytes.Buffer);
	enc := NewEncoder(b);
	et1 := new(ET1);
	et1.a = 7;
	et1.et2 = new(ET2);
	enc.Encode(et1);
	if enc.state.err != nil {
		t.Error("encoder fail:", enc.state.err)
	}

	// Decode the result by hand to verify;
	state := new(DecState);
	state.r = b;
	// The output should be:
	// 1) -7: the type id of ET1
	id1 := DecodeInt(state);
	if id1 >= 0 {
		t.Fatal("expected ET1 negative id; got", id1);
	}
	// 2) The wireType for ET1
	wire1 := new(wireType);
	err := Decode(b, wire1);
	if err != nil {
		t.Fatal("error decoding ET1 type:", err);
	}
	info := getTypeInfo(reflect.Typeof(ET1{}));
	trueWire1 := &wireType{name:"ET1", s: info.typeId.gobType().(*structType)};
	if !reflect.DeepEqual(wire1, trueWire1) {
		t.Fatalf("invalid wireType for ET1: expected %+v; got %+v\n", *trueWire1, *wire1);
	}
	// 3) -8: the type id of ET2
	id2 := DecodeInt(state);
	if id2 >= 0 {
		t.Fatal("expected ET2 negative id; got", id2);
	}
	// 4) The wireType for ET2
	wire2 := new(wireType);
	err = Decode(b, wire2);
	if err != nil {
		t.Fatal("error decoding ET2 type:", err);
	}
	info = getTypeInfo(reflect.Typeof(ET2{}));
	trueWire2 := &wireType{name:"ET2", s: info.typeId.gobType().(*structType)};
	if !reflect.DeepEqual(wire2, trueWire2) {
		t.Fatalf("invalid wireType for ET2: expected %+v; got %+v\n", *trueWire2, *wire2);
	}
	// 5) The type id for the et1 value
	newId1 := DecodeInt(state);
	if newId1 != -id1 {
		t.Fatal("expected Et1 id", -id1, "got", newId1);
	}
	// 6) The value of et1
	newEt1 := new(ET1);
	err = Decode(b, newEt1);
	if err != nil {
		t.Fatal("error decoding ET1 value:", err);
	}
	if !reflect.DeepEqual(et1, newEt1) {
		t.Fatalf("invalid data for et1: expected %+v; got %+v\n", *et1, *newEt1);
	}
	// 7) EOF
	if b.Len() != 0 {
		t.Error("not at eof;", b.Len(), "bytes left")
	}
}
<commit_msg>one more piece of testing: 2nd send should not send type info.<commit_after>// Copyright 2009 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.

package gob

import (
	"bytes";
"fmt";		// DELETE
	"gob";
	"os";
	"reflect";
	"strings";
	"testing";
	"unsafe";
)

type ET2 struct {
	x string;
}

type ET1 struct {
	a int;
	et2 *ET2;
	next *ET1;
}

func TestBasicEncoder(t *testing.T) {
	b := new(bytes.Buffer);
	enc := NewEncoder(b);
	et1 := new(ET1);
	et1.a = 7;
	et1.et2 = new(ET2);
	enc.Encode(et1);
	if enc.state.err != nil {
		t.Error("encoder fail:", enc.state.err)
	}

	// Decode the result by hand to verify;
	state := new(DecState);
	state.r = b;
	// The output should be:
	// 1) -7: the type id of ET1
	id1 := DecodeInt(state);
	if id1 >= 0 {
		t.Fatal("expected ET1 negative id; got", id1);
	}
	// 2) The wireType for ET1
	wire1 := new(wireType);
	err := Decode(b, wire1);
	if err != nil {
		t.Fatal("error decoding ET1 type:", err);
	}
	info := getTypeInfo(reflect.Typeof(ET1{}));
	trueWire1 := &wireType{name:"ET1", s: info.typeId.gobType().(*structType)};
	if !reflect.DeepEqual(wire1, trueWire1) {
		t.Fatalf("invalid wireType for ET1: expected %+v; got %+v\n", *trueWire1, *wire1);
	}
	// 3) -8: the type id of ET2
	id2 := DecodeInt(state);
	if id2 >= 0 {
		t.Fatal("expected ET2 negative id; got", id2);
	}
	// 4) The wireType for ET2
	wire2 := new(wireType);
	err = Decode(b, wire2);
	if err != nil {
		t.Fatal("error decoding ET2 type:", err);
	}
	info = getTypeInfo(reflect.Typeof(ET2{}));
	trueWire2 := &wireType{name:"ET2", s: info.typeId.gobType().(*structType)};
	if !reflect.DeepEqual(wire2, trueWire2) {
		t.Fatalf("invalid wireType for ET2: expected %+v; got %+v\n", *trueWire2, *wire2);
	}
	// 5) The type id for the et1 value
	newId1 := DecodeInt(state);
	if newId1 != -id1 {
		t.Fatal("expected Et1 id", -id1, "got", newId1);
	}
	// 6) The value of et1
	newEt1 := new(ET1);
	err = Decode(b, newEt1);
	if err != nil {
		t.Fatal("error decoding ET1 value:", err);
	}
	if !reflect.DeepEqual(et1, newEt1) {
		t.Fatalf("invalid data for et1: expected %+v; got %+v\n", *et1, *newEt1);
	}
	// 7) EOF
	if b.Len() != 0 {
		t.Error("not at eof;", b.Len(), "bytes left")
	}

	// Now do it again. This time we should see only the type id and value.
	b.Reset();
	enc.Encode(et1);
	if enc.state.err != nil {
		t.Error("2nd round: encoder fail:", enc.state.err)
	}
	// 5a) The type id for the et1 value
	newId1 = DecodeInt(state);
	if newId1 != -id1 {
		t.Fatal("2nd round: expected Et1 id", -id1, "got", newId1);
	}
	// 6a) The value of et1
	newEt1 = new(ET1);
	err = Decode(b, newEt1);
	if err != nil {
		t.Fatal("2nd round: error decoding ET1 value:", err);
	}
	if !reflect.DeepEqual(et1, newEt1) {
		t.Fatalf("2nd round: invalid data for et1: expected %+v; got %+v\n", *et1, *newEt1);
	}
	// 7a) EOF
	if b.Len() != 0 {
		t.Error("2nd round: not at eof;", b.Len(), "bytes left")
	}
}
<|endoftext|>


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

package context

import (
	"fmt"
	"html/template"
	"io"
	"net/http"
	"strings"
	"time"

	"github.com/go-macaron/cache"
	"github.com/go-macaron/csrf"
	"github.com/go-macaron/i18n"
	"github.com/go-macaron/session"
	log "gopkg.in/clog.v1"
	"gopkg.in/macaron.v1"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/pkg/auth"
	"github.com/gogits/gogs/pkg/form"
	"github.com/gogits/gogs/pkg/setting"
)

// Context represents context of a request.
type Context struct {
	*macaron.Context
	Cache   cache.Cache
	csrf    csrf.CSRF
	Flash   *session.Flash
	Session session.Store

	User        *models.User
	IsLogged    bool
	IsBasicAuth bool

	Repo *Repository
	Org  *Organization
}

// Title sets "Title" field in template data.
func (c *Context) Title(locale string) {
	c.Data["Title"] = c.Tr(locale)
}

// PageIs sets "PageIsxxx" field in template data.
func (c *Context) PageIs(name string) {
	c.Data["PageIs"+name] = true
}

// Require sets "Requirexxx" field in template data.
func (c *Context) Require(name string) {
	c.Data["Require"+name] = true
}

func (c *Context) RequireHighlightJS() {
	c.Require("HighlightJS")
}

func (c *Context) RequireSimpleMDE() {
	c.Require("SimpleMDE")
}

// FormErr sets "Err_xxx" field in template data.
func (c *Context) FormErr(names ...string) {
	for i := range names {
		c.Data["Err_"+names[i]] = true
	}
}

// UserID returns ID of current logged in user.
// It returns 0 if visitor is anonymous.
func (c *Context) UserID() int64 {
	if !c.IsLogged {
		return 0
	}
	return c.User.ID
}

// HasError returns true if error occurs in form validation.
func (ctx *Context) HasApiError() bool {
	hasErr, ok := ctx.Data["HasError"]
	if !ok {
		return false
	}
	return hasErr.(bool)
}

func (ctx *Context) GetErrMsg() string {
	return ctx.Data["ErrorMsg"].(string)
}

// HasError returns true if error occurs in form validation.
func (ctx *Context) HasError() bool {
	hasErr, ok := ctx.Data["HasError"]
	if !ok {
		return false
	}
	ctx.Flash.ErrorMsg = ctx.Data["ErrorMsg"].(string)
	ctx.Data["Flash"] = ctx.Flash
	return hasErr.(bool)
}

// HasValue returns true if value of given name exists.
func (ctx *Context) HasValue(name string) bool {
	_, ok := ctx.Data[name]
	return ok
}

// HTML responses template with given status.
func (ctx *Context) HTML(status int, name string) {
	log.Trace("Template: %s", name)
	ctx.Context.HTML(status, name)
}

// Success responses template with status http.StatusOK.
func (c *Context) Success(name string) {
	c.HTML(http.StatusOK, name)
}

// JSONSuccess responses JSON with status http.StatusOK.
func (c *Context) JSONSuccess(data interface{}) {
	c.JSON(http.StatusOK, data)
}

// SubURLRedirect responses redirection wtih given location and status.
// It prepends setting.AppSubURL to the location string.
func (c *Context) SubURLRedirect(location string, status ...int) {
	c.Redirect(setting.AppSubURL + location)
}

// RenderWithErr used for page has form validation but need to prompt error to users.
func (ctx *Context) RenderWithErr(msg, tpl string, f interface{}) {
	if f != nil {
		form.Assign(f, ctx.Data)
	}
	ctx.Flash.ErrorMsg = msg
	ctx.Data["Flash"] = ctx.Flash
	ctx.HTML(http.StatusOK, tpl)
}

// Handle handles and logs error by given status.
func (ctx *Context) Handle(status int, title string, err error) {
	switch status {
	case http.StatusNotFound:
		ctx.Data["Title"] = "Page Not Found"
	case http.StatusInternalServerError:
		ctx.Data["Title"] = "Internal Server Error"
		log.Error(2, "%s: %v", title, err)
		if !setting.ProdMode || (ctx.IsLogged && ctx.User.IsAdmin) {
			ctx.Data["ErrorMsg"] = err
		}
	}
	ctx.HTML(status, fmt.Sprintf("status/%d", status))
}

// NotFound renders the 404 page.
func (ctx *Context) NotFound() {
	ctx.Handle(http.StatusNotFound, "", nil)
}

// ServerError renders the 500 page.
func (c *Context) ServerError(title string, err error) {
	c.Handle(http.StatusInternalServerError, title, err)
}

// NotFoundOrServerError use error check function to determine if the error
// is about not found. It responses with 404 status code for not found error,
// or error context description for logging purpose of 500 server error.
func (c *Context) NotFoundOrServerError(title string, errck func(error) bool, err error) {
	if errck(err) {
		c.NotFound()
		return
	}
	c.ServerError(title, err)
}

func (ctx *Context) HandleText(status int, title string) {
	ctx.PlainText(status, []byte(title))
}

func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
	modtime := time.Now()
	for _, p := range params {
		switch v := p.(type) {
		case time.Time:
			modtime = v
		}
	}
	ctx.Resp.Header().Set("Content-Description", "File Transfer")
	ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
	ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name)
	ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
	ctx.Resp.Header().Set("Expires", "0")
	ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
	ctx.Resp.Header().Set("Pragma", "public")
	http.ServeContent(ctx.Resp, ctx.Req.Request, name, modtime, r)
}

// Contexter initializes a classic context for a request.
func Contexter() macaron.Handler {
	return func(c *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
		ctx := &Context{
			Context: c,
			Cache:   cache,
			csrf:    x,
			Flash:   f,
			Session: sess,
			Repo: &Repository{
				PullRequest: &PullRequest{},
			},
			Org: &Organization{},
		}

		if len(setting.HTTP.AccessControlAllowOrigin) > 0 {
			ctx.Header().Set("Access-Control-Allow-Origin", setting.HTTP.AccessControlAllowOrigin)
			ctx.Header().Set("'Access-Control-Allow-Credentials' ", "true")
			ctx.Header().Set("Access-Control-Max-Age", "3600")
			ctx.Header().Set("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")
		}

		// Compute current URL for real-time change language.
		ctx.Data["Link"] = setting.AppSubURL + strings.TrimSuffix(ctx.Req.URL.Path, "/")

		ctx.Data["PageStartTime"] = time.Now()

		// Get user from session if logined.
		ctx.User, ctx.IsBasicAuth = auth.SignedInUser(ctx.Context, ctx.Session)

		if ctx.User != nil {
			ctx.IsLogged = true
			ctx.Data["IsLogged"] = ctx.IsLogged
			ctx.Data["LoggedUser"] = ctx.User
			ctx.Data["LoggedUserID"] = ctx.User.ID
			ctx.Data["LoggedUserName"] = ctx.User.Name
			ctx.Data["IsAdmin"] = ctx.User.IsAdmin
		} else {
			ctx.Data["LoggedUserID"] = 0
			ctx.Data["LoggedUserName"] = ""
		}

		// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
		if ctx.Req.Method == "POST" && strings.Contains(ctx.Req.Header.Get("Content-Type"), "multipart/form-data") {
			if err := ctx.Req.ParseMultipartForm(setting.AttachmentMaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size
				ctx.Handle(500, "ParseMultipartForm", err)
				return
			}
		}

		ctx.Data["CSRFToken"] = x.GetToken()
		ctx.Data["CSRFTokenHTML"] = template.HTML(`<input type="hidden" name="_csrf" value="` + x.GetToken() + `">`)
		log.Trace("Session ID: %s", sess.ID())
		log.Trace("CSRF Token: %v", ctx.Data["CSRFToken"])

		ctx.Data["ShowRegistrationButton"] = setting.Service.ShowRegistrationButton
		ctx.Data["ShowFooterBranding"] = setting.ShowFooterBranding
		ctx.Data["ShowFooterVersion"] = setting.ShowFooterVersion

		c.Map(ctx)
	}
}
<commit_msg>repo: always response go-get meta when requested (#1878)<commit_after>// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package context

import (
	"fmt"
	"html/template"
	"io"
	"net/http"
	"path"
	"strings"
	"time"

	"github.com/Unknwon/com"
	"github.com/go-macaron/cache"
	"github.com/go-macaron/csrf"
	"github.com/go-macaron/i18n"
	"github.com/go-macaron/session"
	log "gopkg.in/clog.v1"
	"gopkg.in/macaron.v1"

	"github.com/gogits/gogs/models"
	"github.com/gogits/gogs/models/errors"
	"github.com/gogits/gogs/pkg/auth"
	"github.com/gogits/gogs/pkg/form"
	"github.com/gogits/gogs/pkg/setting"
)

// Context represents context of a request.
type Context struct {
	*macaron.Context
	Cache   cache.Cache
	csrf    csrf.CSRF
	Flash   *session.Flash
	Session session.Store

	Link        string // Current request URL
	User        *models.User
	IsLogged    bool
	IsBasicAuth bool

	Repo *Repository
	Org  *Organization
}

// Title sets "Title" field in template data.
func (c *Context) Title(locale string) {
	c.Data["Title"] = c.Tr(locale)
}

// PageIs sets "PageIsxxx" field in template data.
func (c *Context) PageIs(name string) {
	c.Data["PageIs"+name] = true
}

// Require sets "Requirexxx" field in template data.
func (c *Context) Require(name string) {
	c.Data["Require"+name] = true
}

func (c *Context) RequireHighlightJS() {
	c.Require("HighlightJS")
}

func (c *Context) RequireSimpleMDE() {
	c.Require("SimpleMDE")
}

// FormErr sets "Err_xxx" field in template data.
func (c *Context) FormErr(names ...string) {
	for i := range names {
		c.Data["Err_"+names[i]] = true
	}
}

// UserID returns ID of current logged in user.
// It returns 0 if visitor is anonymous.
func (c *Context) UserID() int64 {
	if !c.IsLogged {
		return 0
	}
	return c.User.ID
}

// HasError returns true if error occurs in form validation.
func (ctx *Context) HasApiError() bool {
	hasErr, ok := ctx.Data["HasError"]
	if !ok {
		return false
	}
	return hasErr.(bool)
}

func (ctx *Context) GetErrMsg() string {
	return ctx.Data["ErrorMsg"].(string)
}

// HasError returns true if error occurs in form validation.
func (ctx *Context) HasError() bool {
	hasErr, ok := ctx.Data["HasError"]
	if !ok {
		return false
	}
	ctx.Flash.ErrorMsg = ctx.Data["ErrorMsg"].(string)
	ctx.Data["Flash"] = ctx.Flash
	return hasErr.(bool)
}

// HasValue returns true if value of given name exists.
func (ctx *Context) HasValue(name string) bool {
	_, ok := ctx.Data[name]
	return ok
}

// HTML responses template with given status.
func (ctx *Context) HTML(status int, name string) {
	log.Trace("Template: %s", name)
	ctx.Context.HTML(status, name)
}

// Success responses template with status http.StatusOK.
func (c *Context) Success(name string) {
	c.HTML(http.StatusOK, name)
}

// JSONSuccess responses JSON with status http.StatusOK.
func (c *Context) JSONSuccess(data interface{}) {
	c.JSON(http.StatusOK, data)
}

// SubURLRedirect responses redirection wtih given location and status.
// It prepends setting.AppSubURL to the location string.
func (c *Context) SubURLRedirect(location string, status ...int) {
	c.Redirect(setting.AppSubURL + location)
}

// RenderWithErr used for page has form validation but need to prompt error to users.
func (ctx *Context) RenderWithErr(msg, tpl string, f interface{}) {
	if f != nil {
		form.Assign(f, ctx.Data)
	}
	ctx.Flash.ErrorMsg = msg
	ctx.Data["Flash"] = ctx.Flash
	ctx.HTML(http.StatusOK, tpl)
}

// Handle handles and logs error by given status.
func (ctx *Context) Handle(status int, title string, err error) {
	switch status {
	case http.StatusNotFound:
		ctx.Data["Title"] = "Page Not Found"
	case http.StatusInternalServerError:
		ctx.Data["Title"] = "Internal Server Error"
		log.Error(2, "%s: %v", title, err)
		if !setting.ProdMode || (ctx.IsLogged && ctx.User.IsAdmin) {
			ctx.Data["ErrorMsg"] = err
		}
	}
	ctx.HTML(status, fmt.Sprintf("status/%d", status))
}

// NotFound renders the 404 page.
func (ctx *Context) NotFound() {
	ctx.Handle(http.StatusNotFound, "", nil)
}

// ServerError renders the 500 page.
func (c *Context) ServerError(title string, err error) {
	c.Handle(http.StatusInternalServerError, title, err)
}

// NotFoundOrServerError use error check function to determine if the error
// is about not found. It responses with 404 status code for not found error,
// or error context description for logging purpose of 500 server error.
func (c *Context) NotFoundOrServerError(title string, errck func(error) bool, err error) {
	if errck(err) {
		c.NotFound()
		return
	}
	c.ServerError(title, err)
}

func (ctx *Context) HandleText(status int, title string) {
	ctx.PlainText(status, []byte(title))
}

func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
	modtime := time.Now()
	for _, p := range params {
		switch v := p.(type) {
		case time.Time:
			modtime = v
		}
	}
	ctx.Resp.Header().Set("Content-Description", "File Transfer")
	ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
	ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+name)
	ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
	ctx.Resp.Header().Set("Expires", "0")
	ctx.Resp.Header().Set("Cache-Control", "must-revalidate")
	ctx.Resp.Header().Set("Pragma", "public")
	http.ServeContent(ctx.Resp, ctx.Req.Request, name, modtime, r)
}

// Contexter initializes a classic context for a request.
func Contexter() macaron.Handler {
	return func(ctx *macaron.Context, l i18n.Locale, cache cache.Cache, sess session.Store, f *session.Flash, x csrf.CSRF) {
		c := &Context{
			Context: ctx,
			Cache:   cache,
			csrf:    x,
			Flash:   f,
			Session: sess,
			Link:    setting.AppSubURL + strings.TrimSuffix(ctx.Req.URL.Path, "/"),
			Repo: &Repository{
				PullRequest: &PullRequest{},
			},
			Org: &Organization{},
		}
		c.Data["Link"] = c.Link
		c.Data["PageStartTime"] = time.Now()

		// Quick responses appropriate go-get meta with status 200
		// regardless of if user have access to the repository,
		// or the repository does not exist at all.
		// This is particular a workaround for "go get" command which does not respect
		// .netrc file.
		if c.Query("go-get") == "1" {
			ownerName := ctx.Params(":username")
			repoName := ctx.Params(":reponame")
			branchName := "master"

			owner, err := models.GetUserByName(ownerName)
			if err != nil {
				c.NotFoundOrServerError("GetUserByName", errors.IsUserNotExist, err)
				return
			}

			repo, err := models.GetRepositoryByName(owner.ID, repoName)
			if err == nil && len(repo.DefaultBranch) > 0 {
				branchName = repo.DefaultBranch
			}

			prefix := setting.AppURL + path.Join(ownerName, repoName, "src", branchName)
			ctx.PlainText(http.StatusOK, []byte(com.Expand(`
<html>
	<head>
		<meta name="go-import" content="{GoGetImport} git {CloneLink}">
		<meta name="go-source" content="{GoGetImport} _ {GoDocDirectory} {GoDocFile}">
	</head>
	<body>
		go get {GoGetImport}
	</body>
</html>
`, map[string]string{
				"GoGetImport":    path.Join(setting.Domain, setting.AppSubURL, c.Link),
				"CloneLink":      models.ComposeHTTPSCloneURL(ownerName, repoName),
				"GoDocDirectory": prefix + "{/dir}",
				"GoDocFile":      prefix + "{/dir}/{file}#L{line}",
			})))
			return
		}

		if len(setting.HTTP.AccessControlAllowOrigin) > 0 {
			c.Header().Set("Access-Control-Allow-Origin", setting.HTTP.AccessControlAllowOrigin)
			c.Header().Set("'Access-Control-Allow-Credentials' ", "true")
			c.Header().Set("Access-Control-Max-Age", "3600")
			c.Header().Set("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With")
		}

		// Get user from session if logined.
		c.User, c.IsBasicAuth = auth.SignedInUser(c.Context, c.Session)

		if c.User != nil {
			c.IsLogged = true
			c.Data["IsLogged"] = c.IsLogged
			c.Data["LoggedUser"] = c.User
			c.Data["LoggedUserID"] = c.User.ID
			c.Data["LoggedUserName"] = c.User.Name
			c.Data["IsAdmin"] = c.User.IsAdmin
		} else {
			c.Data["LoggedUserID"] = 0
			c.Data["LoggedUserName"] = ""
		}

		// If request sends files, parse them here otherwise the Query() can't be parsed and the CsrfToken will be invalid.
		if c.Req.Method == "POST" && strings.Contains(c.Req.Header.Get("Content-Type"), "multipart/form-data") {
			if err := c.Req.ParseMultipartForm(setting.AttachmentMaxSize << 20); err != nil && !strings.Contains(err.Error(), "EOF") { // 32MB max size
				c.Handle(500, "ParseMultipartForm", err)
				return
			}
		}

		c.Data["CSRFToken"] = x.GetToken()
		c.Data["CSRFTokenHTML"] = template.HTML(`<input type="hidden" name="_csrf" value="` + x.GetToken() + `">`)
		log.Trace("Session ID: %s", sess.ID())
		log.Trace("CSRF Token: %v", c.Data["CSRFToken"])

		c.Data["ShowRegistrationButton"] = setting.Service.ShowRegistrationButton
		c.Data["ShowFooterBranding"] = setting.ShowFooterBranding
		c.Data["ShowFooterVersion"] = setting.ShowFooterVersion

		ctx.Map(c)
	}
}
<|endoftext|>