<commit_before>package MySQLProtocol

type Packet_HandshakeResponse41 struct {
	Packet

    capability uint32
    max_packet_size uint32
    character_set byte
    username string
    auth_response string
    database string
    auth_plugin_name string
    attributes map[string]string
}

func (packet Packet_HandshakeResponse41) GetPacketSize(context Context) (size uint64) {
    var totalattributesize uint64
    size += 4
    size += 4
    size += 1
    size += 23
    size += GetNulTerminatedStringSize(packet.username)
    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) {
        size += GetLengthEncodedStringSize(packet.auth_response)
    } else if Has_Flag(uint64(packet.capability), CLIENT_SECURE_CONNECTION) {
        size += 1
        size += uint64(len(packet.auth_response))
    } else {
        size += GetNulTerminatedStringSize(packet.auth_response)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_WITH_DB) {
        size += GetNulTerminatedStringSize(packet.database)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH) {
        size += GetNulTerminatedStringSize(packet.auth_plugin_name)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_ATTRS) {
        for key, attr := range packet.attributes {
            totalattributesize += GetLengthEncodedStringSize(attr)
            size += GetLengthEncodedStringSize(attr)

            totalattributesize += GetLengthEncodedStringSize(key)
            size += GetLengthEncodedStringSize(key)
        }
        size += GetLengthEncodedIntegerSize(totalattributesize)
    }
	return size
}

func (packet Packet_HandshakeResponse41) ToPacket(context Context) (data []byte) {
	size := packet.GetPacketSize(context)

	data = make([]byte, 0, size+4)

	data = append(data, BuildFixedLengthInteger3(uint32(size))...)
	data = append(data, BuildFixedLengthInteger1(packet.sequence_id)...)

    data = append(data, BuildFixedLengthInteger4(packet.capability)...)
    data = append(data, BuildFixedLengthInteger4(packet.max_packet_size)...)
    data = append(data, BuildFixedLengthInteger1(packet.character_set)...)
    data = append(data, BuildFixedLengthString("", 23)...)
    data = append(data, BuildNulTerminatedString(packet.username)...)

    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) {
        data = append(data, BuildLengthEncodedString(packet.auth_response)...)
    } else if Has_Flag(uint64(packet.capability), CLIENT_SECURE_CONNECTION) {
        data = append(data, BuildFixedLengthInteger1(uint8(len(packet.auth_response)))...)
        data = append(data, BuildFixedLengthString(packet.auth_response, uint(len(packet.auth_response)))...)
    } else {
        data = append(data, BuildNulTerminatedString(packet.auth_response)...)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_WITH_DB) {
        data = append(data, BuildNulTerminatedString(packet.database)...)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH) {
        data = append(data, BuildNulTerminatedString(packet.auth_plugin_name)...)
    }

    var totalattributesize uint64
    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_ATTRS) {
        for key, attr := range packet.attributes {
            totalattributesize += GetLengthEncodedStringSize(key)
            totalattributesize += GetLengthEncodedStringSize(attr)
        }
        data = append(data, BuildLengthEncodedInteger(totalattributesize)...)
        for key, attr := range packet.attributes {
            data = append(data, BuildLengthEncodedString(key)...)
            data = append(data, BuildLengthEncodedString(attr)...)
        }
    }

	return data
}

func (packet *Packet_HandshakeResponse41) FromPacket(context Context, data Proto) {
	data.GetFixedLengthInteger3()
	packet.sequence_id = data.GetFixedLengthInteger1()

    packet.capability = data.GetFixedLengthInteger4()
    packet.max_packet_size = data.GetFixedLengthInteger4()
    packet.character_set = data.GetFixedLengthInteger1()
    data.GetFixedLengthString(23)
    packet.username = data.GetNulTerminatedString()
    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) {
        packet.auth_response = data.GetLengthEncodedString()
    } else if Has_Flag(uint64(packet.capability), CLIENT_SECURE_CONNECTION) {
        length := data.GetFixedLengthInteger1()
        packet.auth_response = data.GetFixedLengthString(uint(length))
    } else {
        packet.auth_response = data.GetNulTerminatedString()
    }

    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_WITH_DB) {
        packet.database = data.GetNulTerminatedString()
    }

    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH) {
        packet.auth_plugin_name = data.GetNulTerminatedString()
    }

    packet.attributes = make(map[string]string, 0)
    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_ATTRS) {
        data.GetLengthEncodedInteger()
        for data.HasRemainingData() {
            key := data.GetLengthEncodedString()
            val := data.GetLengthEncodedString()
            packet.attributes[key] = val
        }
    }
}
<commit_msg>To [][2]string<commit_after>package MySQLProtocol

type Packet_HandshakeResponse41 struct {
	Packet

    capability uint32
    max_packet_size uint32
    character_set byte
    username string
    auth_response string
    database string
    auth_plugin_name string
    attributes [][2]string
}

func (packet Packet_HandshakeResponse41) GetPacketSize(context Context) (size uint64) {
    var totalattributesize uint64
    size += 4
    size += 4
    size += 1
    size += 23
    size += GetNulTerminatedStringSize(packet.username)
    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) {
        size += GetLengthEncodedStringSize(packet.auth_response)
    } else if Has_Flag(uint64(packet.capability), CLIENT_SECURE_CONNECTION) {
        size += 1
        size += uint64(len(packet.auth_response))
    } else {
        size += GetNulTerminatedStringSize(packet.auth_response)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_WITH_DB) {
        size += GetNulTerminatedStringSize(packet.database)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH) {
        size += GetNulTerminatedStringSize(packet.auth_plugin_name)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_ATTRS) {
        for _, attribute := range packet.attributes {
            totalattributesize += GetLengthEncodedStringSize(attribute[0])
            size += GetLengthEncodedStringSize(attribute[0])

            totalattributesize += GetLengthEncodedStringSize(attribute[1])
            size += GetLengthEncodedStringSize(attribute[1])
        }
        size += GetLengthEncodedIntegerSize(totalattributesize)
    }
	return size
}

func (packet Packet_HandshakeResponse41) ToPacket(context Context) (data []byte) {
	size := packet.GetPacketSize(context)

	data = make([]byte, 0, size+4)

	data = append(data, BuildFixedLengthInteger3(uint32(size))...)
	data = append(data, BuildFixedLengthInteger1(packet.sequence_id)...)

    data = append(data, BuildFixedLengthInteger4(packet.capability)...)
    data = append(data, BuildFixedLengthInteger4(packet.max_packet_size)...)
    data = append(data, BuildFixedLengthInteger1(packet.character_set)...)
    data = append(data, BuildFixedLengthString("", 23)...)
    data = append(data, BuildNulTerminatedString(packet.username)...)

    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) {
        data = append(data, BuildLengthEncodedString(packet.auth_response)...)
    } else if Has_Flag(uint64(packet.capability), CLIENT_SECURE_CONNECTION) {
        data = append(data, BuildFixedLengthInteger1(uint8(len(packet.auth_response)))...)
        data = append(data, BuildFixedLengthString(packet.auth_response, uint(len(packet.auth_response)))...)
    } else {
        data = append(data, BuildNulTerminatedString(packet.auth_response)...)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_WITH_DB) {
        data = append(data, BuildNulTerminatedString(packet.database)...)
    }

    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH) {
        data = append(data, BuildNulTerminatedString(packet.auth_plugin_name)...)
    }

    var totalattributesize uint64
    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_ATTRS) {
        for _, attribute := range packet.attributes {
            totalattributesize += GetLengthEncodedStringSize(attribute[0])
            totalattributesize += GetLengthEncodedStringSize(attribute[1])
        }
        data = append(data, BuildLengthEncodedInteger(totalattributesize)...)
        for _, attribute := range packet.attributes {
            data = append(data, BuildLengthEncodedString(attribute[0])...)
            data = append(data, BuildLengthEncodedString(attribute[1])...)
        }
    }

	return data
}

func (packet *Packet_HandshakeResponse41) FromPacket(context Context, data Proto) {
	data.GetFixedLengthInteger3()
	packet.sequence_id = data.GetFixedLengthInteger1()

    packet.capability = data.GetFixedLengthInteger4()
    packet.max_packet_size = data.GetFixedLengthInteger4()
    packet.character_set = data.GetFixedLengthInteger1()
    data.GetFixedLengthString(23)
    packet.username = data.GetNulTerminatedString()
    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) {
        packet.auth_response = data.GetLengthEncodedString()
    } else if Has_Flag(uint64(packet.capability), CLIENT_SECURE_CONNECTION) {
        length := data.GetFixedLengthInteger1()
        packet.auth_response = data.GetFixedLengthString(uint(length))
    } else {
        packet.auth_response = data.GetNulTerminatedString()
    }

    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_WITH_DB) {
        packet.database = data.GetNulTerminatedString()
    }

    if Has_Flag(uint64(packet.capability), CLIENT_PLUGIN_AUTH) {
        packet.auth_plugin_name = data.GetNulTerminatedString()
    }

    packet.attributes = make([][2]string, 0)
    if Has_Flag(uint64(packet.capability), CLIENT_CONNECT_ATTRS) {
        data.GetLengthEncodedInteger()
        for data.HasRemainingData() {
            key := data.GetLengthEncodedString()
            val := data.GetLengthEncodedString()
            packet.attributes = append(packet.attributes, [2]string{key, val})
        }
    }
}
<|endoftext|>


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

// Build initialization (after flag parsing).

package work

import (
	"cmd/go/internal/base"
	"cmd/go/internal/cfg"
	"cmd/go/internal/load"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

func BuildInit() {
	load.ModInit()
	instrumentInit()
	buildModeInit()

	// Make sure -pkgdir is absolute, because we run commands
	// in different directories.
	if cfg.BuildPkgdir != "" && !filepath.IsAbs(cfg.BuildPkgdir) {
		p, err := filepath.Abs(cfg.BuildPkgdir)
		if err != nil {
			fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err)
			os.Exit(2)
		}
		cfg.BuildPkgdir = p
	}
}

func instrumentInit() {
	if !cfg.BuildRace && !cfg.BuildMSan {
		return
	}
	if cfg.BuildRace && cfg.BuildMSan {
		fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
		os.Exit(2)
	}
	if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64" && cfg.Goarch != "arm64") {
		fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
		os.Exit(2)
	}
	if cfg.BuildRace {
		platform := cfg.Goos + "/" + cfg.Goarch
		switch platform {
		default:
			fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
			os.Exit(2)
		case "linux/amd64", "linux/ppc64le", "freebsd/amd64", "netbsd/amd64", "darwin/amd64", "windows/amd64":
			// race supported on these platforms
		}
	}
	mode := "race"
	if cfg.BuildMSan {
		mode = "msan"
	}
	modeFlag := "-" + mode

	if !cfg.BuildContext.CgoEnabled {
		fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag)
		os.Exit(2)
	}
	forcedGcflags = append(forcedGcflags, modeFlag)
	forcedLdflags = append(forcedLdflags, modeFlag)

	if cfg.BuildContext.InstallSuffix != "" {
		cfg.BuildContext.InstallSuffix += "_"
	}
	cfg.BuildContext.InstallSuffix += mode
	cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, mode)
}

func buildModeInit() {
	gccgo := cfg.BuildToolchainName == "gccgo"
	var codegenArg string
	platform := cfg.Goos + "/" + cfg.Goarch
	switch cfg.BuildBuildmode {
	case "archive":
		pkgsFilter = pkgsNotMain
	case "c-archive":
		pkgsFilter = oneMainPkg
		switch platform {
		case "darwin/arm", "darwin/arm64":
			codegenArg = "-shared"
		default:
			switch cfg.Goos {
			case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
				if platform == "linux/ppc64" {
					base.Fatalf("-buildmode=c-archive not supported on %s\n", platform)
				}
				// Use -shared so that the result is
				// suitable for inclusion in a PIE or
				// shared library.
				codegenArg = "-shared"
			}
		}
		if gccgo {
			codegenArg = "-fPIC"
		}
		cfg.ExeSuffix = ".a"
		ldBuildmode = "c-archive"
	case "c-shared":
		pkgsFilter = oneMainPkg
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x",
				"android/amd64", "android/arm", "android/arm64", "android/386",
				"freebsd/amd64":
				codegenArg = "-shared"
			case "darwin/amd64", "darwin/386":
			case "windows/amd64", "windows/386":
				// Do not add usual .exe suffix to the .dll file.
				cfg.ExeSuffix = ""
			default:
				base.Fatalf("-buildmode=c-shared not supported on %s\n", platform)
			}
		}
		ldBuildmode = "c-shared"
	case "default":
		switch platform {
		case "android/arm", "android/arm64", "android/amd64", "android/386":
			codegenArg = "-shared"
			ldBuildmode = "pie"
		case "darwin/arm", "darwin/arm64":
			codegenArg = "-shared"
			fallthrough
		default:
			ldBuildmode = "exe"
		}
		if gccgo {
			codegenArg = ""
		}
	case "exe":
		pkgsFilter = pkgsMain
		ldBuildmode = "exe"
		// Set the pkgsFilter to oneMainPkg if the user passed a specific binary output
		// and is using buildmode=exe for a better error message.
		// See issue #20017.
		if cfg.BuildO != "" {
			pkgsFilter = oneMainPkg
		}
	case "pie":
		if cfg.BuildRace {
			base.Fatalf("-buildmode=pie not supported when -race is enabled")
		}
		if gccgo {
			codegenArg = "-fPIE"
		} else {
			switch platform {
			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
				"android/amd64", "android/arm", "android/arm64", "android/386",
				"freebsd/amd64":
				codegenArg = "-shared"
			case "darwin/amd64":
				codegenArg = "-shared"
			default:
				base.Fatalf("-buildmode=pie not supported on %s\n", platform)
			}
		}
		ldBuildmode = "pie"
	case "shared":
		pkgsFilter = pkgsNotMain
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
			default:
				base.Fatalf("-buildmode=shared not supported on %s\n", platform)
			}
			codegenArg = "-dynlink"
		}
		if cfg.BuildO != "" {
			base.Fatalf("-buildmode=shared and -o not supported together")
		}
		ldBuildmode = "shared"
	case "plugin":
		pkgsFilter = oneMainPkg
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le",
				"android/amd64", "android/arm", "android/arm64", "android/386":
			case "darwin/amd64":
				// Skip DWARF generation due to #21647
				forcedLdflags = append(forcedLdflags, "-w")
			default:
				base.Fatalf("-buildmode=plugin not supported on %s\n", platform)
			}
			codegenArg = "-dynlink"
		}
		cfg.ExeSuffix = ".so"
		ldBuildmode = "plugin"
	default:
		base.Fatalf("buildmode=%s not supported", cfg.BuildBuildmode)
	}
	if cfg.BuildLinkshared {
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
				forcedAsmflags = append(forcedAsmflags, "-D=GOBUILDMODE_shared=1")
			default:
				base.Fatalf("-linkshared not supported on %s\n", platform)
			}
			codegenArg = "-dynlink"
			// TODO(mwhudson): remove -w when that gets fixed in linker.
			forcedLdflags = append(forcedLdflags, "-linkshared", "-w")
		}
	}
	if codegenArg != "" {
		if gccgo {
			forcedGccgoflags = append([]string{codegenArg}, forcedGccgoflags...)
		} else {
			forcedAsmflags = append([]string{codegenArg}, forcedAsmflags...)
			forcedGcflags = append([]string{codegenArg}, forcedGcflags...)
		}
		// Don't alter InstallSuffix when modifying default codegen args.
		if cfg.BuildBuildmode != "default" || cfg.BuildLinkshared {
			if cfg.BuildContext.InstallSuffix != "" {
				cfg.BuildContext.InstallSuffix += "_"
			}
			cfg.BuildContext.InstallSuffix += codegenArg[1:]
		}
	}

	switch cfg.BuildMod {
	case "":
		// ok
	case "readonly", "vendor":
		if load.ModLookup == nil && !inGOFLAGS("-mod") {
			base.Fatalf("build flag -mod=%s only valid when using modules", cfg.BuildMod)
		}
	default:
		base.Fatalf("-mod=%s not supported (can be '', 'readonly', or 'vendor')", cfg.BuildMod)
	}
}

func inGOFLAGS(flag string) bool {
	for _, goflag := range base.GOFLAGS() {
		name := goflag
		if strings.HasPrefix(name, "--") {
			name = name[1:]
		}
		if i := strings.Index(name, "="); i >= 0 {
			name = name[:i]
		}
		if name == flag {
			return true
		}
	}
	return false
}
<commit_msg>cmd/go: allow buildmode c-archive for gccgo on ppc64<commit_after>// Copyright 2017 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.

// Build initialization (after flag parsing).

package work

import (
	"cmd/go/internal/base"
	"cmd/go/internal/cfg"
	"cmd/go/internal/load"
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

func BuildInit() {
	load.ModInit()
	instrumentInit()
	buildModeInit()

	// Make sure -pkgdir is absolute, because we run commands
	// in different directories.
	if cfg.BuildPkgdir != "" && !filepath.IsAbs(cfg.BuildPkgdir) {
		p, err := filepath.Abs(cfg.BuildPkgdir)
		if err != nil {
			fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err)
			os.Exit(2)
		}
		cfg.BuildPkgdir = p
	}
}

func instrumentInit() {
	if !cfg.BuildRace && !cfg.BuildMSan {
		return
	}
	if cfg.BuildRace && cfg.BuildMSan {
		fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
		os.Exit(2)
	}
	if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64" && cfg.Goarch != "arm64") {
		fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
		os.Exit(2)
	}
	if cfg.BuildRace {
		platform := cfg.Goos + "/" + cfg.Goarch
		switch platform {
		default:
			fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
			os.Exit(2)
		case "linux/amd64", "linux/ppc64le", "freebsd/amd64", "netbsd/amd64", "darwin/amd64", "windows/amd64":
			// race supported on these platforms
		}
	}
	mode := "race"
	if cfg.BuildMSan {
		mode = "msan"
	}
	modeFlag := "-" + mode

	if !cfg.BuildContext.CgoEnabled {
		fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag)
		os.Exit(2)
	}
	forcedGcflags = append(forcedGcflags, modeFlag)
	forcedLdflags = append(forcedLdflags, modeFlag)

	if cfg.BuildContext.InstallSuffix != "" {
		cfg.BuildContext.InstallSuffix += "_"
	}
	cfg.BuildContext.InstallSuffix += mode
	cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, mode)
}

func buildModeInit() {
	gccgo := cfg.BuildToolchainName == "gccgo"
	var codegenArg string
	platform := cfg.Goos + "/" + cfg.Goarch
	switch cfg.BuildBuildmode {
	case "archive":
		pkgsFilter = pkgsNotMain
	case "c-archive":
		pkgsFilter = oneMainPkg
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "darwin/arm", "darwin/arm64":
				codegenArg = "-shared"
			default:
				switch cfg.Goos {
				case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
					if platform == "linux/ppc64" {
						base.Fatalf("-buildmode=c-archive not supported on %s\n", platform)
					}
					// Use -shared so that the result is
					// suitable for inclusion in a PIE or
					// shared library.
					codegenArg = "-shared"
				}
			}
		}
		cfg.ExeSuffix = ".a"
		ldBuildmode = "c-archive"
	case "c-shared":
		pkgsFilter = oneMainPkg
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x",
				"android/amd64", "android/arm", "android/arm64", "android/386",
				"freebsd/amd64":
				codegenArg = "-shared"
			case "darwin/amd64", "darwin/386":
			case "windows/amd64", "windows/386":
				// Do not add usual .exe suffix to the .dll file.
				cfg.ExeSuffix = ""
			default:
				base.Fatalf("-buildmode=c-shared not supported on %s\n", platform)
			}
		}
		ldBuildmode = "c-shared"
	case "default":
		switch platform {
		case "android/arm", "android/arm64", "android/amd64", "android/386":
			codegenArg = "-shared"
			ldBuildmode = "pie"
		case "darwin/arm", "darwin/arm64":
			codegenArg = "-shared"
			fallthrough
		default:
			ldBuildmode = "exe"
		}
		if gccgo {
			codegenArg = ""
		}
	case "exe":
		pkgsFilter = pkgsMain
		ldBuildmode = "exe"
		// Set the pkgsFilter to oneMainPkg if the user passed a specific binary output
		// and is using buildmode=exe for a better error message.
		// See issue #20017.
		if cfg.BuildO != "" {
			pkgsFilter = oneMainPkg
		}
	case "pie":
		if cfg.BuildRace {
			base.Fatalf("-buildmode=pie not supported when -race is enabled")
		}
		if gccgo {
			codegenArg = "-fPIE"
		} else {
			switch platform {
			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
				"android/amd64", "android/arm", "android/arm64", "android/386",
				"freebsd/amd64":
				codegenArg = "-shared"
			case "darwin/amd64":
				codegenArg = "-shared"
			default:
				base.Fatalf("-buildmode=pie not supported on %s\n", platform)
			}
		}
		ldBuildmode = "pie"
	case "shared":
		pkgsFilter = pkgsNotMain
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
			default:
				base.Fatalf("-buildmode=shared not supported on %s\n", platform)
			}
			codegenArg = "-dynlink"
		}
		if cfg.BuildO != "" {
			base.Fatalf("-buildmode=shared and -o not supported together")
		}
		ldBuildmode = "shared"
	case "plugin":
		pkgsFilter = oneMainPkg
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le",
				"android/amd64", "android/arm", "android/arm64", "android/386":
			case "darwin/amd64":
				// Skip DWARF generation due to #21647
				forcedLdflags = append(forcedLdflags, "-w")
			default:
				base.Fatalf("-buildmode=plugin not supported on %s\n", platform)
			}
			codegenArg = "-dynlink"
		}
		cfg.ExeSuffix = ".so"
		ldBuildmode = "plugin"
	default:
		base.Fatalf("buildmode=%s not supported", cfg.BuildBuildmode)
	}
	if cfg.BuildLinkshared {
		if gccgo {
			codegenArg = "-fPIC"
		} else {
			switch platform {
			case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
				forcedAsmflags = append(forcedAsmflags, "-D=GOBUILDMODE_shared=1")
			default:
				base.Fatalf("-linkshared not supported on %s\n", platform)
			}
			codegenArg = "-dynlink"
			// TODO(mwhudson): remove -w when that gets fixed in linker.
			forcedLdflags = append(forcedLdflags, "-linkshared", "-w")
		}
	}
	if codegenArg != "" {
		if gccgo {
			forcedGccgoflags = append([]string{codegenArg}, forcedGccgoflags...)
		} else {
			forcedAsmflags = append([]string{codegenArg}, forcedAsmflags...)
			forcedGcflags = append([]string{codegenArg}, forcedGcflags...)
		}
		// Don't alter InstallSuffix when modifying default codegen args.
		if cfg.BuildBuildmode != "default" || cfg.BuildLinkshared {
			if cfg.BuildContext.InstallSuffix != "" {
				cfg.BuildContext.InstallSuffix += "_"
			}
			cfg.BuildContext.InstallSuffix += codegenArg[1:]
		}
	}

	switch cfg.BuildMod {
	case "":
		// ok
	case "readonly", "vendor":
		if load.ModLookup == nil && !inGOFLAGS("-mod") {
			base.Fatalf("build flag -mod=%s only valid when using modules", cfg.BuildMod)
		}
	default:
		base.Fatalf("-mod=%s not supported (can be '', 'readonly', or 'vendor')", cfg.BuildMod)
	}
}

func inGOFLAGS(flag string) bool {
	for _, goflag := range base.GOFLAGS() {
		name := goflag
		if strings.HasPrefix(name, "--") {
			name = name[1:]
		}
		if i := strings.Index(name, "="); i >= 0 {
			name = name[:i]
		}
		if name == flag {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "errors"
)

const DEFAULT_KEEP_COUNT = 2

type config struct {
    dirName string // the name of the target directory as specified in the command line
    dirPtr *os.File // the target directory, if opened successfully
    keepCount int
}

// initializes a blank config instance from command line arguments or with defaults
// if command line arguments values are not available
func (config *config) init(args []string) error {

    var err error

    if len(args) < 2 {
        return errors.New("no target directory specified")
    }

    //
    // defaults
    //

    config.keepCount = DEFAULT_KEEP_COUNT

    //
    // command line arguments
    //

    config.dirName = args[1]

    config.dirPtr, err = os.Open(config.dirName)

    if err != nil {
        return err
    }

    return nil
}
<commit_msg>corrected keep from 2 to 10<commit_after>package main

import (
    "os"
    "errors"
)

const DEFAULT_KEEP_COUNT = 10

type config struct {
    dirName string // the name of the target directory as specified in the command line
    dirPtr *os.File // the target directory, if opened successfully
    keepCount int
}

// initializes a blank config instance from command line arguments or with defaults
// if command line arguments values are not available
func (config *config) init(args []string) error {

    var err error

    if len(args) < 2 {
        return errors.New("no target directory specified")
    }

    //
    // defaults
    //

    config.keepCount = DEFAULT_KEEP_COUNT

    //
    // command line arguments
    //

    config.dirName = args[1]

    config.dirPtr, err = os.Open(config.dirName)

    if err != nil {
        return err
    }

    return nil
}
<|endoftext|>


<commit_before>package commands

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

	"github.com/git-lfs/git-lfs/errors"
	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/git/githistory"
	"github.com/git-lfs/git-lfs/tasklog"
	"github.com/git-lfs/gitobj"
	"github.com/spf13/cobra"
)

var (
	// migrateIncludeRefs is a set of Git references to explicitly include
	// in the migration.
	migrateIncludeRefs []string
	// migrateExcludeRefs is a set of Git references to explicitly exclude
	// in the migration.
	migrateExcludeRefs []string

	// migrateYes indicates that an answer of 'yes' should be presumed
	// whenever 'git lfs migrate' asks for user input.
	migrateYes bool

	// migrateSkipFetch assumes that the client has the latest copy of
	// remote references, and thus should not contact the remote for a set
	// of updated references.
	migrateSkipFetch bool

	// migrateEverything indicates the presence of the --everything flag,
	// and instructs 'git lfs migrate' to migrate all local references.
	migrateEverything bool

	// migrateVerbose enables verbose logging
	migrateVerbose bool

	// objectMapFile is the path to the map of old sha1 to new sha1
	// commits
	objectMapFilePath string

	// migrateNoRewrite is the flag indicating whether or not the
	// command should rewrite git history
	migrateNoRewrite bool
	// migrateCommitMessage is the message to use with the commit generated
	// by the migrate command
	migrateCommitMessage string

	// exportRemote is the remote from which to download objects when
	// performing an export
	exportRemote string

	// migrateFixup is the flag indicating whether or not to infer the
	// included and excluded filepath patterns.
	migrateFixup bool
)

// migrate takes the given command and arguments, *gitobj.ObjectDatabase, as well
// as a BlobRewriteFn to apply, and performs a migration.
func migrate(args []string, r *githistory.Rewriter, l *tasklog.Logger, opts *githistory.RewriteOptions) {
	requireInRepo()

	opts, err := rewriteOptions(args, opts, l)
	if err != nil {
		ExitWithError(err)
	}

	_, err = r.Rewrite(opts)
	if err != nil {
		ExitWithError(err)
	}
}

// getObjectDatabase creates a *git.ObjectDatabase from the filesystem pointed
// at the .git directory of the currently checked-out repository.
func getObjectDatabase() (*gitobj.ObjectDatabase, error) {
	dir, err := git.GitCommonDir()
	if err != nil {
		return nil, errors.Wrap(err, "cannot open root")
	}
	return gitobj.FromFilesystem(filepath.Join(dir, "objects"), cfg.TempDir())
}

// rewriteOptions returns *githistory.RewriteOptions able to be passed to a
// *githistory.Rewriter that reflect the current arguments and flags passed to
// an invocation of git-lfs-migrate(1).
//
// It is merged with the given "opts". In other words, an identical "opts" is
// returned, where the Include and Exclude fields have been filled based on the
// following rules:
//
// The included and excluded references are determined based on the output of
// includeExcludeRefs (see below for documentation and detail).
//
// If any of the above could not be determined without error, that error will be
// returned immediately.
func rewriteOptions(args []string, opts *githistory.RewriteOptions, l *tasklog.Logger) (*githistory.RewriteOptions, error) {
	include, exclude, err := includeExcludeRefs(l, args)
	if err != nil {
		return nil, err
	}

	return &githistory.RewriteOptions{
		Include: include,
		Exclude: exclude,

		UpdateRefs:        opts.UpdateRefs,
		Verbose:           opts.Verbose,
		ObjectMapFilePath: opts.ObjectMapFilePath,

		BlobFn:            opts.BlobFn,
		TreePreCallbackFn: opts.TreePreCallbackFn,
		TreeCallbackFn:    opts.TreeCallbackFn,
	}, nil
}

// includeExcludeRefs returns fully-qualified sets of references to include, and
// exclude, or an error if those could not be determined.
//
// They are determined based on the following rules:
//
//   - Include all local refs/heads/<branch> references for each branch
//     specified as an argument.
//   - Include the currently checked out branch if no branches are given as
//     arguments and the --include-ref= or --exclude-ref= flag(s) aren't given.
//   - Include all references given in --include-ref=<ref>.
//   - Exclude all references given in --exclude-ref=<ref>.
func includeExcludeRefs(l *tasklog.Logger, args []string) (include, exclude []string, err error) {
	hardcore := len(migrateIncludeRefs) > 0 || len(migrateExcludeRefs) > 0

	if len(args) == 0 && !hardcore && !migrateEverything {
		// If no branches were given explicitly AND neither
		// --include-ref or --exclude-ref flags were given, then add the
		// currently checked out reference.
		current, err := currentRefToMigrate()
		if err != nil {
			return nil, nil, err
		}
		args = append(args, current.Name)
	}

	if migrateEverything && len(args) > 0 {
		return nil, nil, errors.New("fatal: cannot use --everything with explicit reference arguments")
	}

	for _, name := range args {
		var excluded bool
		if strings.HasPrefix("^", name) {
			name = name[1:]
			excluded = true
		}

		// Then, loop through each branch given, resolve that reference,
		// and include it.
		ref, err := git.ResolveRef(name)
		if err != nil {
			return nil, nil, err
		}

		if excluded {
			exclude = append(exclude, ref.Refspec())
		} else {
			include = append(include, ref.Refspec())
		}
	}

	if hardcore {
		if migrateEverything {
			return nil, nil, errors.New("fatal: cannot use --everything with --include-ref or --exclude-ref")
		}

		// If either --include-ref=<ref> or --exclude-ref=<ref> were
		// given, append those to the include and excluded reference
		// set, respectively.
		include = append(include, migrateIncludeRefs...)
		exclude = append(exclude, migrateExcludeRefs...)
	} else if migrateEverything {
		refs, err := git.AllRefsIn("")
		if err != nil {
			return nil, nil, err
		}

		for _, ref := range refs {
			switch ref.Type {
			case git.RefTypeLocalBranch, git.RefTypeLocalTag,
				git.RefTypeRemoteBranch:

				include = append(include, ref.Refspec())
			case git.RefTypeOther:
				parts := strings.SplitN(ref.Refspec(), "/", 3)
				if len(parts) < 2 {
					continue
				}

				switch parts[1] {
				// The following are GitLab-, GitHub-, VSTS-,
				// and BitBucket-specific reference naming
				// conventions.
				case "merge-requests", "pull", "pull-requests":
					include = append(include, ref.Refspec())
				}
			}
		}
	} else {
		bare, err := git.IsBare()
		if err != nil {
			return nil, nil, errors.Wrap(err, "fatal: unable to determine bareness")
		}

		if !bare {
			// Otherwise, if neither --include-ref=<ref> or
			// --exclude-ref=<ref> were given, include no additional
			// references, and exclude all remote references that
			// are remote branches or remote tags.
			remoteRefs, err := getRemoteRefs(l)
			if err != nil {
				return nil, nil, err
			}

			for _, refs := range remoteRefs {
				for _, ref := range refs {
					exclude = append(exclude, ref.Refspec())
				}
			}
		}
	}

	return include, exclude, nil
}

// getRemoteRefs returns a fully qualified set of references belonging to all
// remotes known by the currently checked-out repository, or an error if those
// references could not be determined.
func getRemoteRefs(l *tasklog.Logger) (map[string][]*git.Ref, error) {
	refs := make(map[string][]*git.Ref)

	remotes, err := git.RemoteList()
	if err != nil {
		return nil, err
	}

	if !migrateSkipFetch {
		w := l.Waiter("migrate: Fetching remote refs")
		if err := git.Fetch(remotes...); err != nil {
			return nil, err
		}
		w.Complete()
	}

	for _, remote := range remotes {
		var refsForRemote []*git.Ref
		if migrateSkipFetch {
			refsForRemote, err = git.CachedRemoteRefs(remote)
		} else {
			refsForRemote, err = git.RemoteRefs(remote)
		}

		if err != nil {
			return nil, err
		}

		for i, rr := range refsForRemote {
			// HACK(@ttaylorr): add remote name to fully-qualify
			// references:
			refsForRemote[i].Name =
				fmt.Sprintf("%s/%s", remote, rr.Name)
		}

		refs[remote] = refsForRemote
	}

	return refs, nil
}

// formatRefName returns the fully-qualified name for the given Git reference
// "ref".
func formatRefName(ref *git.Ref, remote string) string {
	var name []string

	switch ref.Type {
	case git.RefTypeRemoteBranch:
		name = []string{"refs", "remotes", remote, ref.Name}
	default:
		return ref.Name
	}
	return strings.Join(name, "/")

}

// currentRefToMigrate returns the fully-qualified name of the currently
// checked-out reference, or an error if the reference's type was not a local
// branch.
func currentRefToMigrate() (*git.Ref, error) {
	current, err := git.CurrentRef()
	if err != nil {
		return nil, err
	}

	if current.Type == git.RefTypeOther ||
		current.Type == git.RefTypeRemoteBranch {

		return nil, errors.Errorf("fatal: cannot migrate non-local ref: %s", current.Name)
	}
	return current, nil
}

// getHistoryRewriter returns a history rewriter that includes the filepath
// filter given by the --include and --exclude arguments.
func getHistoryRewriter(cmd *cobra.Command, db *gitobj.ObjectDatabase, l *tasklog.Logger) *githistory.Rewriter {
	include, exclude := getIncludeExcludeArgs(cmd)
	filter := buildFilepathFilter(cfg, include, exclude)

	return githistory.NewRewriter(db,
		githistory.WithFilter(filter), githistory.WithLogger(l))
}

func ensureWorkingCopyClean(in io.Reader, out io.Writer) {
	dirty, err := git.IsWorkingCopyDirty()
	if err != nil {
		ExitWithError(errors.Wrap(err,
			"fatal: could not determine if working copy is dirty"))
	}

	if !dirty {
		return
	}

	var proceed bool
	if migrateYes {
		proceed = true
	} else {
		answer := bufio.NewReader(in)
	L:
		for {
			fmt.Fprintf(out, "migrate: override changes in your working copy? [Y/n] ")
			s, err := answer.ReadString('\n')
			if err != nil {
				if err == io.EOF {
					break L
				}
				ExitWithError(errors.Wrap(err,
					"fatal: could not read answer"))
			}

			switch strings.TrimSpace(s) {
			case "n", "N":
				proceed = false
				break L
			case "y", "Y":
				proceed = true
				break L
			}

			if !strings.HasSuffix(s, "\n") {
				fmt.Fprintf(out, "\n")
			}
		}
	}

	if proceed {
		fmt.Fprintf(out, "migrate: changes in your working copy will be overridden ...\n")
	} else {
		Exit("migrate: working copy must not be dirty")
	}
}

func init() {
	info := NewCommand("info", migrateInfoCommand)
	info.Flags().IntVar(&migrateInfoTopN, "top", 5, "--top=<n>")
	info.Flags().StringVar(&migrateInfoAboveFmt, "above", "", "--above=<n>")
	info.Flags().StringVar(&migrateInfoUnitFmt, "unit", "", "--unit=<unit>")

	importCmd := NewCommand("import", migrateImportCommand)
	importCmd.Flags().BoolVar(&migrateVerbose, "verbose", false, "Verbose logging")
	importCmd.Flags().StringVar(&objectMapFilePath, "object-map", "", "Object map file")
	importCmd.Flags().BoolVar(&migrateNoRewrite, "no-rewrite", false, "Add new history without rewriting previous")
	importCmd.Flags().StringVarP(&migrateCommitMessage, "message", "m", "", "With --no-rewrite, an optional commit message")
	importCmd.Flags().BoolVar(&migrateFixup, "fixup", false, "Infer filepaths based on .gitattributes")

	exportCmd := NewCommand("export", migrateExportCommand)
	exportCmd.Flags().BoolVar(&migrateVerbose, "verbose", false, "Verbose logging")
	exportCmd.Flags().StringVar(&objectMapFilePath, "object-map", "", "Object map file")
	exportCmd.Flags().StringVar(&exportRemote, "remote", "", "Remote from which to download objects")

	RegisterCommand("migrate", nil, func(cmd *cobra.Command) {
		cmd.PersistentFlags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
		cmd.PersistentFlags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")

		cmd.PersistentFlags().StringSliceVar(&migrateIncludeRefs, "include-ref", nil, "An explicit list of refs to include")
		cmd.PersistentFlags().StringSliceVar(&migrateExcludeRefs, "exclude-ref", nil, "An explicit list of refs to exclude")
		cmd.PersistentFlags().BoolVar(&migrateEverything, "everything", false, "Migrate all local references")
		cmd.PersistentFlags().BoolVar(&migrateSkipFetch, "skip-fetch", false, "Assume up-to-date remote references.")

		cmd.PersistentFlags().BoolVarP(&migrateYes, "yes", "y", false, "Don't prompt for answers.")

		cmd.AddCommand(exportCmd, importCmd, info)
	})
}
<commit_msg>commands/command_migrate.go: fallback to ref.Refspec()<commit_after>package commands

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

	"github.com/git-lfs/git-lfs/errors"
	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/git/githistory"
	"github.com/git-lfs/git-lfs/tasklog"
	"github.com/git-lfs/gitobj"
	"github.com/spf13/cobra"
)

var (
	// migrateIncludeRefs is a set of Git references to explicitly include
	// in the migration.
	migrateIncludeRefs []string
	// migrateExcludeRefs is a set of Git references to explicitly exclude
	// in the migration.
	migrateExcludeRefs []string

	// migrateYes indicates that an answer of 'yes' should be presumed
	// whenever 'git lfs migrate' asks for user input.
	migrateYes bool

	// migrateSkipFetch assumes that the client has the latest copy of
	// remote references, and thus should not contact the remote for a set
	// of updated references.
	migrateSkipFetch bool

	// migrateEverything indicates the presence of the --everything flag,
	// and instructs 'git lfs migrate' to migrate all local references.
	migrateEverything bool

	// migrateVerbose enables verbose logging
	migrateVerbose bool

	// objectMapFile is the path to the map of old sha1 to new sha1
	// commits
	objectMapFilePath string

	// migrateNoRewrite is the flag indicating whether or not the
	// command should rewrite git history
	migrateNoRewrite bool
	// migrateCommitMessage is the message to use with the commit generated
	// by the migrate command
	migrateCommitMessage string

	// exportRemote is the remote from which to download objects when
	// performing an export
	exportRemote string

	// migrateFixup is the flag indicating whether or not to infer the
	// included and excluded filepath patterns.
	migrateFixup bool
)

// migrate takes the given command and arguments, *gitobj.ObjectDatabase, as well
// as a BlobRewriteFn to apply, and performs a migration.
func migrate(args []string, r *githistory.Rewriter, l *tasklog.Logger, opts *githistory.RewriteOptions) {
	requireInRepo()

	opts, err := rewriteOptions(args, opts, l)
	if err != nil {
		ExitWithError(err)
	}

	_, err = r.Rewrite(opts)
	if err != nil {
		ExitWithError(err)
	}
}

// getObjectDatabase creates a *git.ObjectDatabase from the filesystem pointed
// at the .git directory of the currently checked-out repository.
func getObjectDatabase() (*gitobj.ObjectDatabase, error) {
	dir, err := git.GitCommonDir()
	if err != nil {
		return nil, errors.Wrap(err, "cannot open root")
	}
	return gitobj.FromFilesystem(filepath.Join(dir, "objects"), cfg.TempDir())
}

// rewriteOptions returns *githistory.RewriteOptions able to be passed to a
// *githistory.Rewriter that reflect the current arguments and flags passed to
// an invocation of git-lfs-migrate(1).
//
// It is merged with the given "opts". In other words, an identical "opts" is
// returned, where the Include and Exclude fields have been filled based on the
// following rules:
//
// The included and excluded references are determined based on the output of
// includeExcludeRefs (see below for documentation and detail).
//
// If any of the above could not be determined without error, that error will be
// returned immediately.
func rewriteOptions(args []string, opts *githistory.RewriteOptions, l *tasklog.Logger) (*githistory.RewriteOptions, error) {
	include, exclude, err := includeExcludeRefs(l, args)
	if err != nil {
		return nil, err
	}

	return &githistory.RewriteOptions{
		Include: include,
		Exclude: exclude,

		UpdateRefs:        opts.UpdateRefs,
		Verbose:           opts.Verbose,
		ObjectMapFilePath: opts.ObjectMapFilePath,

		BlobFn:            opts.BlobFn,
		TreePreCallbackFn: opts.TreePreCallbackFn,
		TreeCallbackFn:    opts.TreeCallbackFn,
	}, nil
}

// includeExcludeRefs returns fully-qualified sets of references to include, and
// exclude, or an error if those could not be determined.
//
// They are determined based on the following rules:
//
//   - Include all local refs/heads/<branch> references for each branch
//     specified as an argument.
//   - Include the currently checked out branch if no branches are given as
//     arguments and the --include-ref= or --exclude-ref= flag(s) aren't given.
//   - Include all references given in --include-ref=<ref>.
//   - Exclude all references given in --exclude-ref=<ref>.
func includeExcludeRefs(l *tasklog.Logger, args []string) (include, exclude []string, err error) {
	hardcore := len(migrateIncludeRefs) > 0 || len(migrateExcludeRefs) > 0

	if len(args) == 0 && !hardcore && !migrateEverything {
		// If no branches were given explicitly AND neither
		// --include-ref or --exclude-ref flags were given, then add the
		// currently checked out reference.
		current, err := currentRefToMigrate()
		if err != nil {
			return nil, nil, err
		}
		args = append(args, current.Name)
	}

	if migrateEverything && len(args) > 0 {
		return nil, nil, errors.New("fatal: cannot use --everything with explicit reference arguments")
	}

	for _, name := range args {
		var excluded bool
		if strings.HasPrefix("^", name) {
			name = name[1:]
			excluded = true
		}

		// Then, loop through each branch given, resolve that reference,
		// and include it.
		ref, err := git.ResolveRef(name)
		if err != nil {
			return nil, nil, err
		}

		if excluded {
			exclude = append(exclude, ref.Refspec())
		} else {
			include = append(include, ref.Refspec())
		}
	}

	if hardcore {
		if migrateEverything {
			return nil, nil, errors.New("fatal: cannot use --everything with --include-ref or --exclude-ref")
		}

		// If either --include-ref=<ref> or --exclude-ref=<ref> were
		// given, append those to the include and excluded reference
		// set, respectively.
		include = append(include, migrateIncludeRefs...)
		exclude = append(exclude, migrateExcludeRefs...)
	} else if migrateEverything {
		refs, err := git.AllRefsIn("")
		if err != nil {
			return nil, nil, err
		}

		for _, ref := range refs {
			switch ref.Type {
			case git.RefTypeLocalBranch, git.RefTypeLocalTag,
				git.RefTypeRemoteBranch:

				include = append(include, ref.Refspec())
			case git.RefTypeOther:
				parts := strings.SplitN(ref.Refspec(), "/", 3)
				if len(parts) < 2 {
					continue
				}

				switch parts[1] {
				// The following are GitLab-, GitHub-, VSTS-,
				// and BitBucket-specific reference naming
				// conventions.
				case "merge-requests", "pull", "pull-requests":
					include = append(include, ref.Refspec())
				}
			}
		}
	} else {
		bare, err := git.IsBare()
		if err != nil {
			return nil, nil, errors.Wrap(err, "fatal: unable to determine bareness")
		}

		if !bare {
			// Otherwise, if neither --include-ref=<ref> or
			// --exclude-ref=<ref> were given, include no additional
			// references, and exclude all remote references that
			// are remote branches or remote tags.
			remoteRefs, err := getRemoteRefs(l)
			if err != nil {
				return nil, nil, err
			}

			for _, refs := range remoteRefs {
				for _, ref := range refs {
					exclude = append(exclude, ref.Refspec())
				}
			}
		}
	}

	return include, exclude, nil
}

// getRemoteRefs returns a fully qualified set of references belonging to all
// remotes known by the currently checked-out repository, or an error if those
// references could not be determined.
func getRemoteRefs(l *tasklog.Logger) (map[string][]*git.Ref, error) {
	refs := make(map[string][]*git.Ref)

	remotes, err := git.RemoteList()
	if err != nil {
		return nil, err
	}

	if !migrateSkipFetch {
		w := l.Waiter("migrate: Fetching remote refs")
		if err := git.Fetch(remotes...); err != nil {
			return nil, err
		}
		w.Complete()
	}

	for _, remote := range remotes {
		var refsForRemote []*git.Ref
		if migrateSkipFetch {
			refsForRemote, err = git.CachedRemoteRefs(remote)
		} else {
			refsForRemote, err = git.RemoteRefs(remote)
		}

		if err != nil {
			return nil, err
		}

		for i, rr := range refsForRemote {
			// HACK(@ttaylorr): add remote name to fully-qualify
			// references:
			refsForRemote[i].Name =
				fmt.Sprintf("%s/%s", remote, rr.Name)
		}

		refs[remote] = refsForRemote
	}

	return refs, nil
}

// formatRefName returns the fully-qualified name for the given Git reference
// "ref".
func formatRefName(ref *git.Ref, remote string) string {
	var name []string

	switch ref.Type {
	case git.RefTypeRemoteBranch:
		name = []string{"refs", "remotes", remote, ref.Name}
	default:
		return ref.Refspec()
	}
	return strings.Join(name, "/")

}

// currentRefToMigrate returns the fully-qualified name of the currently
// checked-out reference, or an error if the reference's type was not a local
// branch.
func currentRefToMigrate() (*git.Ref, error) {
	current, err := git.CurrentRef()
	if err != nil {
		return nil, err
	}

	if current.Type == git.RefTypeOther ||
		current.Type == git.RefTypeRemoteBranch {

		return nil, errors.Errorf("fatal: cannot migrate non-local ref: %s", current.Name)
	}
	return current, nil
}

// getHistoryRewriter returns a history rewriter that includes the filepath
// filter given by the --include and --exclude arguments.
func getHistoryRewriter(cmd *cobra.Command, db *gitobj.ObjectDatabase, l *tasklog.Logger) *githistory.Rewriter {
	include, exclude := getIncludeExcludeArgs(cmd)
	filter := buildFilepathFilter(cfg, include, exclude)

	return githistory.NewRewriter(db,
		githistory.WithFilter(filter), githistory.WithLogger(l))
}

func ensureWorkingCopyClean(in io.Reader, out io.Writer) {
	dirty, err := git.IsWorkingCopyDirty()
	if err != nil {
		ExitWithError(errors.Wrap(err,
			"fatal: could not determine if working copy is dirty"))
	}

	if !dirty {
		return
	}

	var proceed bool
	if migrateYes {
		proceed = true
	} else {
		answer := bufio.NewReader(in)
	L:
		for {
			fmt.Fprintf(out, "migrate: override changes in your working copy? [Y/n] ")
			s, err := answer.ReadString('\n')
			if err != nil {
				if err == io.EOF {
					break L
				}
				ExitWithError(errors.Wrap(err,
					"fatal: could not read answer"))
			}

			switch strings.TrimSpace(s) {
			case "n", "N":
				proceed = false
				break L
			case "y", "Y":
				proceed = true
				break L
			}

			if !strings.HasSuffix(s, "\n") {
				fmt.Fprintf(out, "\n")
			}
		}
	}

	if proceed {
		fmt.Fprintf(out, "migrate: changes in your working copy will be overridden ...\n")
	} else {
		Exit("migrate: working copy must not be dirty")
	}
}

func init() {
	info := NewCommand("info", migrateInfoCommand)
	info.Flags().IntVar(&migrateInfoTopN, "top", 5, "--top=<n>")
	info.Flags().StringVar(&migrateInfoAboveFmt, "above", "", "--above=<n>")
	info.Flags().StringVar(&migrateInfoUnitFmt, "unit", "", "--unit=<unit>")

	importCmd := NewCommand("import", migrateImportCommand)
	importCmd.Flags().BoolVar(&migrateVerbose, "verbose", false, "Verbose logging")
	importCmd.Flags().StringVar(&objectMapFilePath, "object-map", "", "Object map file")
	importCmd.Flags().BoolVar(&migrateNoRewrite, "no-rewrite", false, "Add new history without rewriting previous")
	importCmd.Flags().StringVarP(&migrateCommitMessage, "message", "m", "", "With --no-rewrite, an optional commit message")
	importCmd.Flags().BoolVar(&migrateFixup, "fixup", false, "Infer filepaths based on .gitattributes")

	exportCmd := NewCommand("export", migrateExportCommand)
	exportCmd.Flags().BoolVar(&migrateVerbose, "verbose", false, "Verbose logging")
	exportCmd.Flags().StringVar(&objectMapFilePath, "object-map", "", "Object map file")
	exportCmd.Flags().StringVar(&exportRemote, "remote", "", "Remote from which to download objects")

	RegisterCommand("migrate", nil, func(cmd *cobra.Command) {
		cmd.PersistentFlags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
		cmd.PersistentFlags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")

		cmd.PersistentFlags().StringSliceVar(&migrateIncludeRefs, "include-ref", nil, "An explicit list of refs to include")
		cmd.PersistentFlags().StringSliceVar(&migrateExcludeRefs, "exclude-ref", nil, "An explicit list of refs to exclude")
		cmd.PersistentFlags().BoolVar(&migrateEverything, "everything", false, "Migrate all local references")
		cmd.PersistentFlags().BoolVar(&migrateSkipFetch, "skip-fetch", false, "Assume up-to-date remote references.")

		cmd.PersistentFlags().BoolVarP(&migrateYes, "yes", "y", false, "Don't prompt for answers.")

		cmd.AddCommand(exportCmd, importCmd, info)
	})
}
<|endoftext|>


<commit_before>package comments

import (
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"regexp"
	"strings"

	"github.com/parkr/auto-reply/Godeps/_workspace/src/github.com/google/go-github/github"
	"github.com/parkr/auto-reply/Godeps/_workspace/src/github.com/parkr/changelog"
)

var (
	mergeCommentRegexp = regexp.MustCompile("@[a-zA-Z-_]+: (merge|:shipit:|:ship:)( \\+([a-zA-Z-_ ]+))?")

	HandlerMergeAndLabel = func(client *github.Client, event github.IssueCommentEvent) error {
		// Is this a pull request?
		if !isPullRequest(event) {
			return errors.New("not a pull request")
		}

		var changeSectionLabel string
		isReq, labelFromComment := parseMergeRequestComment(*event.Comment.Body)

		// Is It a merge request comment?
		if !isReq {
			return errors.New("not a merge request comment")
		}

		log.Println(event)

		owner, repo, number := *event.Repo.Owner.Login, *event.Repo.Name, *event.Issue.Number

		// Does the user have merge/label abilities?
		if !isAuthorizedCommenter(event.Comment.User) {
			return errors.New("commenter isn't allowed to merge")
		}

		// Should it be labeled?
		if labelFromComment != "" {
			// Apply label
			changeSectionLabel = sectionForLabel(labelFromComment)
		} else {
			// Get changeSectionLabel from issue labels!
			labels, _, err := client.Issues.ListLabelsForMilestone(owner, repo, number, nil)
			if err != nil {
				return err
			}
			fmt.Printf("labels from GitHub = %v\n", labels)
			changeSectionLabel = sectionForLabel(selectSectionLabel(labels))
		}
		fmt.Printf("changeSectionLabel = '%s'\n", changeSectionLabel)

		// Merge
		commitMsg := fmt.Sprintf("Merge pull request %v", number)
		_, _, mergeErr := client.PullRequests.Merge(owner, repo, number, commitMsg)
		if mergeErr != nil {
			fmt.Printf("comments: error merging %v\n", mergeErr)
			//return mergeErr
		}

		// Delete branch
		repoInfo, _, getRepoErr := client.PullRequests.Get(owner, repo, number)
		if getRepoErr != nil {
			fmt.Printf("comments: error fetching pull request: %v\n", getRepoErr)
			return getRepoErr
		}
		ref := fmt.Sprintf("heads/%s", *repoInfo.Head.Ref)
		_, deleteBranchErr := client.Git.DeleteRef(owner, repo, ref)
		if deleteBranchErr != nil {
			fmt.Printf("comments: error deleting branch %v\n", mergeErr)
		}

		// Read History.markdown, add line to appropriate change section
		historyFileContents, historySHA := getHistoryContents(client, owner, repo)
		log.Println(historyFileContents)

		// Add to
		newHistoryFileContents := addMergeReference(historyFileContents, changeSectionLabel, *repoInfo.Title, number)

		// Commit change to History.markdown
		commitErr := commitHistoryFile(client, historySHA, owner, repo, number, newHistoryFileContents)
		if commitErr != nil {
			fmt.Printf("comments: error committing updated history %v\n", mergeErr)
		}
		return commitErr
	}
)

func isAuthorizedCommenter(user *github.User) bool {
	return *user.Login == "parkr"
}

func parseMergeRequestComment(commentBody string) (bool, string) {
	matches := mergeCommentRegexp.FindAllStringSubmatch(commentBody, -1)
	if matches == nil || matches[0] == nil {
		return false, ""
	}

	var label string
	if len(matches[0]) >= 4 {
		if labelFromComment := matches[0][3]; labelFromComment != "" {
			label = downcaseAndHyphenize(labelFromComment)
		}
	}

	return true, normalizeLabel(label)
}

func downcaseAndHyphenize(label string) string {
	return strings.Replace(strings.ToLower(label), " ", "-", -1)
}

func normalizeLabel(label string) string {
	if strings.HasPrefix(label, "major") {
		return "major-enhancements"
	}

	if strings.HasPrefix(label, "minor") {
		return "minor-enhancements"
	}

	if strings.HasPrefix(label, "bug") {
		return "bug-fixes"
	}

	if strings.HasPrefix(label, "dev") {
		return "development-fixes"
	}

	if strings.HasPrefix(label, "site") {
		return "site-enhancements"
	}

	return label
}

func sectionForLabel(label string) string {
	switch label {
	case "major-enhancements":
		return "Major Enhancements"
	case "minor-enhancements":
		return "Minor Enhancements"
	case "bug-fixes":
		return "Bug Fixes"
	case "development-fixes":
		return "Development Fixes"
	case "site-enhancements":
		return "Site Enhancements"
	default:
		return label
	}
}

func selectSectionLabel(labels []github.Label) string {
	for _, label := range labels {
		if sectionForLabel(*label.Name) != *label.Name {
			return *label.Name
		}
	}
	return ""
}

func containsChangeLabel(commentBody string) bool {
	_, labelFromComment := parseMergeRequestComment(commentBody)
	return labelFromComment != ""
}

func getHistoryContents(client *github.Client, owner, repo string) (content, sha string) {
	contents, _, _, err := client.Repositories.GetContents(
		owner,
		repo,
		"History.markdown",
		&github.RepositoryContentGetOptions{Ref: "heads/master"},
	)
	if err != nil {
		fmt.Printf("comments: error getting History.markdown %v\n", err)
		return "", ""
	}
	return base64Decode(*contents.Content), *contents.SHA
}

func base64Decode(encoded string) string {
	decoded, err := base64.StdEncoding.DecodeString(encoded)
	if err != nil {
		fmt.Printf("comments: error decoding string: %v\n", err)
		return ""
	}
	return string(decoded)
}

func addMergeReference(historyFileContents, changeSectionLabel, prTitle string, number int) string {
	changes, err := changelog.NewChangelogFromReader(strings.NewReader(historyFileContents))
	if historyFileContents == "" {
		err = nil
		changes = &changelog.Changelog{
			Versions: []*changelog.Version{},
		}
	}
	if err != nil {
		fmt.Printf("comments: error %v\n", err)
		return historyFileContents
	}
	reference := fmt.Sprintf("#%d", number)

	// Find HEAD, or create
	var version *changelog.Version
	for _, v := range changes.Versions {
		if v.Version == "HEAD" {
			version = v
		}
	}
	if version == nil {
		version = &changelog.Version{
			Version:     "HEAD",
			Subsections: []*changelog.Subsection{},
		}
		changes.Versions = append([]*changelog.Version{version}, changes.Versions...)
	}

	// Find Subsection, or create
	var subsection *changelog.Subsection
	for _, s := range version.Subsections {
		if s.Name == changeSectionLabel {
			subsection = s
		}
	}
	if subsection == nil {
		subsection = &changelog.Subsection{
			Name:    changeSectionLabel,
			History: []*changelog.ChangeLine{},
		}
		version.Subsections = append([]*changelog.Subsection{subsection}, version.Subsections...)
	}

	// Find changeline, only create if does not exist.
	for _, c := range subsection.History {
		if c.Reference == reference {
			return historyFileContents
		}
	}
	changeLine := &changelog.ChangeLine{
		Summary:   prTitle,
		Reference: reference,
	}
	subsection.History = append(subsection.History, changeLine)

	return changes.String()
}

func commitHistoryFile(client *github.Client, historySHA, owner, repo string, number int, newHistoryFileContents string) error {
	repositoryContentsOptions := &github.RepositoryContentFileOptions{
		Message: github.String(fmt.Sprintf("Update history to reflect merge of #%d [ci skip]", number)),
		Content: []byte(newHistoryFileContents),
		SHA:     github.String(historySHA),
		Committer: &github.CommitAuthor{
			Name:  github.String("jekyllbot"),
			Email: github.String("jekyllbot@jekyllrb.com"),
		},
	}
	updateResponse, _, err := client.Repositories.UpdateFile(owner, repo, "History.markdown", repositoryContentsOptions)
	if err != nil {
		fmt.Printf("comments: error committing History.markdown: %v\n", err)
		return err
	}
	fmt.Printf("comments: updateResponse: %s\n", updateResponse)
	return nil
}
<commit_msg>don't delete master DUMMY<commit_after>package comments

import (
	"encoding/base64"
	"errors"
	"fmt"
	"log"
	"regexp"
	"strings"

	"github.com/parkr/auto-reply/Godeps/_workspace/src/github.com/google/go-github/github"
	"github.com/parkr/auto-reply/Godeps/_workspace/src/github.com/parkr/changelog"
)

var (
	mergeCommentRegexp = regexp.MustCompile("@[a-zA-Z-_]+: (merge|:shipit:|:ship:)( \\+([a-zA-Z-_ ]+))?")

	HandlerMergeAndLabel = func(client *github.Client, event github.IssueCommentEvent) error {
		// Is this a pull request?
		if !isPullRequest(event) {
			return errors.New("not a pull request")
		}

		var changeSectionLabel string
		isReq, labelFromComment := parseMergeRequestComment(*event.Comment.Body)

		// Is It a merge request comment?
		if !isReq {
			return errors.New("not a merge request comment")
		}

		log.Println(event)

		owner, repo, number := *event.Repo.Owner.Login, *event.Repo.Name, *event.Issue.Number

		// Does the user have merge/label abilities?
		if !isAuthorizedCommenter(event.Comment.User) {
			return errors.New("commenter isn't allowed to merge")
		}

		// Should it be labeled?
		if labelFromComment != "" {
			// Apply label
			changeSectionLabel = sectionForLabel(labelFromComment)
		} else {
			// Get changeSectionLabel from issue labels!
			labels, _, err := client.Issues.ListLabelsForMilestone(owner, repo, number, nil)
			if err != nil {
				return err
			}
			fmt.Printf("labels from GitHub = %v\n", labels)
			changeSectionLabel = sectionForLabel(selectSectionLabel(labels))
		}
		fmt.Printf("changeSectionLabel = '%s'\n", changeSectionLabel)

		// Merge
		commitMsg := fmt.Sprintf("Merge pull request %v", number)
		_, _, mergeErr := client.PullRequests.Merge(owner, repo, number, commitMsg)
		if mergeErr != nil {
			fmt.Printf("comments: error merging %v\n", mergeErr)
			//return mergeErr
		}

		// Delete branch
		repoInfo, _, getRepoErr := client.PullRequests.Get(owner, repo, number)
		if getRepoErr != nil {
			fmt.Printf("comments: error fetching pull request: %v\n", getRepoErr)
			return getRepoErr
		}

		// Delete branch
		if deletableRef(repoInfo, owner) {
			ref := fmt.Sprintf("heads/%s", *repoInfo.Head.Ref)
			_, deleteBranchErr := client.Git.DeleteRef(owner, repo, ref)
			if deleteBranchErr != nil {
				fmt.Printf("comments: error deleting branch %v\n", mergeErr)
			}
		}

		// Read History.markdown, add line to appropriate change section
		historyFileContents, historySHA := getHistoryContents(client, owner, repo)
		log.Println(historyFileContents)

		// Add to
		newHistoryFileContents := addMergeReference(historyFileContents, changeSectionLabel, *repoInfo.Title, number)

		// Commit change to History.markdown
		commitErr := commitHistoryFile(client, historySHA, owner, repo, number, newHistoryFileContents)
		if commitErr != nil {
			fmt.Printf("comments: error committing updated history %v\n", mergeErr)
		}
		return commitErr
	}
)

func isAuthorizedCommenter(user *github.User) bool {
	return *user.Login == "parkr"
}

func parseMergeRequestComment(commentBody string) (bool, string) {
	matches := mergeCommentRegexp.FindAllStringSubmatch(commentBody, -1)
	if matches == nil || matches[0] == nil {
		return false, ""
	}

	var label string
	if len(matches[0]) >= 4 {
		if labelFromComment := matches[0][3]; labelFromComment != "" {
			label = downcaseAndHyphenize(labelFromComment)
		}
	}

	return true, normalizeLabel(label)
}

func downcaseAndHyphenize(label string) string {
	return strings.Replace(strings.ToLower(label), " ", "-", -1)
}

func normalizeLabel(label string) string {
	if strings.HasPrefix(label, "major") {
		return "major-enhancements"
	}

	if strings.HasPrefix(label, "minor") {
		return "minor-enhancements"
	}

	if strings.HasPrefix(label, "bug") {
		return "bug-fixes"
	}

	if strings.HasPrefix(label, "dev") {
		return "development-fixes"
	}

	if strings.HasPrefix(label, "site") {
		return "site-enhancements"
	}

	return label
}

func sectionForLabel(label string) string {
	switch label {
	case "major-enhancements":
		return "Major Enhancements"
	case "minor-enhancements":
		return "Minor Enhancements"
	case "bug-fixes":
		return "Bug Fixes"
	case "development-fixes":
		return "Development Fixes"
	case "site-enhancements":
		return "Site Enhancements"
	default:
		return label
	}
}

func selectSectionLabel(labels []github.Label) string {
	for _, label := range labels {
		if sectionForLabel(*label.Name) != *label.Name {
			return *label.Name
		}
	}
	return ""
}

func containsChangeLabel(commentBody string) bool {
	_, labelFromComment := parseMergeRequestComment(commentBody)
	return labelFromComment != ""
}

func getHistoryContents(client *github.Client, owner, repo string) (content, sha string) {
	contents, _, _, err := client.Repositories.GetContents(
		owner,
		repo,
		"History.markdown",
		&github.RepositoryContentGetOptions{Ref: "heads/master"},
	)
	if err != nil {
		fmt.Printf("comments: error getting History.markdown %v\n", err)
		return "", ""
	}
	return base64Decode(*contents.Content), *contents.SHA
}

func base64Decode(encoded string) string {
	decoded, err := base64.StdEncoding.DecodeString(encoded)
	if err != nil {
		fmt.Printf("comments: error decoding string: %v\n", err)
		return ""
	}
	return string(decoded)
}

func addMergeReference(historyFileContents, changeSectionLabel, prTitle string, number int) string {
	changes, err := changelog.NewChangelogFromReader(strings.NewReader(historyFileContents))
	if historyFileContents == "" {
		err = nil
		changes = &changelog.Changelog{
			Versions: []*changelog.Version{},
		}
	}
	if err != nil {
		fmt.Printf("comments: error %v\n", err)
		return historyFileContents
	}
	reference := fmt.Sprintf("#%d", number)

	// Find HEAD, or create
	var version *changelog.Version
	for _, v := range changes.Versions {
		if v.Version == "HEAD" {
			version = v
		}
	}
	if version == nil {
		version = &changelog.Version{
			Version:     "HEAD",
			Subsections: []*changelog.Subsection{},
		}
		changes.Versions = append([]*changelog.Version{version}, changes.Versions...)
	}

	// Find Subsection, or create
	var subsection *changelog.Subsection
	for _, s := range version.Subsections {
		if s.Name == changeSectionLabel {
			subsection = s
		}
	}
	if subsection == nil {
		subsection = &changelog.Subsection{
			Name:    changeSectionLabel,
			History: []*changelog.ChangeLine{},
		}
		version.Subsections = append([]*changelog.Subsection{subsection}, version.Subsections...)
	}

	// Find changeline, only create if does not exist.
	for _, c := range subsection.History {
		if c.Reference == reference {
			return historyFileContents
		}
	}
	changeLine := &changelog.ChangeLine{
		Summary:   prTitle,
		Reference: reference,
	}
	subsection.History = append(subsection.History, changeLine)

	return changes.String()
}

func deletableRef(pr *github.PullRequest, owner string) bool {
	return *pr.Head.Repo.Owner.Login == owner && *pr.Head.Ref != "master" && *pr.Head.Ref != "gh-pages"
}

func commitHistoryFile(client *github.Client, historySHA, owner, repo string, number int, newHistoryFileContents string) error {
	repositoryContentsOptions := &github.RepositoryContentFileOptions{
		Message: github.String(fmt.Sprintf("Update history to reflect merge of #%d [ci skip]", number)),
		Content: []byte(newHistoryFileContents),
		SHA:     github.String(historySHA),
		Committer: &github.CommitAuthor{
			Name:  github.String("jekyllbot"),
			Email: github.String("jekyllbot@jekyllrb.com"),
		},
	}
	updateResponse, _, err := client.Repositories.UpdateFile(owner, repo, "History.markdown", repositoryContentsOptions)
	if err != nil {
		fmt.Printf("comments: error committing History.markdown: %v\n", err)
		return err
	}
	fmt.Printf("comments: updateResponse: %s\n", updateResponse)
	return nil
}
<|endoftext|>


<commit_before>package cwl

import (
	"fmt"
	"reflect"

	"github.com/davecgh/go-spew/spew"
	"github.com/mitchellh/mapstructure"
)

// ExpressionToolOutputParameter http://www.commonwl.org/v1.0/Workflow.html#ExpressionToolOutputParameter
type ExpressionToolOutputParameter struct {
	OutputParameter `yaml:",inline" json:",inline" bson:",inline" mapstructure:",squash"` // provides Id, Label, SecondaryFiles, Format, Streamable, OutputBinding, Type
}

// type: CWLType | OutputRecordSchema | OutputEnumSchema | OutputArraySchema | string | array<CWLType | OutputRecordSchema | OutputEnumSchema | OutputArraySchema | string>

//NewExpressionToolOutputParameter _
func NewExpressionToolOutputParameter(original interface{}, schemata []CWLType_Type, context *WorkflowContext) (wop *ExpressionToolOutputParameter, err error) {
	var outputParameter ExpressionToolOutputParameter

	original, err = MakeStringMap(original, context)
	if err != nil {
		return
	}

	switch original.(type) {

	case map[string]interface{}:

		var op *OutputParameter
		var opIf interface{}
		opIf, err = NewOutputParameterFromInterface(original, schemata, "Output", context)
		if err != nil {
			err = fmt.Errorf("(NewExpressionToolOutputParameter) NewOutputParameterFromInterface returns %s", err.Error())
			return
		}

		op, ok := opIf.(*OutputParameter)
		if !ok {
			err = fmt.Errorf("(NewExpressionToolOutputParameter) could not cast into *OutputParameter")
			return
		}

		err = mapstructure.Decode(original, &outputParameter)
		if err != nil {
			err = fmt.Errorf("(NewExpressionToolOutputParameter) decode error: %s", err.Error())
			return
		}
		wop = &outputParameter

		wop.OutputParameter = *op
	default:
		err = fmt.Errorf("(NewExpressionToolOutputParameter) type unknown, %s", reflect.TypeOf(original))
		return

	}

	return
}

// NewExpressionToolOutputParameterArray _
func NewExpressionToolOutputParameterArray(original interface{}, schemata []CWLType_Type, context *WorkflowContext) (newArray []interface{}, err error) {

	original, err = MakeStringMap(original, context)
	if err != nil {
		return
	}

	newArray = []interface{}{}
	switch original.(type) {
	case map[string]interface{}:
		for k, v := range original.(map[string]interface{}) {
			//fmt.Printf("A")
			var elementStr string
			var ok bool
			elementStr, ok = v.(string)

			if ok {
				var result CWLType_Type
				result, err = NewCWLType_TypeFromString(schemata, elementStr, "ExpressionToolOutput")
				if err != nil {
					err = fmt.Errorf("(NewExpressionToolOutputParameterArray) NewCWLType_TypeFromString returns: %s", err.Error())
					return
				}
				newArray = append(newArray, result)
				continue
			}
			outputParameter, xerr := NewExpressionToolOutputParameter(v, schemata, context)
			if xerr != nil {
				err = xerr
				return
			}
			outputParameter.Id = k
			//fmt.Printf("C")
			newArray = append(newArray, *outputParameter)
			//fmt.Printf("D")

		}

		return
	case []interface{}:

		for _, v := range original.([]interface{}) {
			//fmt.Printf("A")

			outputParameter, xerr := NewExpressionToolOutputParameter(v, schemata, context)
			if xerr != nil {
				err = xerr
				return
			}
			//output_parameter.Id = k.(string)
			//fmt.Printf("C")
			newArray = append(newArray, *outputParameter)
			//fmt.Printf("D")

		}

		return

	default:
		spew.Dump(newArray)
		err = fmt.Errorf("(NewExpressionToolOutputParameterArray) type %s unknown", reflect.TypeOf(original))
	}
	//spew.Dump(new_array)
	return
}
<commit_msg>better error message<commit_after>package cwl

import (
	"fmt"
	"reflect"

	"github.com/davecgh/go-spew/spew"
	"github.com/mitchellh/mapstructure"
)

// ExpressionToolOutputParameter http://www.commonwl.org/v1.0/Workflow.html#ExpressionToolOutputParameter
type ExpressionToolOutputParameter struct {
	OutputParameter `yaml:",inline" json:",inline" bson:",inline" mapstructure:",squash"` // provides Id, Label, SecondaryFiles, Format, Streamable, OutputBinding, Type
}

// type: CWLType | OutputRecordSchema | OutputEnumSchema | OutputArraySchema | string | array<CWLType | OutputRecordSchema | OutputEnumSchema | OutputArraySchema | string>

//NewExpressionToolOutputParameter _
func NewExpressionToolOutputParameter(original interface{}, schemata []CWLType_Type, context *WorkflowContext) (wop *ExpressionToolOutputParameter, err error) {
	var outputParameter ExpressionToolOutputParameter

	original, err = MakeStringMap(original, context)
	if err != nil {
		return
	}

	switch original.(type) {
	case string:
		err = fmt.Errorf("(NewExpressionToolOutputParameter) type string not supported!! ")
		return
	case map[string]interface{}:

		var op *OutputParameter
		var opIf interface{}
		opIf, err = NewOutputParameterFromInterface(original, schemata, "Output", context)
		if err != nil {
			err = fmt.Errorf("(NewExpressionToolOutputParameter) NewOutputParameterFromInterface returns %s", err.Error())
			return
		}

		op, ok := opIf.(*OutputParameter)
		if !ok {
			err = fmt.Errorf("(NewExpressionToolOutputParameter) could not cast into *OutputParameter")
			return
		}

		err = mapstructure.Decode(original, &outputParameter)
		if err != nil {
			err = fmt.Errorf("(NewExpressionToolOutputParameter) decode error: %s", err.Error())
			return
		}
		wop = &outputParameter

		wop.OutputParameter = *op
	default:
		err = fmt.Errorf("(NewExpressionToolOutputParameter) type unknown, %s", reflect.TypeOf(original))
		return

	}

	return
}

// NewExpressionToolOutputParameterArray _
func NewExpressionToolOutputParameterArray(original interface{}, schemata []CWLType_Type, context *WorkflowContext) (newArray []interface{}, err error) {

	original, err = MakeStringMap(original, context)
	if err != nil {
		return
	}

	newArray = []interface{}{}
	switch original.(type) {
	case map[string]interface{}:
		for k, v := range original.(map[string]interface{}) {
			//fmt.Printf("A")
			var elementStr string
			var ok bool
			elementStr, ok = v.(string)

			if ok {
				var result CWLType_Type
				result, err = NewCWLType_TypeFromString(schemata, elementStr, "ExpressionToolOutput")
				if err != nil {
					err = fmt.Errorf("(NewExpressionToolOutputParameterArray) NewCWLType_TypeFromString returns: %s", err.Error())
					return
				}
				newArray = append(newArray, result)
				continue
			}
			var outputParameter *ExpressionToolOutputParameter
			outputParameter, err = NewExpressionToolOutputParameter(v, schemata, context)
			if err != nil {
				err = fmt.Errorf("(NewExpressionToolOutputParameterArray) NewExpressionToolOutputParameter returns: %s", err.Error())

				return
			}
			outputParameter.Id = k
			//fmt.Printf("C")
			newArray = append(newArray, *outputParameter)
			//fmt.Printf("D")

		}

		return
	case []interface{}:

		for _, v := range original.([]interface{}) {
			//fmt.Printf("A")

			outputParameter, xerr := NewExpressionToolOutputParameter(v, schemata, context)
			if xerr != nil {
				err = xerr
				return
			}
			//output_parameter.Id = k.(string)
			//fmt.Printf("C")
			newArray = append(newArray, *outputParameter)
			//fmt.Printf("D")

		}

		return

	default:
		spew.Dump(newArray)
		err = fmt.Errorf("(NewExpressionToolOutputParameterArray) type %s unknown", reflect.TypeOf(original))
	}
	//spew.Dump(new_array)
	return
}
<|endoftext|>


<commit_before>/*
Copyright 2016 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 componentconfig

import (
	"fmt"
	"net"
)

// used for validating command line ip addresses.
type IPVar struct {
	Val *string
}

func (v IPVar) Set(s string) error {
	if net.ParseIP(s) == nil {
		return fmt.Errorf("%q is not a valid IP address", s)
	}
	if v.Val == nil {
		// it's okay to panic here since this is programmer error
		panic("the string pointer passed into IPVar should not be nil")
	}
	*v.Val = s
	return nil
}

func (v IPVar) String() string {
	if v.Val == nil {
		return ""
	}
	return *v.Val
}

func (v IPVar) Type() string {
	return "ip"
}
<commit_msg>update proxy server<commit_after>/*
Copyright 2016 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 componentconfig

import (
	"fmt"
	"net"

	utilnet "k8s.io/kubernetes/pkg/util/net"
)

// used for validating command line opts
// TODO(mikedanese): remove these when we remove command line flags

type IPVar struct {
	Val *string
}

func (v IPVar) Set(s string) error {
	if net.ParseIP(s) == nil {
		return fmt.Errorf("%q is not a valid IP address", s)
	}
	if v.Val == nil {
		// it's okay to panic here since this is programmer error
		panic("the string pointer passed into IPVar should not be nil")
	}
	*v.Val = s
	return nil
}

func (v IPVar) String() string {
	if v.Val == nil {
		return ""
	}
	return *v.Val
}

func (v IPVar) Type() string {
	return "ip"
}

func (m *ProxyMode) Set(s string) error {
	nm := ProxyMode(s)
	m = &nm
	return nil
}

func (m *ProxyMode) String() string {
	if m != nil {
		return string(*m)
	}
	return ""
}

func (m *ProxyMode) Type() string {
	return "ProxyMode"
}

type PortRangeVar struct {
	Val *string
}

func (v PortRangeVar) Set(s string) error {
	if _, err := utilnet.ParsePortRange(s); err != nil {
		return fmt.Errorf("%q is not a valid port range: %v", s, err)
	}
	if v.Val == nil {
		// it's okay to panic here since this is programmer error
		panic("the string pointer passed into PortRangeVar should not be nil")
	}
	*v.Val = s
	return nil
}

func (v PortRangeVar) String() string {
	if v.Val == nil {
		return ""
	}
	return *v.Val
}

func (v PortRangeVar) Type() string {
	return "port-range"
}
<|endoftext|>


<commit_before>package handlers

import (
	"container/heap"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/gojp/goreportcard/download"
)

const (
	// DBPath is the relative (or absolute) path to the bolt database file
	DBPath string = "goreportcard.db"

	// RepoBucket is the bucket in which repos will be cached in the bolt DB
	RepoBucket string = "repos"

	// MetaBucket is the bucket containing the names of the projects with the
	// top 100 high scores, and other meta information
	MetaBucket string = "meta"
)

// CheckHandler handles the request for checking a repo
func CheckHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	repo, err := download.Clean(r.FormValue("repo"))
	if err != nil {
		log.Println("ERROR: from download.Clean:", err)
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte(`Could not download the repository: ` + err.Error()))
		return
	}

	log.Printf("Checking repo %q...", repo)

	forceRefresh := r.Method != "GET" // if this is a GET request, try to fetch from cached version in boltdb first
	resp, err := newChecksResp(repo, forceRefresh)
	if err != nil {
		log.Println("ERROR: from newChecksResp:", err)
		w.WriteHeader(http.StatusBadRequest)
		w.Write([]byte(`Could not download the repository.`))
		return
	}

	respBytes, err := json.Marshal(resp)
	if err != nil {
		log.Println("ERROR: could not marshal json:", err)
		http.Error(w, err.Error(), 500)
		return
	}

	// write to boltdb
	db, err := bolt.Open(DBPath, 0755, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Println("Failed to open bolt database: ", err)
		http.Error(w, err.Error(), 500)
		return
	}
	defer db.Close()

	// is this a new repo? if so, increase the count in the high scores bucket later
	isNewRepo := false
	var oldRepoBytes []byte
	err = db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(RepoBucket))
		if b == nil {
			return fmt.Errorf("repo bucket not found")
		}
		oldRepoBytes = b.Get([]byte(repo))
		return nil
	})
	if err != nil {
		log.Println("ERROR getting repo from repo bucket:", err)
	}

	isNewRepo = oldRepoBytes == nil

	// if this is a new repo, or the user force-refreshed, update the cache
	if isNewRepo || forceRefresh {
		err = db.Update(func(tx *bolt.Tx) error {
			log.Printf("Saving repo %q to cache...", repo)

			b := tx.Bucket([]byte(RepoBucket))
			if b == nil {
				return fmt.Errorf("repo bucket not found")
			}

			// save repo to cache
			err = b.Put([]byte(repo), respBytes)
			if err != nil {
				return err
			}

			return updateMetadata(tx, resp, repo, isNewRepo)
		})

		if err != nil {
			log.Println("Bolt writing error:", err)
		}

	}

	db.Update(func(tx *bolt.Tx) error {
		// fetch meta-bucket
		mb := tx.Bucket([]byte(MetaBucket))
		return updateRecentlyViewed(mb, repo)
	})

	b, err := json.Marshal(map[string]string{"redirect": "/report/" + repo})
	if err != nil {
		log.Println("JSON marshal error:", err)
	}
	w.WriteHeader(http.StatusOK)
	w.Write(b)
	return
}

func updateHighScores(mb *bolt.Bucket, resp checksResp, repo string) error {
	// check if we need to update the high score list
	if resp.Files < 100 {
		// only repos with >= 100 files are considered for the high score list
		return nil
	}

	// start updating high score list
	scoreBytes := mb.Get([]byte("scores"))
	if scoreBytes == nil {
		scoreBytes, _ = json.Marshal([]ScoreHeap{})
	}
	scores := &ScoreHeap{}
	json.Unmarshal(scoreBytes, scores)

	heap.Init(scores)
	if len(*scores) > 0 && (*scores)[0].Score > resp.Average*100.0 && len(*scores) == 50 {
		// lowest score on list is higher than this repo's score, so no need to add, unless
		// we do not have 50 high scores yet
		return nil
	}
	// if this repo is already in the list, remove the original entry:
	for i := range *scores {
		if strings.ToLower((*scores)[i].Repo) == strings.ToLower(repo) {
			heap.Remove(scores, i)
			break
		}
	}
	// now we can safely push it onto the heap
	heap.Push(scores, scoreItem{
		Repo:  repo,
		Score: resp.Average * 100.0,
		Files: resp.Files,
	})
	if len(*scores) > 50 {
		// trim heap if it's grown to over 50
		*scores = (*scores)[1:51]
	}
	scoreBytes, err := json.Marshal(&scores)
	if err != nil {
		return err
	}
	err = mb.Put([]byte("scores"), scoreBytes)
	if err != nil {
		return err
	}

	return nil
}

func updateReposCount(mb *bolt.Bucket, repo string) (err error) {
	log.Printf("New repo %q, adding to repo count...", repo)
	totalInt := 0
	total := mb.Get([]byte("total_repos"))
	if total != nil {
		err = json.Unmarshal(total, &totalInt)
		if err != nil {
			return fmt.Errorf("could not unmarshal total repos count: %v", err)
		}
	}
	totalInt++ // increase repo count
	total, err = json.Marshal(totalInt)
	if err != nil {
		return fmt.Errorf("could not marshal total repos count: %v", err)
	}
	mb.Put([]byte("total_repos"), total)
	log.Println("Repo count is now", totalInt)
	return nil
}

type recentItem struct {
	Repo string
}

func updateRecentlyViewed(mb *bolt.Bucket, repo string) error {
	if mb == nil {
		return fmt.Errorf("meta bucket not found")
	}
	b := mb.Get([]byte("recent"))
	if b == nil {
		b, _ = json.Marshal([]recentItem{})
	}
	recent := []recentItem{}
	json.Unmarshal(b, &recent)

	// add it to the slice, if it is not in there already
	for i := range recent {
		if recent[i].Repo == repo {
			return nil
		}
	}

	recent = append(recent, recentItem{Repo: repo})
	if len(recent) > 5 {
		// trim recent if it's grown to over 5
		recent = (recent)[1:6]
	}
	b, err := json.Marshal(&recent)
	if err != nil {
		return err
	}
	err = mb.Put([]byte("recent"), b)
	if err != nil {
		return err
	}

	return nil
}

//func updateMetadata(tx *bolt.Tx, resp checksResp, repo string, isNewRepo bool, oldScore *float64) error {
func updateMetadata(tx *bolt.Tx, resp checksResp, repo string, isNewRepo bool) error {
	// fetch meta-bucket
	mb := tx.Bucket([]byte(MetaBucket))
	if mb == nil {
		return fmt.Errorf("high score bucket not found")
	}
	// update total repos count
	if isNewRepo {
		err := updateReposCount(mb, repo)
		if err != nil {
			return err
		}
	}

	return updateHighScores(mb, resp, repo)
}
<commit_msg>Minor code cleanup in error handling.<commit_after>package handlers

import (
	"container/heap"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"strings"
	"time"

	"github.com/boltdb/bolt"
	"github.com/gojp/goreportcard/download"
)

const (
	// DBPath is the relative (or absolute) path to the bolt database file
	DBPath string = "goreportcard.db"

	// RepoBucket is the bucket in which repos will be cached in the bolt DB
	RepoBucket string = "repos"

	// MetaBucket is the bucket containing the names of the projects with the
	// top 100 high scores, and other meta information
	MetaBucket string = "meta"
)

// CheckHandler handles the request for checking a repo
func CheckHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	repo, err := download.Clean(r.FormValue("repo"))
	if err != nil {
		log.Println("ERROR: from download.Clean:", err)
		http.Error(w, "Could not download the repository: "+err.Error(), http.StatusBadRequest)
		return
	}

	log.Printf("Checking repo %q...", repo)

	forceRefresh := r.Method != "GET" // if this is a GET request, try to fetch from cached version in boltdb first
	resp, err := newChecksResp(repo, forceRefresh)
	if err != nil {
		log.Println("ERROR: from newChecksResp:", err)
		http.Error(w, "Could not analyze the repository: "+err.Error(), http.StatusBadRequest)
		return
	}

	respBytes, err := json.Marshal(resp)
	if err != nil {
		log.Println("ERROR: could not marshal json:", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// write to boltdb
	db, err := bolt.Open(DBPath, 0755, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		log.Println("Failed to open bolt database: ", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	defer db.Close()

	// is this a new repo? if so, increase the count in the high scores bucket later
	isNewRepo := false
	var oldRepoBytes []byte
	err = db.View(func(tx *bolt.Tx) error {
		b := tx.Bucket([]byte(RepoBucket))
		if b == nil {
			return fmt.Errorf("repo bucket not found")
		}
		oldRepoBytes = b.Get([]byte(repo))
		return nil
	})
	if err != nil {
		log.Println("ERROR getting repo from repo bucket:", err)
	}

	isNewRepo = oldRepoBytes == nil

	// if this is a new repo, or the user force-refreshed, update the cache
	if isNewRepo || forceRefresh {
		err = db.Update(func(tx *bolt.Tx) error {
			log.Printf("Saving repo %q to cache...", repo)

			b := tx.Bucket([]byte(RepoBucket))
			if b == nil {
				return fmt.Errorf("repo bucket not found")
			}

			// save repo to cache
			err = b.Put([]byte(repo), respBytes)
			if err != nil {
				return err
			}

			return updateMetadata(tx, resp, repo, isNewRepo)
		})

		if err != nil {
			log.Println("Bolt writing error:", err)
		}

	}

	db.Update(func(tx *bolt.Tx) error {
		// fetch meta-bucket
		mb := tx.Bucket([]byte(MetaBucket))
		return updateRecentlyViewed(mb, repo)
	})

	b, err := json.Marshal(map[string]string{"redirect": "/report/" + repo})
	if err != nil {
		log.Println("JSON marshal error:", err)
	}
	w.WriteHeader(http.StatusOK)
	w.Write(b)
	return
}

func updateHighScores(mb *bolt.Bucket, resp checksResp, repo string) error {
	// check if we need to update the high score list
	if resp.Files < 100 {
		// only repos with >= 100 files are considered for the high score list
		return nil
	}

	// start updating high score list
	scoreBytes := mb.Get([]byte("scores"))
	if scoreBytes == nil {
		scoreBytes, _ = json.Marshal([]ScoreHeap{})
	}
	scores := &ScoreHeap{}
	json.Unmarshal(scoreBytes, scores)

	heap.Init(scores)
	if len(*scores) > 0 && (*scores)[0].Score > resp.Average*100.0 && len(*scores) == 50 {
		// lowest score on list is higher than this repo's score, so no need to add, unless
		// we do not have 50 high scores yet
		return nil
	}
	// if this repo is already in the list, remove the original entry:
	for i := range *scores {
		if strings.ToLower((*scores)[i].Repo) == strings.ToLower(repo) {
			heap.Remove(scores, i)
			break
		}
	}
	// now we can safely push it onto the heap
	heap.Push(scores, scoreItem{
		Repo:  repo,
		Score: resp.Average * 100.0,
		Files: resp.Files,
	})
	if len(*scores) > 50 {
		// trim heap if it's grown to over 50
		*scores = (*scores)[1:51]
	}
	scoreBytes, err := json.Marshal(&scores)
	if err != nil {
		return err
	}
	err = mb.Put([]byte("scores"), scoreBytes)
	if err != nil {
		return err
	}

	return nil
}

func updateReposCount(mb *bolt.Bucket, repo string) (err error) {
	log.Printf("New repo %q, adding to repo count...", repo)
	totalInt := 0
	total := mb.Get([]byte("total_repos"))
	if total != nil {
		err = json.Unmarshal(total, &totalInt)
		if err != nil {
			return fmt.Errorf("could not unmarshal total repos count: %v", err)
		}
	}
	totalInt++ // increase repo count
	total, err = json.Marshal(totalInt)
	if err != nil {
		return fmt.Errorf("could not marshal total repos count: %v", err)
	}
	mb.Put([]byte("total_repos"), total)
	log.Println("Repo count is now", totalInt)
	return nil
}

type recentItem struct {
	Repo string
}

func updateRecentlyViewed(mb *bolt.Bucket, repo string) error {
	if mb == nil {
		return fmt.Errorf("meta bucket not found")
	}
	b := mb.Get([]byte("recent"))
	if b == nil {
		b, _ = json.Marshal([]recentItem{})
	}
	recent := []recentItem{}
	json.Unmarshal(b, &recent)

	// add it to the slice, if it is not in there already
	for i := range recent {
		if recent[i].Repo == repo {
			return nil
		}
	}

	recent = append(recent, recentItem{Repo: repo})
	if len(recent) > 5 {
		// trim recent if it's grown to over 5
		recent = (recent)[1:6]
	}
	b, err := json.Marshal(&recent)
	if err != nil {
		return err
	}
	err = mb.Put([]byte("recent"), b)
	if err != nil {
		return err
	}

	return nil
}

//func updateMetadata(tx *bolt.Tx, resp checksResp, repo string, isNewRepo bool, oldScore *float64) error {
func updateMetadata(tx *bolt.Tx, resp checksResp, repo string, isNewRepo bool) error {
	// fetch meta-bucket
	mb := tx.Bucket([]byte(MetaBucket))
	if mb == nil {
		return fmt.Errorf("high score bucket not found")
	}
	// update total repos count
	if isNewRepo {
		err := updateReposCount(mb, repo)
		if err != nil {
			return err
		}
	}

	return updateHighScores(mb, resp, repo)
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2014 The heketi 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.
//

// TODO: Replace panic() calls with correct returns to the caller

package handlers

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"github.com/lpabon/heketi/plugins"
	"github.com/lpabon/heketi/requests"
	"io"
	"io/ioutil"
	"net/http"
)

type NodeServer struct {
	plugin plugins.Plugin
}

// Handlers
func NewNodeServer(plugin plugins.Plugin) *NodeServer {
	return &NodeServer{
		plugin: plugin,
	}
}

func (n *NodeServer) NodeRoutes() Routes {

	// Node REST URLs routes
	var nodeRoutes = Routes{
		Route{"NodeList", "GET", "/nodes", n.NodeListHandler},
		Route{"NodeAdd", "POST", "/nodes", n.NodeAddHandler},
		Route{"NodeInfo", "GET", "/nodes/{id}", n.NodeInfoHandler},
		Route{"NodeDelete", "DELETE", "/nodes/{id}", n.NodeDeleteHandler},
	}

	return nodeRoutes
}

func (n *NodeServer) NodeListHandler(w http.ResponseWriter, r *http.Request) {

	// Get list
	list, err := n.plugin.NodeList()

	// Must be a server error if we could not get a list
	if err != nil {
		http.Error(w, "unable to get node list", http.StatusInternalServerError)
		return
	}

	// Write msg
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(list); err != nil {
		panic(err)
	}
}

func (n *NodeServer) NodeAddHandler(w http.ResponseWriter, r *http.Request) {
	var msg requests.NodeAddRequest

	body, err := ioutil.ReadAll(io.LimitReader(r.Body, r.ContentLength))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &msg); err != nil {
		http.Error(w, "request unable to be parsed", 422)
		return
	}

	// Add node here
	info, err := n.plugin.NodeAdd(&msg)

	// :TODO:
	// Depending on the error returned here,
	// we should return the correct error code
	if err != nil {
		http.Error(w, "Unable to add the node", http.StatusInternalServerError)
		return
	}

	// Send back we created it (as long as we did not fail)
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusCreated)
	if err := json.NewEncoder(w).Encode(info); err != nil {
		panic(err)
	}
}

func (n *NodeServer) NodeInfoHandler(w http.ResponseWriter, r *http.Request) {

	// Get the id from the URL
	vars := mux.Vars(r)
	id := vars["id"]

	// Call plugin
	info, err := n.plugin.NodeInfo(id)
	if err != nil {
		// Let's guess here and pretend that it failed because
		// it was not found.
		// There probably should be a table of err to http status codes
		http.Error(w, "id not found", http.StatusNotFound)
		return
	}

	// Write msg
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(info); err != nil {
		panic(err)
	}
}

func (n *NodeServer) NodeDeleteHandler(w http.ResponseWriter, r *http.Request) {

	// Get the id from the URL
	vars := mux.Vars(r)

	// Get the id from the URL
	id := vars["id"]

	// Remove node
	err := n.plugin.NodeRemove(id)
	if err != nil {
		// Let's guess here and pretend that it failed because
		// it was not found.
		// There probably should be a table of err to http status codes
		http.Error(w, "id not found", http.StatusNotFound)
		return
	}

	// Send back we created it (as long as we did not fail)
	w.WriteHeader(http.StatusOK)
}
<commit_msg>added parsing to node id on mux<commit_after>//
// Copyright (c) 2014 The heketi 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.
//

// TODO: Replace panic() calls with correct returns to the caller

package handlers

import (
	"encoding/json"
	"github.com/gorilla/mux"
	"github.com/lpabon/heketi/plugins"
	"github.com/lpabon/heketi/requests"
	"io"
	"io/ioutil"
	"net/http"
)

type NodeServer struct {
	plugin plugins.Plugin
}

// Handlers
func NewNodeServer(plugin plugins.Plugin) *NodeServer {
	return &NodeServer{
		plugin: plugin,
	}
}

func (n *NodeServer) NodeRoutes() Routes {

	// Node REST URLs routes
	var nodeRoutes = Routes{
		Route{"NodeList", "GET", "/nodes", n.NodeListHandler},
		Route{"NodeAdd", "POST", "/nodes", n.NodeAddHandler},
		Route{"NodeInfo", "GET", "/nodes/{id:[A-Fa-f0-9]+}", n.NodeInfoHandler},
		Route{"NodeDelete", "DELETE", "/nodes/{id:[A-Fa-f0-9]+}", n.NodeDeleteHandler},
	}

	return nodeRoutes
}

func (n *NodeServer) NodeListHandler(w http.ResponseWriter, r *http.Request) {

	// Get list
	list, err := n.plugin.NodeList()

	// Must be a server error if we could not get a list
	if err != nil {
		http.Error(w, "unable to get node list", http.StatusInternalServerError)
		return
	}

	// Write msg
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(list); err != nil {
		panic(err)
	}
}

func (n *NodeServer) NodeAddHandler(w http.ResponseWriter, r *http.Request) {
	var msg requests.NodeAddRequest

	body, err := ioutil.ReadAll(io.LimitReader(r.Body, r.ContentLength))
	if err != nil {
		panic(err)
	}
	if err := r.Body.Close(); err != nil {
		panic(err)
	}
	if err := json.Unmarshal(body, &msg); err != nil {
		http.Error(w, "request unable to be parsed", 422)
		return
	}

	// Add node here
	info, err := n.plugin.NodeAdd(&msg)

	// :TODO:
	// Depending on the error returned here,
	// we should return the correct error code
	if err != nil {
		http.Error(w, "Unable to add the node", http.StatusInternalServerError)
		return
	}

	// Send back we created it (as long as we did not fail)
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusCreated)
	if err := json.NewEncoder(w).Encode(info); err != nil {
		panic(err)
	}
}

func (n *NodeServer) NodeInfoHandler(w http.ResponseWriter, r *http.Request) {

	// Get the id from the URL
	vars := mux.Vars(r)
	id := vars["id"]

	// Call plugin
	info, err := n.plugin.NodeInfo(id)
	if err != nil {
		// Let's guess here and pretend that it failed because
		// it was not found.
		// There probably should be a table of err to http status codes
		http.Error(w, "id not found", http.StatusNotFound)
		return
	}

	// Write msg
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
	if err := json.NewEncoder(w).Encode(info); err != nil {
		panic(err)
	}
}

func (n *NodeServer) NodeDeleteHandler(w http.ResponseWriter, r *http.Request) {

	// Get the id from the URL
	vars := mux.Vars(r)

	// Get the id from the URL
	id := vars["id"]

	// Remove node
	err := n.plugin.NodeRemove(id)
	if err != nil {
		// Let's guess here and pretend that it failed because
		// it was not found.
		// There probably should be a table of err to http status codes
		http.Error(w, "id not found", http.StatusNotFound)
		return
	}

	// Send back we created it (as long as we did not fail)
	w.WriteHeader(http.StatusOK)
}
<|endoftext|>