<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/dockercn/docker-bucket/drone/pkg/build"
	"github.com/dockercn/docker-bucket/drone/pkg/build/docker"
	"github.com/dockercn/docker-bucket/drone/pkg/build/log"
	"github.com/dockercn/docker-bucket/drone/pkg/build/repo"
	"github.com/dockercn/docker-bucket/drone/pkg/build/script"

	"launchpad.net/goyaml"
)

var (
	// identity file (id_rsa) that will be injected
	// into the container if specified
	identity = flag.String("identity", "", "")

	// runs Drone in parallel mode if True
	parallel = flag.Bool("parallel", false, "")

	// build will timeout after N milliseconds.
	// this will default to 500 minutes (6 hours)
	timeout = flag.Duration("timeout", 300*time.Minute, "")

	// build will run in a privileged container
	privileged = flag.Bool("privileged", false, "")

	// runs Drone with verbose output if True
	verbose = flag.Bool("v", false, "")

	// displays the help / usage if True
	help = flag.Bool("h", false, "")

	// version number, currently deterined by the
	// git revision number (sha)
	version string
)

func init() {
	// default logging
	log.SetPrefix("\033[2m[DRONE] ")
	log.SetSuffix("\033[0m\n")
	log.SetOutput(os.Stdout)
	log.SetPriority(log.LOG_NOTICE)
}

func main() {
	// Parse the input parameters
	flag.Usage = usage
	flag.Parse()

	if *help {
		flag.Usage()
		os.Exit(0)
	}

	if *verbose {
		log.SetPriority(log.LOG_DEBUG)
	}

	// Must speicify a command
	args := flag.Args()
	if len(args) == 0 {
		flag.Usage()
		os.Exit(0)
	}

	switch {
	// run drone build assuming the current
	// working directory contains the drone.yml
	case args[0] == "build" && len(args) == 1:
		path, _ := os.Getwd()
		path = filepath.Join(path, ".drone.yml")
		run(path)

	// run drone build where the path to the
	// source directory is provided
	case args[0] == "build" && len(args) == 2:
		path := args[1]
		path = filepath.Clean(path)
		fmt.Printf(path)
		//path, _ = filepath.Abs(path)
		path = filepath.Join(path, ".drone.yml")
		run(path)

	// run drone vet where the path to the
	// source directory is provided
	case args[0] == "vet" && len(args) == 2:
		path := args[1]
		path = filepath.Clean(path)
		path, _ = filepath.Abs(path)
		path = filepath.Join(path, ".drone.yml")
		vet(path)

	// run drone vet assuming the current
	// working directory contains the drone.yml
	case args[0] == "vet" && len(args) == 1:
		path, _ := os.Getwd()
		path = filepath.Join(path, ".drone.yml")
		vet(path)

	// print the version / revision number
	case args[0] == "version" && len(args) == 1:
		println(version)

	// print the help message
	case args[0] == "help" && len(args) == 1:
		flag.Usage()
	}

	os.Exit(0)
}

func vet(path string) {
	// parse the Drone yml file
	script, err := script.ParseBuildFile(path)
	if err != nil {
		log.Err(err.Error())
		os.Exit(1)
		return
	}

	// print the Drone yml as parsed
	out, _ := goyaml.Marshal(script)
	log.Noticef("parsed yaml:\n%s", string(out))
}

func run(path string) {
	dockerClient := docker.New()

	// parse the Drone yml file
	s, err := script.ParseBuildFile(path)
	if err != nil {
		log.Err(err.Error())
		os.Exit(1)
		return
	}

	// get the repository root directory
	dir := filepath.Dir(path)
	code := repo.Repo{
		Name:   filepath.Base(dir),
		Branch: "HEAD", // should we do this?
		Path:   dir,
	}

	// does the local repository match the
	// $GOPATH/src/{package} pattern? This is
	// important so we know the target location
	// where the code should be copied inside
	// the container.
	if gopath, ok := getRepoPath(dir); ok {
		code.Dir = gopath

	} else if gopath, ok := getGoPath(dir); ok {
		// in this case we found a GOPATH and
		// reverse engineered the package path
		code.Dir = gopath

	} else {
		// otherwise just use directory name
		code.Dir = filepath.Base(dir)
	}

	// this is where the code gets uploaded to the container
	// TODO move this code to the build package
	code.Dir = filepath.Join("/var/cache/drone/src", filepath.Clean(code.Dir))

	// track all build results
	var builders []*build.Builder

	// ssh key to import into container
	var key []byte
	if len(*identity) != 0 {
		key, err = ioutil.ReadFile(*identity)
		if err != nil {
			fmt.Printf("[Error] Could not find or read identity file %s\n", *identity)
			os.Exit(1)
			return
		}
	}

	builds := []*script.Build{s}

	// loop through and create builders
	for _, b := range builds { //script.Builds {
		builder := build.New(dockerClient)
		builder.Build = b
		builder.Repo = &code
		builder.Key = key
		builder.Stdout = os.Stdout
		builder.Timeout = *timeout
		builder.Privileged = *privileged

		if *parallel == true {
			var buf bytes.Buffer
			builder.Stdout = &buf
		}

		builders = append(builders, builder)
	}

	switch *parallel {
	case false:
		runSequential(builders)
	case true:
		runParallel(builders)
	}

	// if in parallel mode, print out the buffer
	// if we had a failure
	for _, builder := range builders {
		if builder.BuildState.ExitCode == 0 {
			continue
		}

		if buf, ok := builder.Stdout.(*bytes.Buffer); ok {
			log.Noticef("printing stdout for failed build %s", builder.Build.Name)
			println(buf.String())
		}
	}

	// this exit code is initially 0 and will
	// be set to an error code if any of the
	// builds fail.
	var exit int

	fmt.Printf("\nDrone Build Results \033[90m(%v)\033[0m\n", len(builders))

	// loop through and print results
	for _, builder := range builders {
		build := builder.Build
		res := builder.BuildState
		duration := time.Duration(res.Finished - res.Started)
		switch {
		case builder.BuildState.ExitCode == 0:
			fmt.Printf(" \033[32m\u2713\033[0m %v \033[90m(%v)\033[0m\n", build.Name, humanizeDuration(duration*time.Second))
		case builder.BuildState.ExitCode != 0:
			fmt.Printf(" \033[31m\u2717\033[0m %v \033[90m(%v)\033[0m\n", build.Name, humanizeDuration(duration*time.Second))
			exit = builder.BuildState.ExitCode
		}
	}

	os.Exit(exit)
}

func runSequential(builders []*build.Builder) {
	// loop through and execute each build
	for _, builder := range builders {
		if err := builder.Run(); err != nil {
			log.Errf("Error executing build: %s", err.Error())
			os.Exit(1)
		}
	}
}

func runParallel(builders []*build.Builder) {
	// spawn four worker goroutines
	var wg sync.WaitGroup
	for _, builder := range builders {
		// Increment the WaitGroup counter
		wg.Add(1)
		// Launch a goroutine to run the build
		go func(builder *build.Builder) {
			defer wg.Done()
			builder.Run()
		}(builder)
		time.Sleep(500 * time.Millisecond) // get weird iptables failures unless we sleep.
	}

	// wait for the workers to finish
	wg.Wait()
}

var usage = func() {
	fmt.Println(`Drone is a tool for building and testing code in Docker containers.

Usage:

	drone command [arguments]

The commands are:

   build           build and test the repository
   version         print the version number
   vet             validate the yaml configuration file

  -v               runs drone with verbose output
  -h               display this help and exit
  --parallel       runs drone build tasks in parallel
  --timeout=300ms  timeout build after 300 milliseconds
  --privileged     runs drone build in a privileged container

Examples:
  drone build                 builds the source in the pwd
  drone build /path/to/repo   builds the source repository

Use "drone help [command]" for more information about a command.
`)
}
<commit_msg>dry run ok.<commit_after>package main

import (
	"fmt"
	//"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"time"

	"github.com/dockercn/docker-bucket/drone/pkg/build"
	"github.com/dockercn/docker-bucket/drone/pkg/build/docker"
	"github.com/dockercn/docker-bucket/drone/pkg/build/log"
	"github.com/dockercn/docker-bucket/drone/pkg/build/repo"
	"github.com/dockercn/docker-bucket/drone/pkg/build/script"
)

var (
	// version number, currently deterined by the
	// git revision number (sha)
	version string
)

func init() {
	// default logging
	log.SetPrefix("\033[2m[DRONE] ")
	log.SetSuffix("\033[0m\n")
	log.SetOutput(os.Stdout)
	log.SetPriority(log.LOG_NOTICE)
}

func drone(yaml string) {
	run(yaml)
}

func main() {
	yaml := "../tests/drone/sample.yml"
	drone(yaml)
}

func run(path string) {
	dockerClient := docker.New()

	// parse the Drone yml file
	s, err := script.ParseBuildFile(path)
	//fmt.Println(s.Repo)
	if err != nil {
		log.Err(err.Error())
		os.Exit(1)
		return
	}

	// get the repository url
	// here we should use githubapi to accplish this
	//dir := filepath.Dir(path)
	code := repo.Repo{
		//Name:   filepath.Base(dir),
		Name:   "test",
		Branch: "HEAD", // should we do this?
		Path:   s.Repo,
	}

	// this is where the code gets uploaded to the container
	// TODO move this code to the build package
	code.Dir = filepath.Join("/var/cache/drone/src", s.Repo)

	// track all build results
	var builders []*build.Builder

	builds := []*script.Build{s}

	// loop through and create builders
	for _, b := range builds { //script.Builds {
		builder := build.New(dockerClient)
		builder.Build = b
		builder.Repo = &code
		//builder.Key = key
		builder.Stdout = os.Stdout
		builder.Timeout = 300 * time.Minute
		//builder.Privileged = *privileged

		//if *parallel == true {
		//var buf bytes.Buffer
		//builder.Stdout = &buf
		//}

		builders = append(builders, builder)
	}

	//switch *parallel {
	//case false:
	runSequential(builders)
	//case true:
	//runParallel(builders)
	//}

	// this exit code is initially 0 and will
	// be set to an error code if any of the
	// builds fail.
	var exit int

	fmt.Printf("\nDrone Build Results \033[90m(%v)\033[0m\n", len(builders))

	// loop through and print results
	for _, builder := range builders {
		build := builder.Build
		res := builder.BuildState
		duration := time.Duration(res.Finished - res.Started)
		switch {
		case builder.BuildState.ExitCode == 0:
			fmt.Printf(" \033[32m\u2713\033[0m %v \033[90m(%v)\033[0m\n", build.Name, humanizeDuration(duration*time.Second))
		case builder.BuildState.ExitCode != 0:
			fmt.Printf(" \033[31m\u2717\033[0m %v \033[90m(%v)\033[0m\n", build.Name, humanizeDuration(duration*time.Second))
			exit = builder.BuildState.ExitCode
		}
	}

	os.Exit(exit)
}

func runSequential(builders []*build.Builder) {
	// loop through and execute each build
	for _, builder := range builders {
		if err := builder.Run(); err != nil {
			log.Errf("Error executing build: %s", err.Error())
			os.Exit(1)
		}
	}
}

func runParallel(builders []*build.Builder) {
	// spawn four worker goroutines
	var wg sync.WaitGroup
	for _, builder := range builders {
		// Increment the WaitGroup counter
		wg.Add(1)
		// Launch a goroutine to run the build
		go func(builder *build.Builder) {
			defer wg.Done()
			builder.Run()
		}(builder)
		time.Sleep(500 * time.Millisecond) // get weird iptables failures unless we sleep.
	}

	// wait for the workers to finish
	wg.Wait()
}
<|endoftext|>


<commit_before>/*
  REVISION HISTORY
  ----------------
  20 Mar 20 -- Made comparisons case insensitive.  And decided to make this cgrepi.go.
                 And then I figured I could not improve performance by using more packages.
                 But I can change the side effect of displaying altered case.
  21 Mar 20 -- Another ack name change, to anack.go.  My plan is to reproduce the function of ack, but on windows not require
                 the complex installation that I cannot do at work.
                 I'll use multiple processes for the grep work.  For the dir walking I'll just do that in main.
  30 Mar 20 -- Started work on extracting the extensions from a slice of input filenames.  And will assume .txt extension if none is provided.

                  Now used as the template for dsrt recursive, named dsrtr.go
*/
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"runtime"
)

const lastAltered = "31 Mar 2020"

func main() {
	//	runtime.GOMAXPROCS(runtime.NumCPU()) // Use all the machine's cores
	log.SetFlags(0)
	var timeoutOpt *int = flag.Int("timeout", 0, "seconds < 240, where 0 means max timeout of 240 sec.")
	flag.Parse()
	if *timeoutOpt < 0 || *timeoutOpt > 240 {
		log.Fatalln("timeout must be in the range [0,240] seconds")
	}
	if *timeoutOpt == 0 {
		*timeoutOpt = 240
	}

	args := flag.Args()
	pattern := strings.ToLower(args[0])

	if len(args) < 1 {
		log.Fatalln("a pattern to match must be specified")
	} else if len(args) == 1 {
		//pattern = strings.ToLower(pattern)
		//fmt.Println(" pattern=", pattern)
	} else {
		// I cannot think of anything to put here at the moment.  I'll say that args must be a slice of strings of filenames, and on linux.
	}

	startDirectory, _ := os.Getwd() // startDirectory is a string
	fmt.Println()
	fmt.Printf(" dsrtr (recursive), written in Go.  Last altered %s, and will start in %s.", lastAltered, startDirectory)
	fmt.Println()
	fmt.Println()
	DirAlreadyWalked := make(map[string]bool, 500)
	DirAlreadyWalked[".git"] = true // ignore .git and its subdir's

	t0 := time.Now()
	tfinal := t0.Add(time.Duration(*timeoutOpt) * time.Second)

	// walkfunc closure
	filepathwalkfunction := func(fpath string, fi os.FileInfo, err error) error {
		if err != nil {
			fmt.Printf(" Error from walk is %v. \n ", err)
			return nil
		}

		if fi.IsDir() {
			if DirAlreadyWalked[fpath] {
				return filepath.SkipDir
			} else {
				DirAlreadyWalked[fpath] = true
			}
		} else if fi.Mode().IsRegular() {
			if runtime.GOOS == "linux" {
				for _, fp := range args {
					fp = strings.ToLower(fp)
					NAME := strings.ToLower(fi.Name())
					if BOOL, _ := filepath.Match(fp, NAME); BOOL {
						s := fi.ModTime().Format("Jan-02-2006_15:04:05")
						sizeint := int(fi.Size())
						sizestr := strconv.Itoa(sizeint)
						if sizeint > 100000 {
							sizestr = AddCommas(sizestr)
						}
						usernameStr, groupnameStr := GetUserGroupStr(fi) // util function in platform specific removed Oct 4, 2019 and then unremoved.
						fmt.Printf("%10v %s:%s %15s %s %s\n", fi.Mode(), usernameStr, groupnameStr, sizestr, s, fpath)
					}
				}
			} else if runtime.GOOS == "windows" {
				//NAME := strings.ToLower(fi.Name())  Not a case sensitive filesystem
				//fmt.Println(" pattern=", pattern, ", fi.Name=", fi.Name(), ", fpath=", fpath)
				if BOOL, _ := filepath.Match(pattern, fi.Name()); BOOL {
					s := fi.ModTime().Format("Jan-02-2006_15:04:05")
					sizeint := int(fi.Size())
					sizestr := strconv.Itoa(sizeint)
					if sizeint > 100000 {
						sizestr = AddCommas(sizestr)
					}
					fmt.Printf("%15s %s %s\n", sizestr, s, fpath)
				}
			}
			now := time.Now()
			if now.After(tfinal) {
				log.Fatalln(" Time up.  Elapsed is", time.Since(t0))
			}
		}
		return nil
	}

	err := filepath.Walk(startDirectory, filepathwalkfunction)

	if err != nil {
		log.Fatalln(" Error from filepath.walk is", err, ".  Elapsed time is", time.Since(t0))
	}

	elapsed := time.Since(t0)
	fmt.Println(" Elapsed time is", elapsed)
	fmt.Println()
} // end main

//-------------------------------------------------------------------- InsertByteSlice
func InsertIntoByteSlice(slice, insertion []byte, index int) []byte {
	return append(slice[:index], append(insertion, slice[index:]...)...)
} // InsertIntoByteSlice

//---------------------------------------------------------------------- AddCommas
func AddCommas(instr string) string {
	var Comma []byte = []byte{','}

	BS := make([]byte, 0, 15)
	BS = append(BS, instr...)

	i := len(BS)

	for NumberOfCommas := i / 3; (NumberOfCommas > 0) && (i > 3); NumberOfCommas-- {
		i -= 3
		BS = InsertIntoByteSlice(BS, Comma, i)
	}
	return string(BS)
} // AddCommas

// ---------------------------- GetIDname -----------------------------------------------------------
func GetIDname(uidStr string) string {

	if len(uidStr) == 0 {
		return ""
	}
	ptrToUser, err := user.LookupId(uidStr)
	if err != nil {
		panic("uid not found")
	}

	idname := ptrToUser.Username
	return idname

} // GetIDname
/*
{{{
	if linuxflag {
		for _, f := range files {
			s := f.ModTime().Format("Jan-02-2006_15:04:05")
			sizeint := 0
			sizestr := ""
			usernameStr, groupnameStr := GetUserGroupStr(f) // util function in platform specific removed Oct 4, 2019 and then unremoved.
			if FilenameList && f.Mode().IsRegular() {
				SizeTotal += f.Size()
				sizeint = int(f.Size())
				sizestr = strconv.Itoa(sizeint)
				if sizeint > 100000 {
					sizestr = AddCommas(sizestr)
				}
				fmt.Printf("%10v %s:%s %15s %s %s\n", f.Mode(), usernameStr, groupnameStr, sizestr, s, f.Name())
				count++
			} else if IsSymlink(f.Mode()) {
				fmt.Printf("%10v %s:%s %15s %s <%s>\n", f.Mode(), usernameStr, groupnameStr, sizestr, s, f.Name())
				count++
			} else if Dirlist && f.IsDir() {
				fmt.Printf("%10v %s:%s %15s %s (%s)\n", f.Mode(), usernameStr, groupnameStr, sizestr, s, f.Name())
				count++
			}
			if count >= NumLines {
				break
			}
		}
	} else if winflag {
		for _, f := range files {
			NAME := strings.ToUpper(f.Name())
			if BOOL, _ := filepath.Match(CleanFileName, NAME); BOOL {
				s := f.ModTime().Format("Jan-02-2006_15:04:05")
				sizeint := 0
				sizestr := ""
				if FilenameList && f.Mode().IsRegular() {
					SizeTotal += f.Size()
					sizeint = int(f.Size())
					sizestr = strconv.Itoa(sizeint)
					if sizeint > 100000 {
						sizestr = AddCommas(sizestr)
					}
					fmt.Printf("%15s %s %s\n", sizestr, s, f.Name())
					count++
				} else if IsSymlink(f.Mode()) {
					fmt.Printf("%15s %s <%s>\n", sizestr, s, f.Name())
					count++
				} else if Dirlist && f.IsDir() {
					fmt.Printf("%15s %s (%s)\n", sizestr, s, f.Name())
					count++
				}
				if count >= NumLines {
					break
				}
			}
		}
	}

}}}
*/
/*
{{{
// ------------------------------ IsSymlink ---------------------------
func IsSymlink(m os.FileMode) bool {
	intermed := m & os.ModeSymlink
	result := intermed != 0
	return result
} // IsSymlink
}}}
*/
<commit_msg>04/01/2020 07:52:04 AM dsrtr/dsrtr.go<commit_after>/*
  REVISION HISTORY
  ----------------
  20 Mar 20 -- Made comparisons case insensitive.  And decided to make this cgrepi.go.
                 And then I figured I could not improve performance by using more packages.
                 But I can change the side effect of displaying altered case.
  21 Mar 20 -- Another ack name change, to anack.go.  My plan is to reproduce the function of ack, but on windows not require
                 the complex installation that I cannot do at work.
                 I'll use multiple processes for the grep work.  For the dir walking I'll just do that in main.
  30 Mar 20 -- Started work on extracting the extensions from a slice of input filenames.  And will assume .txt extension if none is provided.

                  Now used as the template for dsrt recursive, named dsrtr.go
*/
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/user"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"runtime"
)

const lastAltered = "1 Apr 2020"

func main() {
	//	runtime.GOMAXPROCS(runtime.NumCPU()) // Use all the machine's cores
	log.SetFlags(0)
	var timeoutOpt *int = flag.Int("timeout", 0, "seconds < 240, where 0 means max timeout of 240 sec.")
	flag.Parse()
	if *timeoutOpt < 0 || *timeoutOpt > 240 {
		log.Fatalln("timeout must be in the range [0,240] seconds")
	}
	if *timeoutOpt == 0 {
		*timeoutOpt = 240
	}

	args := flag.Args()
	pattern := strings.ToLower(args[0])

	if len(args) < 1 {
		log.Fatalln("a pattern to match must be specified")
	} else if len(args) == 1 {
		//pattern = strings.ToLower(pattern)
		//fmt.Println(" pattern=", pattern)
	} else {
		// I cannot think of anything to put here at the moment.  I'll say that args must be a slice of strings of filenames, and on linux.
	}

	startDirectory, _ := os.Getwd() // startDirectory is a string
	fmt.Println()
	fmt.Printf(" dsrtr (recursive), written in Go.  Last altered %s, and will start in %s.", lastAltered, startDirectory)
	fmt.Println()
	fmt.Println()
	DirAlreadyWalked := make(map[string]bool, 500)
	DirAlreadyWalked[".git"] = true // ignore .git and its subdir's

	t0 := time.Now()
	tfinal := t0.Add(time.Duration(*timeoutOpt) * time.Second)

	// walkfunc closure
	filepathwalkfunction := func(fpath string, fi os.FileInfo, err error) error {
		if err != nil {
			fmt.Printf(" Error from walk is %v. \n ", err)
			return nil
		}

		if fi.IsDir() {
			if DirAlreadyWalked[fpath] {
				return filepath.SkipDir
			} else {
				DirAlreadyWalked[fpath] = true
			}
		} else if fi.Mode().IsRegular() {
			if runtime.GOOS == "linux" {
				for _, fp := range args {
					fp = strings.ToLower(fp)
					NAME := strings.ToLower(fi.Name())
					if BOOL, _ := filepath.Match(fp, NAME); BOOL {
						s := fi.ModTime().Format("Jan-02-2006_15:04:05")
						sizeint := int(fi.Size())
						sizestr := strconv.Itoa(sizeint)
						if sizeint > 100000 {
							sizestr = AddCommas(sizestr)
						}
						usernameStr, groupnameStr := GetUserGroupStr(fi) // util function in platform specific removed Oct 4, 2019 and then unremoved.
						fmt.Printf("%10v %s:%s %15s %s %s\n", fi.Mode(), usernameStr, groupnameStr, sizestr, s, fpath)
					}
				}
			} else if runtime.GOOS == "windows" {
				//NAME := strings.ToLower(fi.Name())  Not a case sensitive filesystem
				//fmt.Println(" pattern=", pattern, ", fi.Name=", fi.Name(), ", fpath=", fpath)
				if BOOL, _ := filepath.Match(pattern, fi.Name()); BOOL {
					s := fi.ModTime().Format("Jan-02-2006_15:04:05")
					sizeint := int(fi.Size())
					sizestr := strconv.Itoa(sizeint)
					if sizeint > 100000 {
						sizestr = AddCommas(sizestr)
					}
					fmt.Printf("%15s %s %s\n", sizestr, s, fpath)
				}
			}
			now := time.Now()
			if now.After(tfinal) {
				log.Fatalln(" Time up.  Elapsed is", time.Since(t0))
			}
		}
		return nil
	}

	err := filepath.Walk(startDirectory, filepathwalkfunction)

	if err != nil {
		log.Fatalln(" Error from filepath.walk is", err, ".  Elapsed time is", time.Since(t0))
	}

	elapsed := time.Since(t0)
	fmt.Println(" Elapsed time is", elapsed)
	fmt.Println()
} // end main

//-------------------------------------------------------------------- InsertByteSlice
func InsertIntoByteSlice(slice, insertion []byte, index int) []byte {
	return append(slice[:index], append(insertion, slice[index:]...)...)
} // InsertIntoByteSlice

//---------------------------------------------------------------------- AddCommas
func AddCommas(instr string) string {
	var Comma []byte = []byte{','}

	BS := make([]byte, 0, 15)
	BS = append(BS, instr...)

	i := len(BS)

	for NumberOfCommas := i / 3; (NumberOfCommas > 0) && (i > 3); NumberOfCommas-- {
		i -= 3
		BS = InsertIntoByteSlice(BS, Comma, i)
	}
	return string(BS)
} // AddCommas

// ---------------------------- GetIDname -----------------------------------------------------------
func GetIDname(uidStr string) string {

	if len(uidStr) == 0 {
		return ""
	}
	ptrToUser, err := user.LookupId(uidStr)
	if err != nil {
		panic("uid not found")
	}

	idname := ptrToUser.Username
	return idname

} // GetIDname
/*
{{{
	if linuxflag {
		for _, f := range files {
			s := f.ModTime().Format("Jan-02-2006_15:04:05")
			sizeint := 0
			sizestr := ""
			usernameStr, groupnameStr := GetUserGroupStr(f) // util function in platform specific removed Oct 4, 2019 and then unremoved.
			if FilenameList && f.Mode().IsRegular() {
				SizeTotal += f.Size()
				sizeint = int(f.Size())
				sizestr = strconv.Itoa(sizeint)
				if sizeint > 100000 {
					sizestr = AddCommas(sizestr)
				}
				fmt.Printf("%10v %s:%s %15s %s %s\n", f.Mode(), usernameStr, groupnameStr, sizestr, s, f.Name())
				count++
			} else if IsSymlink(f.Mode()) {
				fmt.Printf("%10v %s:%s %15s %s <%s>\n", f.Mode(), usernameStr, groupnameStr, sizestr, s, f.Name())
				count++
			} else if Dirlist && f.IsDir() {
				fmt.Printf("%10v %s:%s %15s %s (%s)\n", f.Mode(), usernameStr, groupnameStr, sizestr, s, f.Name())
				count++
			}
			if count >= NumLines {
				break
			}
		}
	} else if winflag {
		for _, f := range files {
			NAME := strings.ToUpper(f.Name())
			if BOOL, _ := filepath.Match(CleanFileName, NAME); BOOL {
				s := f.ModTime().Format("Jan-02-2006_15:04:05")
				sizeint := 0
				sizestr := ""
				if FilenameList && f.Mode().IsRegular() {
					SizeTotal += f.Size()
					sizeint = int(f.Size())
					sizestr = strconv.Itoa(sizeint)
					if sizeint > 100000 {
						sizestr = AddCommas(sizestr)
					}
					fmt.Printf("%15s %s %s\n", sizestr, s, f.Name())
					count++
				} else if IsSymlink(f.Mode()) {
					fmt.Printf("%15s %s <%s>\n", sizestr, s, f.Name())
					count++
				} else if Dirlist && f.IsDir() {
					fmt.Printf("%15s %s (%s)\n", sizestr, s, f.Name())
					count++
				}
				if count >= NumLines {
					break
				}
			}
		}
	}

}}}
*/
/*
{{{
// ------------------------------ IsSymlink ---------------------------
func IsSymlink(m os.FileMode) bool {
	intermed := m & os.ModeSymlink
	result := intermed != 0
	return result
} // IsSymlink
}}}
*/
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"go/parser"
	"go/printer"
	"go/ast"
	"go/token"
	"log"
	"os"
)

var (
	srcFn   = flag.String("src", "", "source filename")
	getName = flag.String("name", "", "func/type name to output")
	html    = flag.Bool("html", true, "output HTML")
	showPkg = flag.Bool("pkg", false, "show package in output")
)

func main() {
	// handle input
	flag.Parse()
	if *srcFn == "" || *getName == "" {
		flag.Usage()
		os.Exit(2)
	}
	// load file
	fs := token.NewFileSet()
	file, err := parser.ParseFile(fs, *srcFn, nil, 0)
	if err != nil {
		log.Fatal(err)
	}
	// create printer
	p := &printer.Config{
		Mode:     0,
		Tabwidth: 8,
		Styler:   nil,
	}
	if *html {
		p.Mode = printer.GenHTML
	}
	// create filter
	filter := func(name string) bool {
		return name == *getName
	}
	// filter
	if !ast.FilterFile(file, filter) {
		os.Exit(1)
	}
	b := new(bytes.Buffer)
	p.Fprint(b, fs, file)
	// drop package declaration
	if !*showPkg {
		for {
			c, err := b.ReadByte()
			if c == '\n' || err != nil {
				break
			}
		}
	}
	// drop leading newlines
	for {
		b, err := b.ReadByte()
		if err != nil {
			break
		}
		if b != '\n' {
			os.Stdout.Write([]byte{b})
			break
		}
	}
	// output
	b.WriteTo(os.Stdout)
}
<commit_msg>codelab: update due to recent changes in go/printer<commit_after>package main

import (
	"bytes"
	"flag"
	"go/parser"
	"go/printer"
	"go/ast"
	"go/token"
	"log"
	"os"
)

var (
	srcFn   = flag.String("src", "", "source filename")
	getName = flag.String("name", "", "func/type name to output")
	html    = flag.Bool("html", true, "output HTML")
	showPkg = flag.Bool("pkg", false, "show package in output")
)

func main() {
	// handle input
	flag.Parse()
	if *srcFn == "" || *getName == "" {
		flag.Usage()
		os.Exit(2)
	}
	// load file
	fs := token.NewFileSet()
	file, err := parser.ParseFile(fs, *srcFn, nil, 0)
	if err != nil {
		log.Fatal(err)
	}
	// create printer
	p := &printer.Config{
		Mode:     0,
		Tabwidth: 8,
	}
	// create filter
	filter := func(name string) bool {
		return name == *getName
	}
	// filter
	if !ast.FilterFile(file, filter) {
		os.Exit(1)
	}
	b := new(bytes.Buffer)
	p.Fprint(b, fs, file)
	// drop package declaration
	if !*showPkg {
		for {
			c, err := b.ReadByte()
			if c == '\n' || err != nil {
				break
			}
		}
	}
	// drop leading newlines
	for {
		b, err := b.ReadByte()
		if err != nil {
			break
		}
		if b != '\n' {
			os.Stdout.Write([]byte{b})
			break
		}
	}
	// output
	b.WriteTo(os.Stdout)
}
<|endoftext|>


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

package osenv

import (
	"testing"
)

func TestMustVar_ReturnsValueWhenEnvVarSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	glogExitf = t.Fatalf

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "env-var-value" }

	key := "set-env-var"
	got := MustVar(key)

	want := "env-var-value"
	if want != got {
		t.Fatalf("MustVar(%v) = %v, want %v", key, got, want)
	}
}

func TestMustVar_DoesNotExitWhenEnvVarSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	exited := false
	glogExitf = func(format string, args ...interface{}) { exited = true }

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "env-var-value" }

	key := "set-env-var"
	MustVar(key)

	if exited {
		t.Fatal("MustVar(%v) exited.", key)
	}
}

func TestMustVar_ExitsWhenEnvVarNotSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	exited := false
	glogExitf = func(format string, args ...interface{}) { exited = true }

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "" }

	key := "unset-env-var"
	MustVar(key)

	if !exited {
		t.Fatal("MustVar(%v) did not exit.", key)
	}
}

func TestVarWithDefault_ReturnsValueWhenEnvVarSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	glogExitf = t.Fatalf

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "env-var-value" }

	key := "set-env-var"
	got := VarWithDefault(key, "default-value")

	want := "env-var-value"
	if want != got {
		t.Fatalf("MustVar(%v) = %v, want %v", key, got, want)
	}
}

func TestVarWithDefault_ReturnsDefaultValueWhenEnvVarNotSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	glogExitf = t.Fatalf

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "" }

	key := "set-env-var"
	got := VarWithDefault(key, "default-value")

	want := "default-value"
	if want != got {
		t.Fatalf("MustVar(%v) = %v, want %v", key, got, want)
	}
}
<commit_msg>fix typo in osenv_test.go<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package osenv

import (
	"testing"
)

func TestMustVar_ReturnsValueWhenEnvVarSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	glogExitf = t.Fatalf

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "env-var-value" }

	key := "set-env-var"
	got := MustVar(key)

	want := "env-var-value"
	if want != got {
		t.Fatalf("MustVar(%v) = %v, want %v", key, got, want)
	}
}

func TestMustVar_DoesNotExitWhenEnvVarSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	exited := false
	glogExitf = func(format string, args ...interface{}) { exited = true }

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "env-var-value" }

	key := "set-env-var"
	MustVar(key)

	if exited {
		t.Fatalf("MustVar(%v) exited.", key)
	}
}

func TestMustVar_ExitsWhenEnvVarNotSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	exited := false
	glogExitf = func(format string, args ...interface{}) { exited = true }

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "" }

	key := "unset-env-var"
	MustVar(key)

	if !exited {
		t.Fatalf("MustVar(%v) did not exit.", key)
	}
}

func TestVarWithDefault_ReturnsValueWhenEnvVarSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	glogExitf = t.Fatalf

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "env-var-value" }

	key := "set-env-var"
	got := VarWithDefault(key, "default-value")

	want := "env-var-value"
	if want != got {
		t.Fatalf("MustVar(%v) = %v, want %v", key, got, want)
	}
}

func TestVarWithDefault_ReturnsDefaultValueWhenEnvVarNotSet(t *testing.T) {
	glogExitfOrg := glogExitf
	defer func() { glogExitf = glogExitfOrg }()
	glogExitf = t.Fatalf

	osGetEnvOrg := osGetEnv
	defer func() { osGetEnv = osGetEnvOrg }()
	osGetEnv = func(key string) string { return "" }

	key := "set-env-var"
	got := VarWithDefault(key, "default-value")

	want := "default-value"
	if want != got {
		t.Fatalf("MustVar(%v) = %v, want %v", key, got, want)
	}
}
<|endoftext|>


<commit_before>package wspacego

import (
	. "github.com/r7kamura/gospel"
	"testing"
)

func TestConerter(t *testing.T) {
	Describe(t, "whitespace のソースを文字や読みやすい文字列に変換する", func() {
		Context("インスタンスの生成", func() {
			It("インスタンスが作成されること", func() {
				Expect(NewConverter()).To(Exist)
			})
		})
		Context("スタックに関連する命令の生成", func() {
			It("スタックに１をプッシュするコマンドが作成されること", func() {
				data := []byte{' ', '\t', '\n'}
				sut := NewConverter()
				cmd, seek, err := sut.stackManipulation(data)
				Expect(err).To(NotExist)
				Expect(cmd).To(Exist)
				Expect(seek).To(Equal, 3)
			})
		})
	})
}
<commit_msg>スタックに２と４を積む命令のテストケースを追加<commit_after>package wspacego

import (
	. "github.com/r7kamura/gospel"
	"testing"
)

func TestConerter(t *testing.T) {
	Describe(t, "whitespace のソースを文字や読みやすい文字列に変換する", func() {
		Context("インスタンスの生成", func() {
			It("インスタンスが作成されること", func() {
				Expect(NewConverter()).To(Exist)
			})
		})
		Context("スタックに関連する命令の生成", func() {
			It("スタックに１をプッシュするコマンドが作成されること", func() {
				data := []byte{' ', '\t', '\n'}
				sut := NewConverter()
				cmd, seek, err := sut.stackManipulation(data)
				Expect(err).To(NotExist)
				Expect(seek).To(Equal, len(data))
				Expect(cmd).To(Exist)
				Expect(cmd).To(Equal, NewSubCommandWithParam("stack", "push", 1))
			})
			It("スタックに2をプッシュするコマンドが作成されること", func() {
				data := []byte{' ', '\t', ' ', '\n'}
				sut := NewConverter()
				cmd, seek, err := sut.stackManipulation(data)
				Expect(err).To(NotExist)
				Expect(seek).To(Equal, len(data))
				Expect(cmd).To(Exist)
				Expect(cmd).To(Equal, NewSubCommandWithParam("stack", "push", 2))
			})
			It("スタックに4をプッシュするコマンドが作成されること", func() {
				data := []byte{' ', '\t', ' ', ' ', '\n'}
				sut := NewConverter()
				cmd, seek, err := sut.stackManipulation(data)
				Expect(err).To(NotExist)
				Expect(seek).To(Equal, len(data))
				Expect(cmd).To(Exist)
				Expect(cmd).To(Equal, NewSubCommandWithParam("stack", "push", 4))
			})
		})
	})
}
<|endoftext|>


<commit_before>package commandline

import (
	"fmt"
	"strings"
)

func Parse(s string) *Command {
	ss := strings.Split(s, " ")
	if ss[0] == "" {
		return nil
	}
	return &Command{
		Name: ss[0],
		Args: ss[1:],
	}
}

type Command struct {
	Name string
	Args []string
}

type scanner struct {
	src  []byte
	size int
	off  int
}

func newScanner(src []byte) *scanner {
	return &scanner{
		src:  src,
		size: len(src),
	}
}

func (s *scanner) next() (byte, bool) {
	if s.off >= s.size {
		return 0, true
	}

	ret := s.src[s.off]

	s.off++
	return ret, false
}

func (s *scanner) scan() (*token, error) {
	ch, eof := s.next()
	if eof {
		return nil, nil
	}
	switch {
	case isIdent(ch):
		var ret []byte
		for isIdent(ch) {
			ch, eof = s.next()
			if eof {
				break
			}
			ret = append(ret, ch)
		}
		return &token{tt: ident, value: ret}, nil
	case ch == '"':
		var ret []byte
		for ch != '"' {
			ch, eof = s.next()
			if eof {
				return nil, fmt.Errorf("unexpected eof in string literal at offset: %d", s.off)
			}
			ret = append(ret, ch)
		}
		return &token{tt: str, value: ret}, nil
	case isWhitespace(ch):
		return s.scan()
	}
	return nil, fmt.Errorf("unexpected character at offset: %d", s.off)
}

type scanError struct {
	msg string
	off int
}

func isWhitespace(b byte) bool {
	return b == ' '
}

func isIdent(b byte) bool {
	return 'A' <= b && b <= 'Z' || 'a' <= b && b <= 'z'
}

type tokenType int

type token struct {
	tt    tokenType
	value []byte
}

const (
	ident tokenType = iota
	str
)
<commit_msg>Add scanError.Error<commit_after>package commandline

import (
	"fmt"
	"strings"
)

func Parse(s string) *Command {
	ss := strings.Split(s, " ")
	if ss[0] == "" {
		return nil
	}
	return &Command{
		Name: ss[0],
		Args: ss[1:],
	}
}

type Command struct {
	Name string
	Args []string
}

type scanner struct {
	src  []byte
	size int
	off  int
}

func newScanner(src []byte) *scanner {
	return &scanner{
		src:  src,
		size: len(src),
	}
}

func (s *scanner) next() (byte, bool) {
	if s.off >= s.size {
		return 0, true
	}

	ret := s.src[s.off]

	s.off++
	return ret, false
}

func (s *scanner) scan() (*token, error) {
	ch, eof := s.next()
	if eof {
		return nil, nil
	}
	switch {
	case isIdent(ch):
		var ret []byte
		for isIdent(ch) {
			ch, eof = s.next()
			if eof {
				break
			}
			ret = append(ret, ch)
		}
		return &token{tt: ident, value: ret}, nil
	case ch == '"':
		var ret []byte
		for ch != '"' {
			ch, eof = s.next()
			if eof {
				return nil, fmt.Errorf("unexpected eof in string literal at offset: %d", s.off)
			}
			ret = append(ret, ch)
		}
		return &token{tt: str, value: ret}, nil
	case isWhitespace(ch):
		return s.scan()
	}
	return nil, fmt.Errorf("unexpected character at offset: %d", s.off)
}

type scanError struct {
	msg string
	off int
}

func (s *scanError) Error() string {
	return fmt.Sprintf("%s: %d", s.msg, s.off)
}

func isWhitespace(b byte) bool {
	return b == ' '
}

func isIdent(b byte) bool {
	return 'A' <= b && b <= 'Z' || 'a' <= b && b <= 'z'
}

type tokenType int

type token struct {
	tt    tokenType
	value []byte
}

const (
	ident tokenType = iota
	str
)
<|endoftext|>


<commit_before>package functor

import (
	"errors"
	"testing"

	"github.com/arschles/assert"
)

func TestEitherIntOrErrRight(t *testing.T) {
	err := errors.New("testerr")
	right := EitherIntOrErrRight(err)
	assert.False(t, right.Left(), "Right was reported as a left")
	assert.True(t, right.Right(), "right was not reported as a right")
	leftProj := right.ToLeft()
	rightProj := right.ToRight()
	assert.True(t, leftProj.Empty(), "left projection not reported as empty")
	assert.False(t, rightProj.Empty(), "right projection reported as empty")
	assert.Equal(t, rightProj.Err(), err, "right projection error")
}
<commit_msg>mapping over the right projection of an either<commit_after>package functor

import (
	"errors"
	"fmt"
	"testing"

	"github.com/arschles/assert"
)

func TestEitherIntOrErrRight(t *testing.T) {
	err := errors.New("testerr")
	right := EitherIntOrErrRight(err)
	assert.False(t, right.Left(), "Right was reported as a left")
	assert.True(t, right.Right(), "right was not reported as a right")
	leftProj := right.ToLeft()
	rightProj := right.ToRight()
	assert.True(t, leftProj.Empty(), "left projection not reported as empty")
	assert.False(t, rightProj.Empty(), "right projection reported as empty")
	assert.Equal(t, rightProj.Err(), err, "right projection error")

	errFunc := func(err error) error {
		return fmt.Errorf("%s1", err.Error())
	}
	mapped := rightProj.Map(errFunc)
	assert.False(t, mapped.Empty(), "right mapped projection reported as empty")
	assert.Equal(t, mapped.Err(), errFunc(err), "returned error")
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package fuseutil

import (
	"github.com/jacobsa/fuse"
	"golang.org/x/net/context"
)

// Embed this within your file system type to inherit default implementations
// of all methods that return fuse.ENOSYS.
type NotImplementedFileSystem struct {
}

var _ fuse.FileSystem = &NotImplementedFileSystem{}

func (fs *NotImplementedFileSystem) Init(
	ctx context.Context,
	req *fuse.InitRequest) (*fuse.InitResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) LookUpInode(
	ctx context.Context,
	req *fuse.LookUpInodeRequest) (*fuse.LookUpInodeResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) GetInodeAttributes(
	ctx context.Context,
	req *fuse.GetInodeAttributesRequest) (
	*fuse.GetInodeAttributesResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) ForgetInode(
	ctx context.Context,
	req *fuse.ForgetInodeRequest) (*fuse.ForgetInodeResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) OpenDir(
	ctx context.Context,
	req *fuse.OpenDirRequest) (*fuse.OpenDirResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) ReadDir(
	ctx context.Context,
	req *fuse.ReadDirRequest) (*fuse.ReadDirResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) ReleaseDirHandle(
	ctx context.Context,
	req *fuse.ReleaseDirHandleRequest) (*fuse.ReleaseDirHandleResponse, error) {
	return nil, fuse.ENOSYS
}
<commit_msg>Added NotImplementedFileSystem support.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package fuseutil

import (
	"github.com/jacobsa/fuse"
	"golang.org/x/net/context"
)

// Embed this within your file system type to inherit default implementations
// of all methods that return fuse.ENOSYS.
type NotImplementedFileSystem struct {
}

var _ fuse.FileSystem = &NotImplementedFileSystem{}

func (fs *NotImplementedFileSystem) Init(
	ctx context.Context,
	req *fuse.InitRequest) (*fuse.InitResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) LookUpInode(
	ctx context.Context,
	req *fuse.LookUpInodeRequest) (*fuse.LookUpInodeResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) GetInodeAttributes(
	ctx context.Context,
	req *fuse.GetInodeAttributesRequest) (
	*fuse.GetInodeAttributesResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) ForgetInode(
	ctx context.Context,
	req *fuse.ForgetInodeRequest) (*fuse.ForgetInodeResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) OpenDir(
	ctx context.Context,
	req *fuse.OpenDirRequest) (*fuse.OpenDirResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) ReadDir(
	ctx context.Context,
	req *fuse.ReadDirRequest) (*fuse.ReadDirResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) ReleaseDirHandle(
	ctx context.Context,
	req *fuse.ReleaseDirHandleRequest) (*fuse.ReleaseDirHandleResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) OpenFile(
	ctx context.Context,
	req *fuse.OpenFileRequest) (*fuse.OpenFileResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) ReadFile(
	ctx context.Context,
	req *fuse.ReadFileRequest) (*fuse.ReadFileResponse, error) {
	return nil, fuse.ENOSYS
}

func (fs *NotImplementedFileSystem) ReleaseFileHandle(
	ctx context.Context,
	req *fuse.ReleaseFileHandleRequest) (*fuse.ReleaseFileHandleResponse, error) {
	return nil, fuse.ENOSYS
}
<|endoftext|>


<commit_before>package daemon

import (
	"path/filepath"
	"sync"

	"github.com/docker/docker/pkg/mount"
	"github.com/docker/docker/pkg/plugingetter"
	metrics "github.com/docker/go-metrics"
	"github.com/pkg/errors"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/sirupsen/logrus"
)

const metricsPluginType = "MetricsCollector"

var (
	containerActions          metrics.LabeledTimer
	imageActions              metrics.LabeledTimer
	networkActions            metrics.LabeledTimer
	engineInfo                metrics.LabeledGauge
	engineCpus                metrics.Gauge
	engineMemory              metrics.Gauge
	healthChecksCounter       metrics.Counter
	healthChecksFailedCounter metrics.Counter

	stateCtr *stateCounter
)

func init() {
	ns := metrics.NewNamespace("engine", "daemon", nil)
	containerActions = ns.NewLabeledTimer("container_actions", "The number of seconds it takes to process each container action", "action")
	for _, a := range []string{
		"start",
		"changes",
		"commit",
		"create",
		"delete",
	} {
		containerActions.WithValues(a).Update(0)
	}

	networkActions = ns.NewLabeledTimer("network_actions", "The number of seconds it takes to process each network action", "action")
	engineInfo = ns.NewLabeledGauge("engine", "The information related to the engine and the OS it is running on", metrics.Unit("info"),
		"version",
		"commit",
		"architecture",
		"graphdriver",
		"kernel", "os",
		"os_type",
		"daemon_id", // ID is a randomly generated unique identifier (e.g. UUID4)
	)
	engineCpus = ns.NewGauge("engine_cpus", "The number of cpus that the host system of the engine has", metrics.Unit("cpus"))
	engineMemory = ns.NewGauge("engine_memory", "The number of bytes of memory that the host system of the engine has", metrics.Bytes)
	healthChecksCounter = ns.NewCounter("health_checks", "The total number of health checks")
	healthChecksFailedCounter = ns.NewCounter("health_checks_failed", "The total number of failed health checks")
	imageActions = ns.NewLabeledTimer("image_actions", "The number of seconds it takes to process each image action", "action")

	stateCtr = newStateCounter(ns.NewDesc("container_states", "The count of containers in various states", metrics.Unit("containers"), "state"))
	ns.Add(stateCtr)

	metrics.Register(ns)
}

type stateCounter struct {
	mu     sync.Mutex
	states map[string]string
	desc   *prometheus.Desc
}

func newStateCounter(desc *prometheus.Desc) *stateCounter {
	return &stateCounter{
		states: make(map[string]string),
		desc:   desc,
	}
}

func (ctr *stateCounter) get() (running int, paused int, stopped int) {
	ctr.mu.Lock()
	defer ctr.mu.Unlock()

	states := map[string]int{
		"running": 0,
		"paused":  0,
		"stopped": 0,
	}
	for _, state := range ctr.states {
		states[state]++
	}
	return states["running"], states["paused"], states["stopped"]
}

func (ctr *stateCounter) set(id, label string) {
	ctr.mu.Lock()
	ctr.states[id] = label
	ctr.mu.Unlock()
}

func (ctr *stateCounter) del(id string) {
	ctr.mu.Lock()
	delete(ctr.states, id)
	ctr.mu.Unlock()
}

func (ctr *stateCounter) Describe(ch chan<- *prometheus.Desc) {
	ch <- ctr.desc
}

func (ctr *stateCounter) Collect(ch chan<- prometheus.Metric) {
	running, paused, stopped := ctr.get()
	ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(running), "running")
	ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(paused), "paused")
	ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(stopped), "stopped")
}

func (d *Daemon) cleanupMetricsPlugins() {
	ls := d.PluginStore.GetAllManagedPluginsByCap(metricsPluginType)
	var wg sync.WaitGroup
	wg.Add(len(ls))

	for _, p := range ls {
		go func() {
			defer wg.Done()
			pluginStopMetricsCollection(p)
		}()
	}
	wg.Wait()

	if d.metricsPluginListener != nil {
		d.metricsPluginListener.Close()
	}
}

type metricsPlugin struct {
	plugingetter.CompatPlugin
}

func (p metricsPlugin) sock() string {
	return "metrics.sock"
}

func (p metricsPlugin) sockBase() string {
	return filepath.Join(p.BasePath(), "run", "docker")
}

func pluginStartMetricsCollection(p plugingetter.CompatPlugin) error {
	type metricsPluginResponse struct {
		Err string
	}
	var res metricsPluginResponse
	if err := p.Client().Call(metricsPluginType+".StartMetrics", nil, &res); err != nil {
		return errors.Wrap(err, "could not start metrics plugin")
	}
	if res.Err != "" {
		return errors.New(res.Err)
	}
	return nil
}

func pluginStopMetricsCollection(p plugingetter.CompatPlugin) {
	if err := p.Client().Call(metricsPluginType+".StopMetrics", nil, nil); err != nil {
		logrus.WithError(err).WithField("name", p.Name()).Error("error stopping metrics collector")
	}

	mp := metricsPlugin{p}
	sockPath := filepath.Join(mp.sockBase(), mp.sock())
	if err := mount.Unmount(sockPath); err != nil {
		if mounted, _ := mount.Mounted(sockPath); mounted {
			logrus.WithError(err).WithField("name", p.Name()).WithField("socket", sockPath).Error("error unmounting metrics socket for plugin")
		}
	}
}
<commit_msg>daemon.cleanupMetricsPlugins(): fix<commit_after>package daemon

import (
	"path/filepath"
	"sync"

	"github.com/docker/docker/pkg/mount"
	"github.com/docker/docker/pkg/plugingetter"
	metrics "github.com/docker/go-metrics"
	"github.com/pkg/errors"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/sirupsen/logrus"
)

const metricsPluginType = "MetricsCollector"

var (
	containerActions          metrics.LabeledTimer
	imageActions              metrics.LabeledTimer
	networkActions            metrics.LabeledTimer
	engineInfo                metrics.LabeledGauge
	engineCpus                metrics.Gauge
	engineMemory              metrics.Gauge
	healthChecksCounter       metrics.Counter
	healthChecksFailedCounter metrics.Counter

	stateCtr *stateCounter
)

func init() {
	ns := metrics.NewNamespace("engine", "daemon", nil)
	containerActions = ns.NewLabeledTimer("container_actions", "The number of seconds it takes to process each container action", "action")
	for _, a := range []string{
		"start",
		"changes",
		"commit",
		"create",
		"delete",
	} {
		containerActions.WithValues(a).Update(0)
	}

	networkActions = ns.NewLabeledTimer("network_actions", "The number of seconds it takes to process each network action", "action")
	engineInfo = ns.NewLabeledGauge("engine", "The information related to the engine and the OS it is running on", metrics.Unit("info"),
		"version",
		"commit",
		"architecture",
		"graphdriver",
		"kernel", "os",
		"os_type",
		"daemon_id", // ID is a randomly generated unique identifier (e.g. UUID4)
	)
	engineCpus = ns.NewGauge("engine_cpus", "The number of cpus that the host system of the engine has", metrics.Unit("cpus"))
	engineMemory = ns.NewGauge("engine_memory", "The number of bytes of memory that the host system of the engine has", metrics.Bytes)
	healthChecksCounter = ns.NewCounter("health_checks", "The total number of health checks")
	healthChecksFailedCounter = ns.NewCounter("health_checks_failed", "The total number of failed health checks")
	imageActions = ns.NewLabeledTimer("image_actions", "The number of seconds it takes to process each image action", "action")

	stateCtr = newStateCounter(ns.NewDesc("container_states", "The count of containers in various states", metrics.Unit("containers"), "state"))
	ns.Add(stateCtr)

	metrics.Register(ns)
}

type stateCounter struct {
	mu     sync.Mutex
	states map[string]string
	desc   *prometheus.Desc
}

func newStateCounter(desc *prometheus.Desc) *stateCounter {
	return &stateCounter{
		states: make(map[string]string),
		desc:   desc,
	}
}

func (ctr *stateCounter) get() (running int, paused int, stopped int) {
	ctr.mu.Lock()
	defer ctr.mu.Unlock()

	states := map[string]int{
		"running": 0,
		"paused":  0,
		"stopped": 0,
	}
	for _, state := range ctr.states {
		states[state]++
	}
	return states["running"], states["paused"], states["stopped"]
}

func (ctr *stateCounter) set(id, label string) {
	ctr.mu.Lock()
	ctr.states[id] = label
	ctr.mu.Unlock()
}

func (ctr *stateCounter) del(id string) {
	ctr.mu.Lock()
	delete(ctr.states, id)
	ctr.mu.Unlock()
}

func (ctr *stateCounter) Describe(ch chan<- *prometheus.Desc) {
	ch <- ctr.desc
}

func (ctr *stateCounter) Collect(ch chan<- prometheus.Metric) {
	running, paused, stopped := ctr.get()
	ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(running), "running")
	ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(paused), "paused")
	ch <- prometheus.MustNewConstMetric(ctr.desc, prometheus.GaugeValue, float64(stopped), "stopped")
}

func (d *Daemon) cleanupMetricsPlugins() {
	ls := d.PluginStore.GetAllManagedPluginsByCap(metricsPluginType)
	var wg sync.WaitGroup
	wg.Add(len(ls))

	for _, plugin := range ls {
		p := plugin
		go func() {
			defer wg.Done()
			pluginStopMetricsCollection(p)
		}()
	}
	wg.Wait()

	if d.metricsPluginListener != nil {
		d.metricsPluginListener.Close()
	}
}

type metricsPlugin struct {
	plugingetter.CompatPlugin
}

func (p metricsPlugin) sock() string {
	return "metrics.sock"
}

func (p metricsPlugin) sockBase() string {
	return filepath.Join(p.BasePath(), "run", "docker")
}

func pluginStartMetricsCollection(p plugingetter.CompatPlugin) error {
	type metricsPluginResponse struct {
		Err string
	}
	var res metricsPluginResponse
	if err := p.Client().Call(metricsPluginType+".StartMetrics", nil, &res); err != nil {
		return errors.Wrap(err, "could not start metrics plugin")
	}
	if res.Err != "" {
		return errors.New(res.Err)
	}
	return nil
}

func pluginStopMetricsCollection(p plugingetter.CompatPlugin) {
	if err := p.Client().Call(metricsPluginType+".StopMetrics", nil, nil); err != nil {
		logrus.WithError(err).WithField("name", p.Name()).Error("error stopping metrics collector")
	}

	mp := metricsPlugin{p}
	sockPath := filepath.Join(mp.sockBase(), mp.sock())
	if err := mount.Unmount(sockPath); err != nil {
		if mounted, _ := mount.Mounted(sockPath); mounted {
			logrus.WithError(err).WithField("name", p.Name()).WithField("socket", sockPath).Error("error unmounting metrics socket for plugin")
		}
	}
}
<|endoftext|>


<commit_before>package daemon

import (
	"fmt"
	"net"
	"strings"

	"github.com/Sirupsen/logrus"
	clustertypes "github.com/docker/docker/daemon/cluster/provider"
	"github.com/docker/docker/errors"
	"github.com/docker/docker/runconfig"
	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/network"
	"github.com/docker/libnetwork"
	networktypes "github.com/docker/libnetwork/types"
)

// NetworkControllerEnabled checks if the networking stack is enabled.
// This feature depends on OS primitives and it's disabled in systems like Windows.
func (daemon *Daemon) NetworkControllerEnabled() bool {
	return daemon.netController != nil
}

// FindNetwork function finds a network for a given string that can represent network name or id
func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) {
	// Find by Name
	n, err := daemon.GetNetworkByName(idName)
	if err != nil && !isNoSuchNetworkError(err) {
		return nil, err
	}

	if n != nil {
		return n, nil
	}

	// Find by id
	return daemon.GetNetworkByID(idName)
}

func isNoSuchNetworkError(err error) bool {
	_, ok := err.(libnetwork.ErrNoSuchNetwork)
	return ok
}

// GetNetworkByID function returns a network whose ID begins with the given prefix.
// It fails with an error if no matching, or more than one matching, networks are found.
func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, error) {
	list := daemon.GetNetworksByID(partialID)

	if len(list) == 0 {
		return nil, libnetwork.ErrNoSuchNetwork(partialID)
	}
	if len(list) > 1 {
		return nil, libnetwork.ErrInvalidID(partialID)
	}
	return list[0], nil
}

// GetNetworkByName function returns a network for a given network name.
func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
	c := daemon.netController
	if c == nil {
		return nil, libnetwork.ErrNoSuchNetwork(name)
	}
	if name == "" {
		name = c.Config().Daemon.DefaultNetwork
	}
	return c.NetworkByName(name)
}

// GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
	c := daemon.netController
	if c == nil {
		return nil
	}
	list := []libnetwork.Network{}
	l := func(nw libnetwork.Network) bool {
		if strings.HasPrefix(nw.ID(), partialID) {
			list = append(list, nw)
		}
		return false
	}
	c.WalkNetworks(l)

	return list
}

// getAllNetworks returns a list containing all networks
func (daemon *Daemon) getAllNetworks() []libnetwork.Network {
	c := daemon.netController
	list := []libnetwork.Network{}
	l := func(nw libnetwork.Network) bool {
		list = append(list, nw)
		return false
	}
	c.WalkNetworks(l)

	return list
}

func isIngressNetwork(name string) bool {
	return name == "ingress"
}

var ingressChan = make(chan struct{}, 1)

func ingressWait() func() {
	ingressChan <- struct{}{}
	return func() { <-ingressChan }
}

// SetupIngress setups ingress networking.
func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) error {
	ip, _, err := net.ParseCIDR(nodeIP)
	if err != nil {
		return err
	}

	go func() {
		controller := daemon.netController
		controller.AgentInitWait()

		if n, err := daemon.GetNetworkByName(create.Name); err == nil && n != nil && n.ID() != create.ID {
			if err := controller.SandboxDestroy("ingress-sbox"); err != nil {
				logrus.Errorf("Failed to delete stale ingress sandbox: %v", err)
				return
			}

			// Cleanup any stale endpoints that might be left over during previous iterations
			epList := n.Endpoints()
			for _, ep := range epList {
				if err := ep.Delete(true); err != nil {
					logrus.Errorf("Failed to delete endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
				}
			}

			if err := n.Delete(); err != nil {
				logrus.Errorf("Failed to delete stale ingress network %s: %v", n.ID(), err)
				return
			}
		}

		if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil {
			// If it is any other error other than already
			// exists error log error and return.
			if _, ok := err.(libnetwork.NetworkNameError); !ok {
				logrus.Errorf("Failed creating ingress network: %v", err)
				return
			}

			// Otherwise continue down the call to create or recreate sandbox.
		}

		n, err := daemon.GetNetworkByID(create.ID)
		if err != nil {
			logrus.Errorf("Failed getting ingress network by id after creating: %v", err)
			return
		}

		sb, err := controller.NewSandbox("ingress-sbox", libnetwork.OptionIngress())
		if err != nil {
			logrus.Errorf("Failed creating ingress sandbox: %v", err)
			return
		}

		ep, err := n.CreateEndpoint("ingress-endpoint", libnetwork.CreateOptionIpam(ip, nil, nil, nil))
		if err != nil {
			logrus.Errorf("Failed creating ingress endpoint: %v", err)
			return
		}

		if err := ep.Join(sb, nil); err != nil {
			logrus.Errorf("Failed joining ingress sandbox to ingress endpoint: %v", err)
		}
	}()

	return nil
}

// SetNetworkBootstrapKeys sets the bootstrap keys.
func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error {
	return daemon.netController.SetKeys(keys)
}

// CreateManagedNetwork creates an agent network.
func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error {
	_, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true)
	return err
}

// CreateNetwork creates a network with the given name, driver and other optional parameters
func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) {
	resp, err := daemon.createNetwork(create, "", false)
	if err != nil {
		return nil, err
	}
	return resp, err
}

func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
	// If there is a pending ingress network creation wait here
	// since ingress network creation can happen via node download
	// from manager or task download.
	if isIngressNetwork(create.Name) {
		defer ingressWait()()
	}

	if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
		err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
		return nil, errors.NewRequestForbiddenError(err)
	}

	var warning string
	nw, err := daemon.GetNetworkByName(create.Name)
	if err != nil {
		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
			return nil, err
		}
	}
	if nw != nil {
		if create.CheckDuplicate {
			return nil, libnetwork.NetworkNameError(create.Name)
		}
		warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
	}

	c := daemon.netController
	driver := create.Driver
	if driver == "" {
		driver = c.Config().Daemon.DefaultDriver
	}

	ipam := create.IPAM
	v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
	if err != nil {
		return nil, err
	}

	nwOptions := []libnetwork.NetworkOption{
		libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options),
		libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
		libnetwork.NetworkOptionDriverOpts(create.Options),
		libnetwork.NetworkOptionLabels(create.Labels),
	}
	if create.Internal {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
	}
	if agent {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic())
		nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false))
	}

	if isIngressNetwork(create.Name) {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionIngress())
	}

	n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)
	if err != nil {
		return nil, err
	}

	daemon.LogNetworkEvent(n, "create")
	return &types.NetworkCreateResponse{
		ID:      n.ID(),
		Warning: warning,
	}, nil
}

func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
	ipamV4Cfg := []*libnetwork.IpamConf{}
	ipamV6Cfg := []*libnetwork.IpamConf{}
	for _, d := range data {
		iCfg := libnetwork.IpamConf{}
		iCfg.PreferredPool = d.Subnet
		iCfg.SubPool = d.IPRange
		iCfg.Gateway = d.Gateway
		iCfg.AuxAddresses = d.AuxAddress
		ip, _, err := net.ParseCIDR(d.Subnet)
		if err != nil {
			return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err)
		}
		if ip.To4() != nil {
			ipamV4Cfg = append(ipamV4Cfg, &iCfg)
		} else {
			ipamV6Cfg = append(ipamV6Cfg, &iCfg)
		}
	}
	return ipamV4Cfg, ipamV6Cfg, nil
}

// UpdateContainerServiceConfig updates a service configuration.
func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		return err
	}

	container.NetworkSettings.Service = serviceConfig
	return nil
}

// ConnectContainerToNetwork connects the given container to the given
// network. If either cannot be found, an err is returned. If the
// network cannot be set up, an err is returned.
func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		return err
	}
	return daemon.ConnectToNetwork(container, networkName, endpointConfig)
}

// DisconnectContainerFromNetwork disconnects the given container from
// the given network. If either cannot be found, an err is returned.
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		if force {
			return daemon.ForceEndpointDelete(containerName, network)
		}
		return err
	}
	return daemon.DisconnectFromNetwork(container, network, force)
}

// GetNetworkDriverList returns the list of plugins drivers
// registered for network.
func (daemon *Daemon) GetNetworkDriverList() map[string]bool {
	pluginList := make(map[string]bool)

	if !daemon.NetworkControllerEnabled() {
		return nil
	}
	c := daemon.netController
	networks := c.Networks()

	for _, network := range networks {
		driver := network.Type()
		pluginList[driver] = true
	}
	// TODO : Replace this with proper libnetwork API
	pluginList["overlay"] = true

	return pluginList
}

// DeleteManagedNetwork deletes an agent network.
func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
	return daemon.deleteNetwork(networkID, true)
}

// DeleteNetwork destroys a network unless it's one of docker's predefined networks.
func (daemon *Daemon) DeleteNetwork(networkID string) error {
	return daemon.deleteNetwork(networkID, false)
}

func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
	nw, err := daemon.FindNetwork(networkID)
	if err != nil {
		return err
	}

	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
		return errors.NewRequestForbiddenError(err)
	}

	if err := nw.Delete(); err != nil {
		return err
	}
	daemon.LogNetworkEvent(nw, "destroy")
	return nil
}

// GetNetworks returns a list of all networks
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
	return daemon.getAllNetworks()
}
<commit_msg>Handle ingress sbox creation gracefully<commit_after>package daemon

import (
	"fmt"
	"net"
	"strings"

	"github.com/Sirupsen/logrus"
	clustertypes "github.com/docker/docker/daemon/cluster/provider"
	"github.com/docker/docker/errors"
	"github.com/docker/docker/runconfig"
	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/network"
	"github.com/docker/libnetwork"
	networktypes "github.com/docker/libnetwork/types"
)

// NetworkControllerEnabled checks if the networking stack is enabled.
// This feature depends on OS primitives and it's disabled in systems like Windows.
func (daemon *Daemon) NetworkControllerEnabled() bool {
	return daemon.netController != nil
}

// FindNetwork function finds a network for a given string that can represent network name or id
func (daemon *Daemon) FindNetwork(idName string) (libnetwork.Network, error) {
	// Find by Name
	n, err := daemon.GetNetworkByName(idName)
	if err != nil && !isNoSuchNetworkError(err) {
		return nil, err
	}

	if n != nil {
		return n, nil
	}

	// Find by id
	return daemon.GetNetworkByID(idName)
}

func isNoSuchNetworkError(err error) bool {
	_, ok := err.(libnetwork.ErrNoSuchNetwork)
	return ok
}

// GetNetworkByID function returns a network whose ID begins with the given prefix.
// It fails with an error if no matching, or more than one matching, networks are found.
func (daemon *Daemon) GetNetworkByID(partialID string) (libnetwork.Network, error) {
	list := daemon.GetNetworksByID(partialID)

	if len(list) == 0 {
		return nil, libnetwork.ErrNoSuchNetwork(partialID)
	}
	if len(list) > 1 {
		return nil, libnetwork.ErrInvalidID(partialID)
	}
	return list[0], nil
}

// GetNetworkByName function returns a network for a given network name.
func (daemon *Daemon) GetNetworkByName(name string) (libnetwork.Network, error) {
	c := daemon.netController
	if c == nil {
		return nil, libnetwork.ErrNoSuchNetwork(name)
	}
	if name == "" {
		name = c.Config().Daemon.DefaultNetwork
	}
	return c.NetworkByName(name)
}

// GetNetworksByID returns a list of networks whose ID partially matches zero or more networks
func (daemon *Daemon) GetNetworksByID(partialID string) []libnetwork.Network {
	c := daemon.netController
	if c == nil {
		return nil
	}
	list := []libnetwork.Network{}
	l := func(nw libnetwork.Network) bool {
		if strings.HasPrefix(nw.ID(), partialID) {
			list = append(list, nw)
		}
		return false
	}
	c.WalkNetworks(l)

	return list
}

// getAllNetworks returns a list containing all networks
func (daemon *Daemon) getAllNetworks() []libnetwork.Network {
	c := daemon.netController
	list := []libnetwork.Network{}
	l := func(nw libnetwork.Network) bool {
		list = append(list, nw)
		return false
	}
	c.WalkNetworks(l)

	return list
}

func isIngressNetwork(name string) bool {
	return name == "ingress"
}

var ingressChan = make(chan struct{}, 1)

func ingressWait() func() {
	ingressChan <- struct{}{}
	return func() { <-ingressChan }
}

// SetupIngress setups ingress networking.
func (daemon *Daemon) SetupIngress(create clustertypes.NetworkCreateRequest, nodeIP string) error {
	ip, _, err := net.ParseCIDR(nodeIP)
	if err != nil {
		return err
	}

	go func() {
		controller := daemon.netController
		controller.AgentInitWait()

		if n, err := daemon.GetNetworkByName(create.Name); err == nil && n != nil && n.ID() != create.ID {
			if err := controller.SandboxDestroy("ingress-sbox"); err != nil {
				logrus.Errorf("Failed to delete stale ingress sandbox: %v", err)
				return
			}

			// Cleanup any stale endpoints that might be left over during previous iterations
			epList := n.Endpoints()
			for _, ep := range epList {
				if err := ep.Delete(true); err != nil {
					logrus.Errorf("Failed to delete endpoint %s (%s): %v", ep.Name(), ep.ID(), err)
				}
			}

			if err := n.Delete(); err != nil {
				logrus.Errorf("Failed to delete stale ingress network %s: %v", n.ID(), err)
				return
			}
		}

		if _, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true); err != nil {
			// If it is any other error other than already
			// exists error log error and return.
			if _, ok := err.(libnetwork.NetworkNameError); !ok {
				logrus.Errorf("Failed creating ingress network: %v", err)
				return
			}

			// Otherwise continue down the call to create or recreate sandbox.
		}

		n, err := daemon.GetNetworkByID(create.ID)
		if err != nil {
			logrus.Errorf("Failed getting ingress network by id after creating: %v", err)
			return
		}

		sb, err := controller.NewSandbox("ingress-sbox", libnetwork.OptionIngress())
		if err != nil {
			if _, ok := err.(networktypes.ForbiddenError); !ok {
				logrus.Errorf("Failed creating ingress sandbox: %v", err)
			}
			return
		}

		ep, err := n.CreateEndpoint("ingress-endpoint", libnetwork.CreateOptionIpam(ip, nil, nil, nil))
		if err != nil {
			logrus.Errorf("Failed creating ingress endpoint: %v", err)
			return
		}

		if err := ep.Join(sb, nil); err != nil {
			logrus.Errorf("Failed joining ingress sandbox to ingress endpoint: %v", err)
		}
	}()

	return nil
}

// SetNetworkBootstrapKeys sets the bootstrap keys.
func (daemon *Daemon) SetNetworkBootstrapKeys(keys []*networktypes.EncryptionKey) error {
	return daemon.netController.SetKeys(keys)
}

// CreateManagedNetwork creates an agent network.
func (daemon *Daemon) CreateManagedNetwork(create clustertypes.NetworkCreateRequest) error {
	_, err := daemon.createNetwork(create.NetworkCreateRequest, create.ID, true)
	return err
}

// CreateNetwork creates a network with the given name, driver and other optional parameters
func (daemon *Daemon) CreateNetwork(create types.NetworkCreateRequest) (*types.NetworkCreateResponse, error) {
	resp, err := daemon.createNetwork(create, "", false)
	if err != nil {
		return nil, err
	}
	return resp, err
}

func (daemon *Daemon) createNetwork(create types.NetworkCreateRequest, id string, agent bool) (*types.NetworkCreateResponse, error) {
	// If there is a pending ingress network creation wait here
	// since ingress network creation can happen via node download
	// from manager or task download.
	if isIngressNetwork(create.Name) {
		defer ingressWait()()
	}

	if runconfig.IsPreDefinedNetwork(create.Name) && !agent {
		err := fmt.Errorf("%s is a pre-defined network and cannot be created", create.Name)
		return nil, errors.NewRequestForbiddenError(err)
	}

	var warning string
	nw, err := daemon.GetNetworkByName(create.Name)
	if err != nil {
		if _, ok := err.(libnetwork.ErrNoSuchNetwork); !ok {
			return nil, err
		}
	}
	if nw != nil {
		if create.CheckDuplicate {
			return nil, libnetwork.NetworkNameError(create.Name)
		}
		warning = fmt.Sprintf("Network with name %s (id : %s) already exists", nw.Name(), nw.ID())
	}

	c := daemon.netController
	driver := create.Driver
	if driver == "" {
		driver = c.Config().Daemon.DefaultDriver
	}

	ipam := create.IPAM
	v4Conf, v6Conf, err := getIpamConfig(ipam.Config)
	if err != nil {
		return nil, err
	}

	nwOptions := []libnetwork.NetworkOption{
		libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf, ipam.Options),
		libnetwork.NetworkOptionEnableIPv6(create.EnableIPv6),
		libnetwork.NetworkOptionDriverOpts(create.Options),
		libnetwork.NetworkOptionLabels(create.Labels),
	}
	if create.Internal {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionInternalNetwork())
	}
	if agent {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionDynamic())
		nwOptions = append(nwOptions, libnetwork.NetworkOptionPersist(false))
	}

	if isIngressNetwork(create.Name) {
		nwOptions = append(nwOptions, libnetwork.NetworkOptionIngress())
	}

	n, err := c.NewNetwork(driver, create.Name, id, nwOptions...)
	if err != nil {
		return nil, err
	}

	daemon.LogNetworkEvent(n, "create")
	return &types.NetworkCreateResponse{
		ID:      n.ID(),
		Warning: warning,
	}, nil
}

func getIpamConfig(data []network.IPAMConfig) ([]*libnetwork.IpamConf, []*libnetwork.IpamConf, error) {
	ipamV4Cfg := []*libnetwork.IpamConf{}
	ipamV6Cfg := []*libnetwork.IpamConf{}
	for _, d := range data {
		iCfg := libnetwork.IpamConf{}
		iCfg.PreferredPool = d.Subnet
		iCfg.SubPool = d.IPRange
		iCfg.Gateway = d.Gateway
		iCfg.AuxAddresses = d.AuxAddress
		ip, _, err := net.ParseCIDR(d.Subnet)
		if err != nil {
			return nil, nil, fmt.Errorf("Invalid subnet %s : %v", d.Subnet, err)
		}
		if ip.To4() != nil {
			ipamV4Cfg = append(ipamV4Cfg, &iCfg)
		} else {
			ipamV6Cfg = append(ipamV6Cfg, &iCfg)
		}
	}
	return ipamV4Cfg, ipamV6Cfg, nil
}

// UpdateContainerServiceConfig updates a service configuration.
func (daemon *Daemon) UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		return err
	}

	container.NetworkSettings.Service = serviceConfig
	return nil
}

// ConnectContainerToNetwork connects the given container to the given
// network. If either cannot be found, an err is returned. If the
// network cannot be set up, an err is returned.
func (daemon *Daemon) ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		return err
	}
	return daemon.ConnectToNetwork(container, networkName, endpointConfig)
}

// DisconnectContainerFromNetwork disconnects the given container from
// the given network. If either cannot be found, an err is returned.
func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, network libnetwork.Network, force bool) error {
	container, err := daemon.GetContainer(containerName)
	if err != nil {
		if force {
			return daemon.ForceEndpointDelete(containerName, network)
		}
		return err
	}
	return daemon.DisconnectFromNetwork(container, network, force)
}

// GetNetworkDriverList returns the list of plugins drivers
// registered for network.
func (daemon *Daemon) GetNetworkDriverList() map[string]bool {
	pluginList := make(map[string]bool)

	if !daemon.NetworkControllerEnabled() {
		return nil
	}
	c := daemon.netController
	networks := c.Networks()

	for _, network := range networks {
		driver := network.Type()
		pluginList[driver] = true
	}
	// TODO : Replace this with proper libnetwork API
	pluginList["overlay"] = true

	return pluginList
}

// DeleteManagedNetwork deletes an agent network.
func (daemon *Daemon) DeleteManagedNetwork(networkID string) error {
	return daemon.deleteNetwork(networkID, true)
}

// DeleteNetwork destroys a network unless it's one of docker's predefined networks.
func (daemon *Daemon) DeleteNetwork(networkID string) error {
	return daemon.deleteNetwork(networkID, false)
}

func (daemon *Daemon) deleteNetwork(networkID string, dynamic bool) error {
	nw, err := daemon.FindNetwork(networkID)
	if err != nil {
		return err
	}

	if runconfig.IsPreDefinedNetwork(nw.Name()) && !dynamic {
		err := fmt.Errorf("%s is a pre-defined network and cannot be removed", nw.Name())
		return errors.NewRequestForbiddenError(err)
	}

	if err := nw.Delete(); err != nil {
		return err
	}
	daemon.LogNetworkEvent(nw, "destroy")
	return nil
}

// GetNetworks returns a list of all networks
func (daemon *Daemon) GetNetworks() []libnetwork.Network {
	return daemon.getAllNetworks()
}
<|endoftext|>


<commit_before>// +build !pro

package crane

import (
	"fmt"
)

func printVersion() {
	fmt.Println("v3.2.0")
}
<commit_msg>Adjust basic version info<commit_after>// +build !pro

package crane

import (
	"fmt"
)

func printVersion() {
	fmt.Println("v3.2.1")
}
<|endoftext|>


<commit_before>package trees

import (
	"io"
	"sync"

	"github.com/joushou/qp"
)

var (
	globalIDLock sync.Mutex
	globalID     uint64 = 0
)

func nextID() uint64 {
	globalIDLock.Lock()
	defer globalIDLock.Unlock()
	id := globalID
	globalID++
	return id
}

type File interface {
	Name() (string, error)

	Open(user string, mode qp.OpenMode) (ReadWriteSeekCloser, error)

	Qid() (qp.Qid, error)
	Stat() (qp.Stat, error)
	WriteStat(qp.Stat) error

	IsDir() (bool, error)
	CanRemove() (bool, error)
}

type Dir interface {
	File

	Walk(user, name string) (File, error)
	Create(user, name string, perms qp.FileMode) (File, error)
	Remove(user, name string) error
	Rename(user, oldname, newname string) error
}

type ReadWriteSeekCloser interface {
	io.Reader
	io.Writer
	io.Seeker
	io.Closer
}

type Lister interface {
	List(user string) ([]qp.Stat, error)
}

type AccessLogger interface {
	Accessed()
	Modified()
	Closed()
}

func permCheck(owner bool, permissions qp.FileMode, mode qp.OpenMode) bool {
	var offset uint8
	if owner {
		offset = 6
	}

	switch mode & 3 {
	case qp.OREAD:
		return permissions&(1<<(2+offset)) != 0
	case qp.OWRITE:
		return permissions&(1<<(1+offset)) != 0
	case qp.ORDWR:
		return (permissions&(1<<(2+offset)) != 0) && (permissions&(1<<(1+offset)) != 0)
	case qp.OEXEC:
		return permissions&(1<<offset) != 0
	default:
		return false
	}
}
<commit_msg>Add a few comments<commit_after>package trees

import (
	"io"
	"sync"

	"github.com/joushou/qp"
)

var (
	globalIDLock sync.Mutex
	globalID     uint64 = 0
)

func nextID() uint64 {
	globalIDLock.Lock()
	defer globalIDLock.Unlock()
	id := globalID
	globalID++
	return id
}

// File is a node in the tree abstraction.
type File interface {
	// Name returns the name of the file.
	Name() (string, error)

	// Open returns a handle to the file in form of a ReadWriteSeekCloser in
	// the mode requested if the user is permitted to do so.
	Open(user string, mode qp.OpenMode) (ReadWriteSeekCloser, error)

	// QId returns the qid of the file.
	Qid() (qp.Qid, error)

	// Stat returns the stat structure of the file.
	Stat() (qp.Stat, error)

	// WriteStat changes the stat structure of the file.
	WriteStat(qp.Stat) error

	// IsDir returns whether or not the file is a directory.
	IsDir() (bool, error)

	// CanRemove returns if the file can be removed.
	CanRemove() (bool, error)
}

// Dir is a file that also sports directory features. Directory detection must
// not occur by asserting Dir, but should be done by using IsDir.
type Dir interface {
	File

	// Walk finds a file by name "file" and returns it if it exists and the
	// user is allowed to execute the directory. The name is the name of the
	// file, without any "/" in it.
	Walk(user, name string) (File, error)

	// Create creats a file of a default type defined by teh directory
	// implementation itself, with the permissions required and returns it if
	// the file does not already exist and the user is permitted to do so.
	Create(user, name string, perms qp.FileMode) (File, error)

	// Remove removes the file if it exists and the user is permitted to do so.
	Remove(user, name string) error

	// Rename renames the file in the local directory if the old name exists,
	// the new name does not already exist, and the user is permitted to do so.
	Rename(user, oldname, newname string) error
}

// ReadWriteSeekCloser is an interface that allows reading, writing, seeking
// and closing.
type ReadWriteSeekCloser interface {
	io.Reader
	io.Writer
	io.Seeker
	io.Closer
}

// Lister allows for ListHandle to read the directory entries, so that a
// directory does not have to implement reading.
type Lister interface {
	List(user string) ([]qp.Stat, error)
}

// AccessLogger defines a file that can log access
type AccessLogger interface {
	// Accessed logs access.
	Accessed()

	// Modified logs modification.
	Modified()

	// Closed logs closure.
	Closed()
}

func permCheck(owner bool, permissions qp.FileMode, mode qp.OpenMode) bool {
	var offset uint8
	if owner {
		offset = 6
	}

	switch mode & 3 {
	case qp.OREAD:
		return permissions&(1<<(2+offset)) != 0
	case qp.OWRITE:
		return permissions&(1<<(1+offset)) != 0
	case qp.ORDWR:
		return (permissions&(1<<(2+offset)) != 0) && (permissions&(1<<(1+offset)) != 0)
	case qp.OEXEC:
		return permissions&(1<<offset) != 0
	default:
		return false
	}
}
<|endoftext|>


<commit_before>package sudoku

import (
	"fmt"
)

type SolveDirections []*SolveStep

const (
	ONLY_LEGAL_NUMBER = iota
)

type SolveStep struct {
	Row       int
	Col       int
	Num       int
	Technique SolveTechnique
}

type SolveTechnique interface {
	Name() string
	Description(*SolveStep) string
	Apply(*Grid) *SolveStep
}

var techniques []SolveTechnique

func init() {
	//TODO: init techniques with enough space
	techniques = append(techniques, onlyLegalNumberTechnique{})
	techniques = append(techniques, necessaryInRowTechnique{})
}

type onlyLegalNumberTechnique struct {
}

type necessaryInRowTechnique struct {
}

func (self onlyLegalNumberTechnique) Name() string {
	return "Only Legal Number"
}

func (self onlyLegalNumberTechnique) Description(step *SolveStep) string {
	return fmt.Sprintf("%d is the only remaining valid number for that cell", step.Num)
}

func (self onlyLegalNumberTechnique) Apply(grid *Grid) *SolveStep {
	//This will be a random item
	obj := grid.queue.NewGetter().GetSmallerThan(2)
	if obj == nil {
		//There weren't any cells with one option.
		return nil
	}
	cell := obj.(*Cell)

	cell.SetNumber(cell.implicitNumber())
	return &SolveStep{cell.Row, cell.Col, cell.Number(), self}
}

func (self necessaryInRowTechnique) Name() string {
	return "Necessary In Row"
}

func (self necessaryInRowTechnique) Description(step *SolveStep) string {
	//TODO: format the text to say "first/second/third/etc"
	return fmt.Sprintf("%d is required in the %d row, and %d is the only column it fits", step.Num, step.Row+1, step.Col+1)
}

func (self necessaryInRowTechnique) Apply(grid *Grid) *SolveStep {
	//TODO: test this.
	//This will be a random item
	//TODO: iterate through rows in a random order.
	for r := 0; r < DIM; r++ {
		seenInRow := make([]int, DIM)
		row := grid.Row(r)
		for _, cell := range row {
			for _, possibility := range cell.Possibilities() {
				seenInRow[possibility]++
			}
		}
		//TODO: iterate through this in a random order.
		for i, seen := range seenInRow {
			if seen == 1 {
				//Okay, we know our target number. Which cell was it?
				for _, cell := range row {
					if cell.Possible(i) {
						//Found it!
						cell.SetNumber(i)
						return &SolveStep{cell.Row, cell.Col, cell.Number(), self}
					}
				}
			}
		}
	}
	//Nope.
	return nil
}

func (self *Grid) HumanSolve() *SolveDirections {
	return nil
}
<commit_msg>TESTS FAIL. Fixed a panic, some tests still fail.<commit_after>package sudoku

import (
	"fmt"
)

type SolveDirections []*SolveStep

const (
	ONLY_LEGAL_NUMBER = iota
)

type SolveStep struct {
	Row       int
	Col       int
	Num       int
	Technique SolveTechnique
}

type SolveTechnique interface {
	Name() string
	Description(*SolveStep) string
	Apply(*Grid) *SolveStep
}

var techniques []SolveTechnique

func init() {
	//TODO: init techniques with enough space
	techniques = append(techniques, onlyLegalNumberTechnique{})
	techniques = append(techniques, necessaryInRowTechnique{})
}

type onlyLegalNumberTechnique struct {
}

type necessaryInRowTechnique struct {
}

func (self onlyLegalNumberTechnique) Name() string {
	return "Only Legal Number"
}

func (self onlyLegalNumberTechnique) Description(step *SolveStep) string {
	return fmt.Sprintf("%d is the only remaining valid number for that cell", step.Num)
}

func (self onlyLegalNumberTechnique) Apply(grid *Grid) *SolveStep {
	//This will be a random item
	obj := grid.queue.NewGetter().GetSmallerThan(2)
	if obj == nil {
		//There weren't any cells with one option.
		return nil
	}
	cell := obj.(*Cell)

	cell.SetNumber(cell.implicitNumber())
	return &SolveStep{cell.Row, cell.Col, cell.Number(), self}
}

func (self necessaryInRowTechnique) Name() string {
	return "Necessary In Row"
}

func (self necessaryInRowTechnique) Description(step *SolveStep) string {
	//TODO: format the text to say "first/second/third/etc"
	return fmt.Sprintf("%d is required in the %d row, and %d is the only column it fits", step.Num, step.Row+1, step.Col+1)
}

func (self necessaryInRowTechnique) Apply(grid *Grid) *SolveStep {
	//TODO: test this.
	//This will be a random item
	//TODO: iterate through rows in a random order.
	for r := 0; r < DIM; r++ {
		seenInRow := make([]int, DIM)
		row := grid.Row(r)
		for _, cell := range row {
			for _, possibility := range cell.Possibilities() {
				seenInRow[possibility-1]++
			}
		}
		//TODO: iterate through this in a random order.
		for i, seen := range seenInRow {
			if seen == 1 {
				//Okay, we know our target number. Which cell was it?
				for _, cell := range row {
					if cell.Possible(i + 1) {
						//Found it!
						cell.SetNumber(i + 1)
						return &SolveStep{cell.Row, cell.Col, cell.Number(), self}
					}
				}
			}
		}
	}
	//Nope.
	return nil
}

func (self *Grid) HumanSolve() *SolveDirections {
	return nil
}
<|endoftext|>


<commit_before>package sudoku

import (
	"fmt"
	"math/rand"
)

type SolveDirections []*SolveStep

const (
	ONLY_LEGAL_NUMBER = iota
	NECESSARY_IN_ROW
	NECESSARY_IN_COL
	NECESSARY_IN_BLOCK
)

type SolveStep struct {
	Row       int
	Col       int
	Block     int
	Num       int
	Technique SolveTechnique
}

type SolveTechnique interface {
	Name() string
	Description(*SolveStep) string
	Find(*Grid) *SolveStep
}

var techniques []SolveTechnique

func init() {
	//TODO: init techniques with enough space
	techniques = append(techniques, onlyLegalNumberTechnique{})
	techniques = append(techniques, necessaryInRowTechnique{})
	techniques = append(techniques, necessaryInColTechnique{})
	techniques = append(techniques, necessaryInBlockTechnique{})
}

type onlyLegalNumberTechnique struct {
}

type necessaryInRowTechnique struct {
}

type necessaryInColTechnique struct {
}

type necessaryInBlockTechnique struct {
}

func (self onlyLegalNumberTechnique) Name() string {
	return "Only Legal Number"
}

func (self onlyLegalNumberTechnique) Description(step *SolveStep) string {
	return fmt.Sprintf("%d is the only remaining valid number for that cell", step.Num)
}

func (self onlyLegalNumberTechnique) Find(grid *Grid) *SolveStep {
	//This will be a random item
	obj := grid.queue.NewGetter().GetSmallerThan(2)
	if obj == nil {
		//There weren't any cells with one option.
		return nil
	}
	cell := obj.(*Cell)
	return &SolveStep{cell.Row, cell.Col, cell.Block, cell.implicitNumber(), self}
}

func (self necessaryInRowTechnique) Name() string {
	return "Necessary In Row"
}

func (self necessaryInRowTechnique) Description(step *SolveStep) string {
	//TODO: format the text to say "first/second/third/etc"
	return fmt.Sprintf("%d is required in the %d row, and %d is the only column it fits", step.Num, step.Row+1, step.Col+1)
}

func (self necessaryInRowTechnique) Find(grid *Grid) *SolveStep {
	getter := func(index int) []*Cell {
		return grid.Row(index)
	}
	return necessaryInCollection(grid, self, getter)
}

func (self necessaryInColTechnique) Name() string {
	return "Necessary In Col"
}

func (self necessaryInColTechnique) Description(step *SolveStep) string {
	//TODO: format the text to say "first/second/third/etc"
	return fmt.Sprintf("%d is required in the %d column, and %d is the only row it fits", step.Num, step.Row+1, step.Col+1)
}

func (self necessaryInColTechnique) Find(grid *Grid) *SolveStep {
	getter := func(index int) []*Cell {
		return grid.Col(index)
	}
	return necessaryInCollection(grid, self, getter)
}

func (self necessaryInBlockTechnique) Name() string {
	return "Necessary In Block"
}

func (self necessaryInBlockTechnique) Description(step *SolveStep) string {
	//TODO: format the text to say "first/second/third/etc"
	return fmt.Sprintf("%d is required in the %d block, and %d, %d is the only cell it fits", step.Num, step.Block+1, step.Row+1, step.Col+1)
}

func (self necessaryInBlockTechnique) Find(grid *Grid) *SolveStep {
	getter := func(index int) []*Cell {
		return grid.Block(index)
	}
	return necessaryInCollection(grid, self, getter)
}

func necessaryInCollection(grid *Grid, technique SolveTechnique, collectionGetter func(index int) []*Cell) *SolveStep {
	//This will be a random item
	indexes := rand.Perm(DIM)

	for _, i := range indexes {
		seenInCollection := make([]int, DIM)
		collection := collectionGetter(i)
		for _, cell := range collection {
			for _, possibility := range cell.Possibilities() {
				seenInCollection[possibility-1]++
			}
		}
		seenIndexes := rand.Perm(DIM)
		for _, index := range seenIndexes {
			seen := seenInCollection[index]
			if seen == 1 {
				//Okay, we know our target number. Which cell was it?
				for _, cell := range collection {
					if cell.Possible(index + 1) {
						//Found it!
						return &SolveStep{cell.Row, cell.Col, cell.Block, index + 1, technique}
					}
				}
			}
		}
	}
	//Nope.
	return nil
}

func (self *Grid) HumanSolve() *SolveDirections {
	return nil
}
<commit_msg>Defined SolveStep.Apply.<commit_after>package sudoku

import (
	"fmt"
	"math/rand"
)

type SolveDirections []*SolveStep

const (
	ONLY_LEGAL_NUMBER = iota
	NECESSARY_IN_ROW
	NECESSARY_IN_COL
	NECESSARY_IN_BLOCK
)

type SolveStep struct {
	Row       int
	Col       int
	Block     int
	Num       int
	Technique SolveTechnique
}

type SolveTechnique interface {
	Name() string
	Description(*SolveStep) string
	Find(*Grid) *SolveStep
}

var techniques []SolveTechnique

func init() {
	//TODO: init techniques with enough space
	techniques = append(techniques, onlyLegalNumberTechnique{})
	techniques = append(techniques, necessaryInRowTechnique{})
	techniques = append(techniques, necessaryInColTechnique{})
	techniques = append(techniques, necessaryInBlockTechnique{})
}

type onlyLegalNumberTechnique struct {
}

type necessaryInRowTechnique struct {
}

type necessaryInColTechnique struct {
}

type necessaryInBlockTechnique struct {
}

func (self *SolveStep) Apply(grid *Grid) {
	cell := grid.Cell(self.Row, self.Col)
	cell.SetNumber(self.Num)
}

func (self onlyLegalNumberTechnique) Name() string {
	return "Only Legal Number"
}

func (self onlyLegalNumberTechnique) Description(step *SolveStep) string {
	return fmt.Sprintf("%d is the only remaining valid number for that cell", step.Num)
}

func (self onlyLegalNumberTechnique) Find(grid *Grid) *SolveStep {
	//This will be a random item
	obj := grid.queue.NewGetter().GetSmallerThan(2)
	if obj == nil {
		//There weren't any cells with one option.
		return nil
	}
	cell := obj.(*Cell)
	return &SolveStep{cell.Row, cell.Col, cell.Block, cell.implicitNumber(), self}
}

func (self necessaryInRowTechnique) Name() string {
	return "Necessary In Row"
}

func (self necessaryInRowTechnique) Description(step *SolveStep) string {
	//TODO: format the text to say "first/second/third/etc"
	return fmt.Sprintf("%d is required in the %d row, and %d is the only column it fits", step.Num, step.Row+1, step.Col+1)
}

func (self necessaryInRowTechnique) Find(grid *Grid) *SolveStep {
	getter := func(index int) []*Cell {
		return grid.Row(index)
	}
	return necessaryInCollection(grid, self, getter)
}

func (self necessaryInColTechnique) Name() string {
	return "Necessary In Col"
}

func (self necessaryInColTechnique) Description(step *SolveStep) string {
	//TODO: format the text to say "first/second/third/etc"
	return fmt.Sprintf("%d is required in the %d column, and %d is the only row it fits", step.Num, step.Row+1, step.Col+1)
}

func (self necessaryInColTechnique) Find(grid *Grid) *SolveStep {
	getter := func(index int) []*Cell {
		return grid.Col(index)
	}
	return necessaryInCollection(grid, self, getter)
}

func (self necessaryInBlockTechnique) Name() string {
	return "Necessary In Block"
}

func (self necessaryInBlockTechnique) Description(step *SolveStep) string {
	//TODO: format the text to say "first/second/third/etc"
	return fmt.Sprintf("%d is required in the %d block, and %d, %d is the only cell it fits", step.Num, step.Block+1, step.Row+1, step.Col+1)
}

func (self necessaryInBlockTechnique) Find(grid *Grid) *SolveStep {
	getter := func(index int) []*Cell {
		return grid.Block(index)
	}
	return necessaryInCollection(grid, self, getter)
}

func necessaryInCollection(grid *Grid, technique SolveTechnique, collectionGetter func(index int) []*Cell) *SolveStep {
	//This will be a random item
	indexes := rand.Perm(DIM)

	for _, i := range indexes {
		seenInCollection := make([]int, DIM)
		collection := collectionGetter(i)
		for _, cell := range collection {
			for _, possibility := range cell.Possibilities() {
				seenInCollection[possibility-1]++
			}
		}
		seenIndexes := rand.Perm(DIM)
		for _, index := range seenIndexes {
			seen := seenInCollection[index]
			if seen == 1 {
				//Okay, we know our target number. Which cell was it?
				for _, cell := range collection {
					if cell.Possible(index + 1) {
						//Found it!
						return &SolveStep{cell.Row, cell.Col, cell.Block, index + 1, technique}
					}
				}
			}
		}
	}
	//Nope.
	return nil
}

func (self *Grid) HumanSolve() *SolveDirections {
	return nil
}
<|endoftext|>