<commit_before>package main

import (
	"fmt"

	"github.com/joist-engineering/force/project"
	"github.com/joist-engineering/force/salesforce"
	"github.com/joist-engineering/force/util"
)

var cmdImport = &Command{
	Usage: "import [deployment options]",
	Short: "Import metadata from a local directory",
	Long: `
Import metadata from a local directory

Deployment Options
  -rollbackonerror, -r    Indicates whether any failure causes a complete rollback
  -runalltests, -t        If set all Apex tests defined in the organization are run (equivalent to -l RunAllTestsInOrg)
  -checkonly, -c          Indicates whether classes and triggers are saved during deployment
  -purgeondelete, -p      If set the deleted components are not stored in recycle bin
  -allowmissingfiles, -m  Specifies whether a deploy succeeds even if files missing
  -autoupdatepackage, -u  Auto add files to the package if missing
  -test                   Run tests in class (implies -l RunSpecifiedTests)
  -testlevel, -l          Set test level (NoTestRun, RunSpecifiedTests, RunLocalTests, RunAllTestsInOrg)
  -ignorewarnings, -i     Indicates if warnings should fail deployment or not
  -directory, -d 		  Path to the package.xml file to import
  -verbose, -v 			  Provide detailed feedback on operation

Examples:

  force import

  force import -directory=my_metadata -c -r -v

  force import -checkonly -runalltests
`,
}

var (
	testsToRun            metaName
	rollBackOnErrorFlag   = cmdImport.Flag.Bool("rollbackonerror", false, "set roll back on error")
	runAllTestsFlag       = cmdImport.Flag.Bool("runalltests", false, "set run all tests")
	testLevelFlag         = cmdImport.Flag.String("testLevel", "NoTestRun", "set test level")
	checkOnlyFlag         = cmdImport.Flag.Bool("checkonly", false, "set check only")
	purgeOnDeleteFlag     = cmdImport.Flag.Bool("purgeondelete", false, "set purge on delete")
	allowMissingFilesFlag = cmdImport.Flag.Bool("allowmissingfiles", false, "set allow missing files")
	autoUpdatePackageFlag = cmdImport.Flag.Bool("autoupdatepackage", false, "set auto update package")
	ignoreWarningsFlag    = cmdImport.Flag.Bool("ignorewarnings", false, "set ignore warnings")
	directory             = cmdImport.Flag.String("directory", "metadata", "relative path to package.xml")
	verbose               = cmdImport.Flag.Bool("verbose", false, "give more verbose output")
)

func init() {
	cmdImport.Run = runImport
	cmdImport.Flag.BoolVar(verbose, "v", false, "give more verbose output")
	cmdImport.Flag.BoolVar(rollBackOnErrorFlag, "r", false, "set roll back on error")
	cmdImport.Flag.BoolVar(runAllTestsFlag, "t", false, "set run all tests")
	cmdImport.Flag.StringVar(testLevelFlag, "l", "NoTestRun", "set test level")
	cmdImport.Flag.BoolVar(checkOnlyFlag, "c", false, "set check only")
	cmdImport.Flag.BoolVar(purgeOnDeleteFlag, "p", false, "set purge on delete")
	cmdImport.Flag.BoolVar(allowMissingFilesFlag, "m", false, "set allow missing files")
	cmdImport.Flag.BoolVar(autoUpdatePackageFlag, "u", false, "set auto update package")
	cmdImport.Flag.BoolVar(ignoreWarningsFlag, "i", false, "set ignore warnings")
	cmdImport.Flag.StringVar(directory, "d", "metadata", "relative path to package.xml")
	cmdImport.Flag.Var(&testsToRun, "test", "Test(s) to run")
}

func runImport(cmd *Command, args []string) {
	if len(args) > 0 {
		util.ErrorAndExit("Unrecognized argument: " + args[0])
	}

	loadedProject := project.LoadProject(*directory)

	force, err := ActiveForce()
	if err != nil {
		util.ErrorAndExit(err.Error())
	}
	files := loadedProject.EnumerateContents()

	loginUsername, err := ActiveLogin()
	if err != nil {
		util.ErrorAndExit(err.Error())
	}

	if projectEnvironmentConfig, err := loadedProject.GetEnvironmentConfigForActiveEnvironment(loginUsername, force.Credentials.InstanceUrl); projectEnvironmentConfig != nil {
		fmt.Printf("About to deploy to: %s at %s\n", projectEnvironmentConfig.Name, force.Credentials.InstanceUrl)
		files = loadedProject.ContentsWithInternalTransformsApplied(projectEnvironmentConfig)
	} else if err != nil {
		util.ErrorAndExit(err.Error())
	}

	// Now to handle the metadata types that Salesforce has implemented their
	// own versioning regimes for, do a retrieval of the current content of the
	// environment.
	query := salesforce.ForceMetadataQuery{
		{Name: "FlowDefinition", Members: []string{"*"}},
		{Name: "Flow", Members: []string{"*"}},
	}

	// if we have any flows to deploy, run a remote query to see if we actually
	// have any non-replaceable metadata that requires it!
	if project.IsNewFlowVersionsOnlyTransformRequired(files) {
		fmt.Print("Flows are present, checking for active flows in target to skip...\n")
		targetFlowsAndDefinitions, err := force.Metadata.Retrieve(query, salesforce.ForceRetrieveOptions{})
		if err != nil {
			fmt.Printf("Encountered an error with retrieve...\n")
			util.ErrorAndExit(err.Error())
		}

		files = project.TransformDeployToIncludeNewFlowVersionsOnly(files, targetFlowsAndDefinitions)
	}

	var DeploymentOptions salesforce.ForceDeployOptions
	DeploymentOptions.AllowMissingFiles = *allowMissingFilesFlag
	DeploymentOptions.AutoUpdatePackage = *autoUpdatePackageFlag
	DeploymentOptions.CheckOnly = *checkOnlyFlag
	DeploymentOptions.IgnoreWarnings = *ignoreWarningsFlag
	DeploymentOptions.PurgeOnDelete = *purgeOnDeleteFlag
	DeploymentOptions.RollbackOnError = *rollBackOnErrorFlag
	DeploymentOptions.TestLevel = *testLevelFlag
	if *runAllTestsFlag {
		DeploymentOptions.TestLevel = "RunAllTestsInOrg"
	}
	DeploymentOptions.RunTests = testsToRun

	result, err := force.Metadata.Deploy(files, DeploymentOptions)
	problems := result.Details.ComponentFailures
	successes := result.Details.ComponentSuccesses
	if err != nil {
		util.ErrorAndExit(err.Error())
	}

	fmt.Printf("\nFailures - %d\n", len(problems))
	if *verbose {
		for _, problem := range problems {
			if problem.FullName == "" {
				fmt.Println(problem.Problem)
			} else {
				fmt.Printf("%s: %s\n", problem.FullName, problem.Problem)
			}
		}
	}

	fmt.Printf("\nSuccesses - %d\n", len(successes))
	if *verbose {
		for _, success := range successes {
			if success.FullName != "package.xml" {
				verb := "unchanged"
				if success.Changed {
					verb = "changed"
				} else if success.Deleted {
					verb = "deleted"
				} else if success.Created {
					verb = "created"
				}
				fmt.Printf("%s\n\tstatus: %s\n\tid=%s\n", success.FullName, verb, success.Id)
			}
		}
	}
	fmt.Printf("Imported from %s\n", loadedProject.LoadedFromPath())
}
<commit_msg>Improve import results a bit to improve CI experience!<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/joist-engineering/force/project"
	"github.com/joist-engineering/force/salesforce"
	"github.com/joist-engineering/force/util"
)

var cmdImport = &Command{
	Usage: "import [deployment options]",
	Short: "Import metadata from a local directory",
	Long: `
Import metadata from a local directory

Deployment Options
  -rollbackonerror, -r    Indicates whether any failure causes a complete rollback
  -runalltests, -t        If set all Apex tests defined in the organization are run (equivalent to -l RunAllTestsInOrg)
  -checkonly, -c          Indicates whether classes and triggers are saved during deployment
  -purgeondelete, -p      If set the deleted components are not stored in recycle bin
  -allowmissingfiles, -m  Specifies whether a deploy succeeds even if files missing
  -autoupdatepackage, -u  Auto add files to the package if missing
  -test                   Run tests in class (implies -l RunSpecifiedTests)
  -testlevel, -l          Set test level (NoTestRun, RunSpecifiedTests, RunLocalTests, RunAllTestsInOrg)
  -ignorewarnings, -i     Indicates if warnings should fail deployment or not
  -directory, -d 		  Path to the package.xml file to import
  -verbose, -v 			  Provide detailed feedback on operation

Examples:

  force import

  force import -directory=my_metadata -c -r -v

  force import -checkonly -runalltests
`,
}

var (
	testsToRun            metaName
	rollBackOnErrorFlag   = cmdImport.Flag.Bool("rollbackonerror", false, "set roll back on error")
	runAllTestsFlag       = cmdImport.Flag.Bool("runalltests", false, "set run all tests")
	testLevelFlag         = cmdImport.Flag.String("testLevel", "NoTestRun", "set test level")
	checkOnlyFlag         = cmdImport.Flag.Bool("checkonly", false, "set check only")
	purgeOnDeleteFlag     = cmdImport.Flag.Bool("purgeondelete", false, "set purge on delete")
	allowMissingFilesFlag = cmdImport.Flag.Bool("allowmissingfiles", false, "set allow missing files")
	autoUpdatePackageFlag = cmdImport.Flag.Bool("autoupdatepackage", false, "set auto update package")
	ignoreWarningsFlag    = cmdImport.Flag.Bool("ignorewarnings", false, "set ignore warnings")
	directory             = cmdImport.Flag.String("directory", "metadata", "relative path to package.xml")
	verbose               = cmdImport.Flag.Bool("verbose", false, "give more verbose output")
)

func init() {
	cmdImport.Run = runImport
	cmdImport.Flag.BoolVar(verbose, "v", false, "give more verbose output")
	cmdImport.Flag.BoolVar(rollBackOnErrorFlag, "r", false, "set roll back on error")
	cmdImport.Flag.BoolVar(runAllTestsFlag, "t", false, "set run all tests")
	cmdImport.Flag.StringVar(testLevelFlag, "l", "NoTestRun", "set test level")
	cmdImport.Flag.BoolVar(checkOnlyFlag, "c", false, "set check only")
	cmdImport.Flag.BoolVar(purgeOnDeleteFlag, "p", false, "set purge on delete")
	cmdImport.Flag.BoolVar(allowMissingFilesFlag, "m", false, "set allow missing files")
	cmdImport.Flag.BoolVar(autoUpdatePackageFlag, "u", false, "set auto update package")
	cmdImport.Flag.BoolVar(ignoreWarningsFlag, "i", false, "set ignore warnings")
	cmdImport.Flag.StringVar(directory, "d", "metadata", "relative path to package.xml")
	cmdImport.Flag.Var(&testsToRun, "test", "Test(s) to run")
}

func runImport(cmd *Command, args []string) {
	if len(args) > 0 {
		util.ErrorAndExit("Unrecognized argument: " + args[0])
	}

	loadedProject := project.LoadProject(*directory)

	force, err := ActiveForce()
	if err != nil {
		util.ErrorAndExit(err.Error())
	}
	files := loadedProject.EnumerateContents()

	loginUsername, err := ActiveLogin()
	if err != nil {
		util.ErrorAndExit(err.Error())
	}

	if projectEnvironmentConfig, err := loadedProject.GetEnvironmentConfigForActiveEnvironment(loginUsername, force.Credentials.InstanceUrl); projectEnvironmentConfig != nil {
		fmt.Printf("About to deploy to: %s at %s\n", projectEnvironmentConfig.Name, force.Credentials.InstanceUrl)
		files = loadedProject.ContentsWithInternalTransformsApplied(projectEnvironmentConfig)
	} else if err != nil {
		util.ErrorAndExit(err.Error())
	}

	// Now to handle the metadata types that Salesforce has implemented their
	// own versioning regimes for, do a retrieval of the current content of the
	// environment.
	query := salesforce.ForceMetadataQuery{
		{Name: "FlowDefinition", Members: []string{"*"}},
		{Name: "Flow", Members: []string{"*"}},
	}

	// if we have any flows to deploy, run a remote query to see if we actually
	// have any non-replaceable metadata that requires it!
	if project.IsNewFlowVersionsOnlyTransformRequired(files) {
		fmt.Print("Flows are present, checking for active flows in target to skip...\n")
		targetFlowsAndDefinitions, err := force.Metadata.Retrieve(query, salesforce.ForceRetrieveOptions{})
		if err != nil {
			fmt.Printf("Encountered an error with retrieve...\n")
			util.ErrorAndExit(err.Error())
		}

		files = project.TransformDeployToIncludeNewFlowVersionsOnly(files, targetFlowsAndDefinitions)
	}

	var DeploymentOptions salesforce.ForceDeployOptions
	DeploymentOptions.AllowMissingFiles = *allowMissingFilesFlag
	DeploymentOptions.AutoUpdatePackage = *autoUpdatePackageFlag
	DeploymentOptions.CheckOnly = *checkOnlyFlag
	DeploymentOptions.IgnoreWarnings = *ignoreWarningsFlag
	DeploymentOptions.PurgeOnDelete = *purgeOnDeleteFlag
	DeploymentOptions.RollbackOnError = *rollBackOnErrorFlag
	DeploymentOptions.TestLevel = *testLevelFlag
	if *runAllTestsFlag {
		DeploymentOptions.TestLevel = "RunAllTestsInOrg"
	}
	DeploymentOptions.RunTests = testsToRun

	result, err := force.Metadata.Deploy(files, DeploymentOptions)
	problems := result.Details.ComponentFailures
	successes := result.Details.ComponentSuccesses
	if err != nil {
		util.ErrorAndExit(err.Error())
	}

	fmt.Printf("\nFailures - %d\n", len(problems))

	for _, problem := range problems {
		if problem.FullName == "" {
			fmt.Println(problem.Problem)
		} else {
			fmt.Printf("%s: %s\n", problem.FullName, problem.Problem)
		}
	}

	fmt.Printf("\nSuccesses - %d\n", len(successes))
	if *verbose {
		for _, success := range successes {
			if success.FullName != "package.xml" {
				verb := "unchanged"
				if success.Changed {
					verb = "changed"
				} else if success.Deleted {
					verb = "deleted"
				} else if success.Created {
					verb = "created"
				}
				fmt.Printf("%s\n\tstatus: %s\n\tid=%s\n", success.FullName, verb, success.Id)
			}
		}
	}
	fmt.Printf("Imported from %s\n", loadedProject.LoadedFromPath())
	fmt.Printf("See build status (and Quick Deploy if needed) at: https://%s/changemgmt/monitorDeploymentsDetails.apexp?retURL=/changemgmt/monitorDeployment.apexp&asyncId=%s\n", force.Credentials.InstanceUrl, result.Id)

	// if failures, return non-zero exit code:
	if !result.Success || len(problems) > 0 {
		os.Exit(-1)
	}
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package main

//
// The bundler turns files into resources contained in go code.
//
// This is useful for serving HTML and Javascript files from a self-contained binary.
//

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const APACHE_HEADER = `/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
`

const GENERATED_CODE_COMMENT = "// THIS IS GENERATED CODE.  DO NOT EDIT."

var SEP string = string(os.PathSeparator)

// Return true if a file contains a given string.
func fileContainsString(path, line string) (bool, error) {
	file, err := os.Open(path)
	if err != nil {
		return false, err
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), line) {
			return true, nil
		}
	}
	if err := scanner.Err(); err != nil {
		return false, err
	}
	return false, nil
}

// Converts a source file path to a destination file path
func sfileToDfile(sfile string) string {
	return strings.Replace(sfile, SEP, "__", -1) + ".go"
}

// Delete generated files that are in dfiles but not sfiles.
// sfiles and dfiles must be sorted by file name.
func deleteUnusedDst(sfiles []string, dst string, dfiles []os.FileInfo) error {
	s := 0
	for d := range dfiles {
		fullDst := dst + SEP + dfiles[d].Name()
		generated, err := fileContainsString(fullDst, GENERATED_CODE_COMMENT)
		if err != nil {
			return err
		}
		if !generated {
			// Skip this destination file, since it is not generated.
			continue
		}
		found := false
		for {
			if s >= len(sfiles) {
				break
			}
			tgt := sfileToDfile(sfiles[s])
			if tgt == dfiles[d].Name() {
				found = true
				break
			}
			if tgt > dfiles[d].Name() {
				break
			}
			s++
		}
		if !found {
			log.Printf("Removing %s\n", fullDst)
			err := os.Remove(fullDst)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func createBundleFile(pkg, src, sfile, dst string) error {
	// Open destination file and write header.
	tgt := sfileToDfile(sfile)
	fullDst := dst + SEP + tgt
	out, err := os.Create(fullDst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = out.WriteString(APACHE_HEADER)
	if err != nil {
		return err
	}
	_, err = out.WriteString("\n" + GENERATED_CODE_COMMENT + "\n")
	if err != nil {
		return err
	}
	_, err = out.WriteString(fmt.Sprintf("\npackage %s\n", pkg))
	if err != nil {
		return err
	}
	_, err = out.WriteString(fmt.Sprintf("var _ = addResource(\"%s\", `\n", tgt[:len(tgt)-3]))
	if err != nil {
		return err
	}

	// Open source file and create scanner.
	fullSrc := src + SEP + sfile
	in, err := os.Open(fullSrc)
	if err != nil {
		return err
	}
	defer in.Close()
	reader := bufio.NewReader(in)
	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		_, err := out.WriteString(strings.Replace(scanner.Text(), "`", "` + \"`\" + `", -1) + "\n")
		if err != nil {
			return err
		}
	}
	_, err = out.WriteString("`)\n")
	if err != nil {
		return err
	}
	err = out.Close()
	if err != nil {
		return err
	}
	return nil
}

var src = flag.String("src", "", "Source path for bundled resources.")
var dst = flag.String("dst", "", "Destination path for bundled resources.")
var pkg = flag.String("pkg", "resource", "Package name to use for bundled resources")

func main() {
	flag.Parse()
	if *src == "" {
		log.Fatal("You must supply a src directory to bundle.")
	}
	if *dst == "" {
		log.Fatal("You must supply a dst directory for output.")
	}
	sfiles := make([]string, 0, 32)
	absSrc, err := filepath.Abs(filepath.Clean(*src))
	if err != nil {
		log.Fatalf("Error getting absolute path for %s: %s\n", *src, err.Error())
	}
	err = filepath.Walk(absSrc, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		var suffix string
		suffix, err = filepath.Rel(absSrc, path)
		if err != nil {
			return err
		}
		sfiles = append(sfiles, suffix)
		return nil
	})
	if err != nil {
		log.Fatalf("Error listing files in src directory %s: %s\n", absSrc, err.Error())
	}
	var dfiles []os.FileInfo
	dfiles, err = ioutil.ReadDir(*dst)
	if err != nil {
		log.Fatalf("Error listing files in output directory %s: %s\n", *dst, err.Error())
	}
	deleteUnusedDst(sfiles, *dst, dfiles)
	for s := range sfiles {
		err = createBundleFile(*pkg, absSrc, sfiles[s], *dst)
		if err != nil {
			log.Fatalf("Error creating bundle file for %s in %s: %s\n",
				sfiles[s], *dst, err.Error())
		}
		log.Printf("Bundled %s as %s\n", absSrc, absSrc+SEP+sfileToDfile(sfiles[s]))
	}
}
<commit_msg>HTRACE-79 addendum.  Fix broken build from "Unicode (UTF-8) BOM in middle of file" error from bundler.go<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package main

//
// The bundler turns files into resources contained in go code.
//
// This is useful for serving HTML and Javascript files from a self-contained binary.
//

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

const APACHE_HEADER = `/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
`

const GENERATED_CODE_COMMENT = "// THIS IS GENERATED CODE.  DO NOT EDIT."

var SEP string = string(os.PathSeparator)

// Return true if a file contains a given string.
func fileContainsString(path, line string) (bool, error) {
	file, err := os.Open(path)
	if err != nil {
		return false, err
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), line) {
			return true, nil
		}
	}
	if err := scanner.Err(); err != nil {
		return false, err
	}
	return false, nil
}

// Converts a source file path to a destination file path
func sfileToDfile(sfile string) string {
	return strings.Replace(sfile, SEP, "__", -1) + ".go"
}

// Delete generated files that are in dfiles but not sfiles.
// sfiles and dfiles must be sorted by file name.
func deleteUnusedDst(sfiles []string, dst string, dfiles []os.FileInfo) error {
	s := 0
	for d := range dfiles {
		fullDst := dst + SEP + dfiles[d].Name()
		generated, err := fileContainsString(fullDst, GENERATED_CODE_COMMENT)
		if err != nil {
			return err
		}
		if !generated {
			// Skip this destination file, since it is not generated.
			continue
		}
		found := false
		for {
			if s >= len(sfiles) {
				break
			}
			tgt := sfileToDfile(sfiles[s])
			if tgt == dfiles[d].Name() {
				found = true
				break
			}
			if tgt > dfiles[d].Name() {
				break
			}
			s++
		}
		if !found {
			log.Printf("Removing %s\n", fullDst)
			err := os.Remove(fullDst)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func createBundleFile(pkg, src, sfile, dst string) error {
	// Open destination file and write header.
	tgt := sfileToDfile(sfile)
	fullDst := dst + SEP + tgt
	out, err := os.Create(fullDst)
	if err != nil {
		return err
	}
	defer out.Close()
	_, err = out.WriteString(APACHE_HEADER)
	if err != nil {
		return err
	}
	_, err = out.WriteString("\n" + GENERATED_CODE_COMMENT + "\n")
	if err != nil {
		return err
	}
	_, err = out.WriteString(fmt.Sprintf("\npackage %s\n", pkg))
	if err != nil {
		return err
	}
	_, err = out.WriteString(fmt.Sprintf("var _ = addResource(\"%s\", `\n", tgt[:len(tgt)-3]))
	if err != nil {
		return err
	}

	// Open source file and create scanner.
	fullSrc := src + SEP + sfile
	in, err := os.Open(fullSrc)
	if err != nil {
		return err
	}
	defer in.Close()
	reader := bufio.NewReader(in)
	scanner := bufio.NewScanner(reader)
	for scanner.Scan() {
		str := strings.Replace(scanner.Text(), "`", "` + \"`\" + `", -1) + "\n"
		// Avoid "Unicode (UTF-8) BOM in middle of file" error.
		str = strings.Replace(str, "\uFEFF", "` + \"\\uFEFF\" + `", -1)
		_, err := out.WriteString(str)
		if err != nil {
			return err
		}
	}
	_, err = out.WriteString("`)\n")
	if err != nil {
		return err
	}
	err = out.Close()
	if err != nil {
		return err
	}
	return nil
}

var src = flag.String("src", "", "Source path for bundled resources.")
var dst = flag.String("dst", "", "Destination path for bundled resources.")
var pkg = flag.String("pkg", "resource", "Package name to use for bundled resources")

func main() {
	flag.Parse()
	if *src == "" {
		log.Fatal("You must supply a src directory to bundle.")
	}
	if *dst == "" {
		log.Fatal("You must supply a dst directory for output.")
	}
	sfiles := make([]string, 0, 32)
	absSrc, err := filepath.Abs(filepath.Clean(*src))
	if err != nil {
		log.Fatalf("Error getting absolute path for %s: %s\n", *src, err.Error())
	}
	err = filepath.Walk(absSrc, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}
		var suffix string
		suffix, err = filepath.Rel(absSrc, path)
		if err != nil {
			return err
		}
		sfiles = append(sfiles, suffix)
		return nil
	})
	if err != nil {
		log.Fatalf("Error listing files in src directory %s: %s\n", absSrc, err.Error())
	}
	var dfiles []os.FileInfo
	dfiles, err = ioutil.ReadDir(*dst)
	if err != nil {
		log.Fatalf("Error listing files in output directory %s: %s\n", *dst, err.Error())
	}
	deleteUnusedDst(sfiles, *dst, dfiles)
	for s := range sfiles {
		err = createBundleFile(*pkg, absSrc, sfiles[s], *dst)
		if err != nil {
			log.Fatalf("Error creating bundle file for %s in %s: %s\n",
				sfiles[s], *dst, err.Error())
		}
		log.Printf("Bundled %s as %s\n", absSrc, *dst+SEP+sfileToDfile(sfiles[s]))
	}
}
<|endoftext|>


<commit_before>package volume

import "github.com/krasin/g3"

const (
	// Size of leaf cube
	lh = 5

	masklh  = (1 << lh) - 1
	mask3lh = (1 << (3 * lh)) - 1
)

// SparseVolume represents a voxel cube.
type SparseVolume struct {
	n      int
	LK     int
	Cubes  [][]uint16
	Colors []uint16
}

// NewSparseVolume create a voxel cube with side n.
func NewSparseVolume(n int) (v *SparseVolume) {
	lk := int(log2(int64(n)) - lh)
	return &SparseVolume{
		n:      n,
		LK:     lk,
		Cubes:  make([][]uint16, 1<<uint(3*lk)),
		Colors: make([]uint16, 1<<uint(3*lk)),
	}
}

// Get returns true, if the voxel is filled (color != 0).
func (v *SparseVolume) Get(node g3.Node) bool {
	return v.GetV(node) != 0
}

// GetV returns the color of the voxel (empty voxel has color == 0).
func (vol *SparseVolume) GetV(node g3.Node) uint16 {
	for _, v := range node {
		if v < 0 || v >= vol.n {
			return 0
		}
	}
	k := point2k(node)
	if vol.Cubes[k] == nil {
		return vol.Colors[k]
	}
	return vol.Cubes[k][point2h(node)]
}

func (v *SparseVolume) XLen() int {
	return v.n
}

func (v *SparseVolume) YLen() int {
	return v.n
}

func (v *SparseVolume) ZLen() int {
	return v.n
}

// Set sets the color of the voxel.
func (vol *SparseVolume) Set(node g3.Node, val uint16) {
	for _, v := range node {
		if v < 0 || v >= vol.n {
			return
		}
	}
	k := point2k(node)
	if vol.Cubes[k] == nil {
		if vol.Colors[k] == val {
			return
		}
		old := vol.Colors[k]
		vol.Colors[k] = 0
		vol.Cubes[k] = make([]uint16, 1<<(3*lh))
		for i := range vol.Cubes[k] {
			vol.Cubes[k][i] = old
		}
	}
	vol.Cubes[k][point2h(node)] = val
}

// SetAllFilled sets the specified color to all voxels with color >= threshold.
func (v *SparseVolume) SetAllFilled(threshold, val uint16) {
	for k, cube := range v.Cubes {
		if cube == nil {
			if v.Colors[k] >= threshold {
				v.Colors[k] = val
			}
			continue
		}
		for h, cur := range cube {
			if cur >= threshold {
				cube[h] = val
			}
		}
	}
}

// MapBoundary invokes a provided function on every border voxel.
func (v *SparseVolume) MapBoundary(f func(node g3.Node)) {
	for k, cube := range v.Cubes {
		if cube == nil {
			// Skip empty cubes
			if v.Colors[k] == 0 {
				continue
			}
			p := k2point(k)
			side := 1 << uint(v.LK)
			for x := 0; x < side; x++ {
				var p2 g3.Node
				p2[0] = p[0] + x
				cnt1 := 0
				if x == 0 || x == side-1 {
					cnt1++
				}
				for y := 0; y < side; y++ {
					p2[1] = p[1] + y
					cnt2 := cnt1
					if y == 0 || y == side-1 {
						cnt2++
					}
					for z := 0; z < side; z++ {
						if cnt2 == 2 && (z == 0 || z == side-10) {
							if z == 0 {
								z = side - 2
							}
							continue
						}
						p2[2] = p[2] + z
						if IsBoundary(v, p2) {
							f(p2)
						}
					}
				}
			}
		}
		for h, cur := range cube {
			if cur == 0 {
				continue
			}
			p := key2point(kh2key(k, h))

			if p[0] == 0 || p[1] == 0 || p[2] == 0 ||
				int(p[0]) == v.n-1 || int(p[1]) == v.n-1 || int(p[2]) == v.n-1 {
				f(p)
				continue
			}
			hp := h2point(h)

			was := false
			for i := 0; i < 3; i++ {
				if hp[i] > 0 {
					hp2 := hp
					hp2[i]--
					if cube[point2h(hp2)] == 0 {
						f(p)
						was = true
						break
					}
				}
				if hp[i] < (1<<lh)-1 {
					hp2 := hp
					hp2[i]++
					if cube[point2h(hp2)] == 0 {
						f(p)
						was = true
						break
					}
				}
			}
			if was {
				continue
			}
			// Slow path for cube edges
			for i := 0; i < 3; i++ {
				if hp[i] == 0 {
					p2 := p
					p2[i]--
					if v.GetV(g3.Node{int(p2[0]), int(p2[1]), int(p2[2])}) == 0 {
						f(p)
						was = true
						break
					}
				}
				if hp[i] == (1<<lh)-1 {
					p2 := p
					p2[i]++
					if v.GetV(g3.Node{int(p2[0]), int(p2[1]), int(p2[2])}) == 0 {
						f(p)
						was = true
						break
					}
				}
			}
		}
	}
}

func (v *SparseVolume) Volume() (res int64) {
	for k, cube := range v.Cubes {
		if cube == nil {
			// Skip empty cubes
			if v.Colors[k] == 0 {
				continue
			}
			side := int64(1 << uint(v.LK))
			res += side * side * side
			continue
		}
		for _, val := range cube {
			if val != 0 {
				res++
			}
		}
	}
	return res
}

func log2(n int64) (res uint) {
	for n > 1 {
		n >>= 1
		res++
	}
	return
}

func point2key(p g3.Node) uint64 {
	return uint64(point2k(p))<<(3*lh) + uint64(point2h(p))
}

func point2k(p g3.Node) int {
	return (spread3(byte(p[0]>>lh)) << 2) + (spread3(byte(p[1]>>lh)) << 1) + spread3(byte(p[2]>>lh))
}

func K2cube(k int) (p g3.Node) {
	p[0] = int(join3((k >> 2) & 0x249249))
	p[1] = int(join3((k >> 1) & 0x249249))
	p[2] = int(join3(k & 0x249249))
	return
}

func Cube2k(p g3.Node) int {
	return (spread3(byte(p[0])) << 2) + (spread3(byte(p[1])) << 1) + spread3(byte(p[2]))
}

func k2point(k int) (p g3.Node) {
	p = K2cube(k)
	p[0] = p[0] << lh
	p[1] = p[1] << lh
	p[2] = p[2] << lh
	return
}

func point2h(p g3.Node) int {
	return ((int(p[0]) & masklh) << (2 * lh)) + ((int(p[1]) & masklh) << lh) + (int(p[2]) & masklh)
}

func h2point(h int) (p g3.Node) {
	p[0] = int(h >> (2 * lh))
	p[1] = int((h >> lh) & masklh)
	p[2] = int(h & masklh)
	return
}

func spread3(b byte) (x int) {
	x = int(b)
	x = ((x & 0xF0) << 8) | (x & 0x0F)
	x = ((x & 0xC00C) << 4) | (x & 0x3003)
	x = ((x & 0x82082) << 2) | (x & 0x41041)
	return
}

func join3(x int) (b byte) {
	x = ((x & 0x208208) >> 2) | (x & 0xDF7DF7)
	x = ((x & 0xC00C0) >> 4) | (x & 0x3FF3F)
	x = ((x & 0xF000) >> 8) | (x & 0x0FFF)
	return byte(x)
}

func key2h(key uint64) int {
	return int(key & mask3lh)
}

func key2k(key uint64) int {
	return int(key >> (3 * lh))
}

func key2point(key uint64) (p g3.Node) {
	ph := h2point(key2h(key))
	pk := k2point(key2k(key))
	p[0] = pk[0] | ph[0]
	p[1] = pk[1] | ph[1]
	p[2] = pk[2] | ph[2]
	return
}

func kh2key(k, h int) uint64 {
	return (uint64(k) << (3 * lh)) | uint64(h)
}

func Kh2point(k, h int) g3.Node {
	return key2point(kh2key(k, h))
}
<commit_msg>Remove unnecessary convertion from g3.Node to g3.Node<commit_after>package volume

import "github.com/krasin/g3"

const (
	// Size of leaf cube
	lh = 5

	masklh  = (1 << lh) - 1
	mask3lh = (1 << (3 * lh)) - 1
)

// SparseVolume represents a voxel cube.
type SparseVolume struct {
	n      int
	LK     int
	Cubes  [][]uint16
	Colors []uint16
}

// NewSparseVolume create a voxel cube with side n.
func NewSparseVolume(n int) (v *SparseVolume) {
	lk := int(log2(int64(n)) - lh)
	return &SparseVolume{
		n:      n,
		LK:     lk,
		Cubes:  make([][]uint16, 1<<uint(3*lk)),
		Colors: make([]uint16, 1<<uint(3*lk)),
	}
}

// Get returns true, if the voxel is filled (color != 0).
func (v *SparseVolume) Get(node g3.Node) bool {
	return v.GetV(node) != 0
}

// GetV returns the color of the voxel (empty voxel has color == 0).
func (vol *SparseVolume) GetV(node g3.Node) uint16 {
	for _, v := range node {
		if v < 0 || v >= vol.n {
			return 0
		}
	}
	k := point2k(node)
	if vol.Cubes[k] == nil {
		return vol.Colors[k]
	}
	return vol.Cubes[k][point2h(node)]
}

func (v *SparseVolume) XLen() int {
	return v.n
}

func (v *SparseVolume) YLen() int {
	return v.n
}

func (v *SparseVolume) ZLen() int {
	return v.n
}

// Set sets the color of the voxel.
func (vol *SparseVolume) Set(node g3.Node, val uint16) {
	for _, v := range node {
		if v < 0 || v >= vol.n {
			return
		}
	}
	k := point2k(node)
	if vol.Cubes[k] == nil {
		if vol.Colors[k] == val {
			return
		}
		old := vol.Colors[k]
		vol.Colors[k] = 0
		vol.Cubes[k] = make([]uint16, 1<<(3*lh))
		for i := range vol.Cubes[k] {
			vol.Cubes[k][i] = old
		}
	}
	vol.Cubes[k][point2h(node)] = val
}

// SetAllFilled sets the specified color to all voxels with color >= threshold.
func (v *SparseVolume) SetAllFilled(threshold, val uint16) {
	for k, cube := range v.Cubes {
		if cube == nil {
			if v.Colors[k] >= threshold {
				v.Colors[k] = val
			}
			continue
		}
		for h, cur := range cube {
			if cur >= threshold {
				cube[h] = val
			}
		}
	}
}

// MapBoundary invokes a provided function on every border voxel.
func (v *SparseVolume) MapBoundary(f func(node g3.Node)) {
	for k, cube := range v.Cubes {
		if cube == nil {
			// Skip empty cubes
			if v.Colors[k] == 0 {
				continue
			}
			p := k2point(k)
			side := 1 << uint(v.LK)
			for x := 0; x < side; x++ {
				var p2 g3.Node
				p2[0] = p[0] + x
				cnt1 := 0
				if x == 0 || x == side-1 {
					cnt1++
				}
				for y := 0; y < side; y++ {
					p2[1] = p[1] + y
					cnt2 := cnt1
					if y == 0 || y == side-1 {
						cnt2++
					}
					for z := 0; z < side; z++ {
						if cnt2 == 2 && (z == 0 || z == side-10) {
							if z == 0 {
								z = side - 2
							}
							continue
						}
						p2[2] = p[2] + z
						if IsBoundary(v, p2) {
							f(p2)
						}
					}
				}
			}
		}
		for h, cur := range cube {
			if cur == 0 {
				continue
			}
			p := key2point(kh2key(k, h))

			if p[0] == 0 || p[1] == 0 || p[2] == 0 ||
				int(p[0]) == v.n-1 || int(p[1]) == v.n-1 || int(p[2]) == v.n-1 {
				f(p)
				continue
			}
			hp := h2point(h)

			was := false
			for i := 0; i < 3; i++ {
				if hp[i] > 0 {
					hp2 := hp
					hp2[i]--
					if cube[point2h(hp2)] == 0 {
						f(p)
						was = true
						break
					}
				}
				if hp[i] < (1<<lh)-1 {
					hp2 := hp
					hp2[i]++
					if cube[point2h(hp2)] == 0 {
						f(p)
						was = true
						break
					}
				}
			}
			if was {
				continue
			}
			// Slow path for cube edges
			for i := 0; i < 3; i++ {
				if hp[i] == 0 {
					p2 := p
					p2[i]--
					if v.GetV(p2) == 0 {
						f(p)
						was = true
						break
					}
				}
				if hp[i] == (1<<lh)-1 {
					p2 := p
					p2[i]++
					if v.GetV(p2) == 0 {
						f(p)
						was = true
						break
					}
				}
			}
		}
	}
}

func (v *SparseVolume) Volume() (res int64) {
	for k, cube := range v.Cubes {
		if cube == nil {
			// Skip empty cubes
			if v.Colors[k] == 0 {
				continue
			}
			side := int64(1 << uint(v.LK))
			res += side * side * side
			continue
		}
		for _, val := range cube {
			if val != 0 {
				res++
			}
		}
	}
	return res
}

func log2(n int64) (res uint) {
	for n > 1 {
		n >>= 1
		res++
	}
	return
}

func point2key(p g3.Node) uint64 {
	return uint64(point2k(p))<<(3*lh) + uint64(point2h(p))
}

func point2k(p g3.Node) int {
	return (spread3(byte(p[0]>>lh)) << 2) + (spread3(byte(p[1]>>lh)) << 1) + spread3(byte(p[2]>>lh))
}

func K2cube(k int) (p g3.Node) {
	p[0] = int(join3((k >> 2) & 0x249249))
	p[1] = int(join3((k >> 1) & 0x249249))
	p[2] = int(join3(k & 0x249249))
	return
}

func Cube2k(p g3.Node) int {
	return (spread3(byte(p[0])) << 2) + (spread3(byte(p[1])) << 1) + spread3(byte(p[2]))
}

func k2point(k int) (p g3.Node) {
	p = K2cube(k)
	p[0] = p[0] << lh
	p[1] = p[1] << lh
	p[2] = p[2] << lh
	return
}

func point2h(p g3.Node) int {
	return ((int(p[0]) & masklh) << (2 * lh)) + ((int(p[1]) & masklh) << lh) + (int(p[2]) & masklh)
}

func h2point(h int) (p g3.Node) {
	p[0] = int(h >> (2 * lh))
	p[1] = int((h >> lh) & masklh)
	p[2] = int(h & masklh)
	return
}

func spread3(b byte) (x int) {
	x = int(b)
	x = ((x & 0xF0) << 8) | (x & 0x0F)
	x = ((x & 0xC00C) << 4) | (x & 0x3003)
	x = ((x & 0x82082) << 2) | (x & 0x41041)
	return
}

func join3(x int) (b byte) {
	x = ((x & 0x208208) >> 2) | (x & 0xDF7DF7)
	x = ((x & 0xC00C0) >> 4) | (x & 0x3FF3F)
	x = ((x & 0xF000) >> 8) | (x & 0x0FFF)
	return byte(x)
}

func key2h(key uint64) int {
	return int(key & mask3lh)
}

func key2k(key uint64) int {
	return int(key >> (3 * lh))
}

func key2point(key uint64) (p g3.Node) {
	ph := h2point(key2h(key))
	pk := k2point(key2k(key))
	p[0] = pk[0] | ph[0]
	p[1] = pk[1] | ph[1]
	p[2] = pk[2] | ph[2]
	return
}

func kh2key(k, h int) uint64 {
	return (uint64(k) << (3 * lh)) | uint64(h)
}

func Kh2point(k, h int) g3.Node {
	return key2point(kh2key(k, h))
}
<|endoftext|>


<commit_before>package web_test

import (
	"fmt"
	"time"

	"github.com/concourse/atc"
	"github.com/concourse/testflight/gitserver"
	"github.com/pivotal-golang/lager/lagertest"

	gclient "github.com/cloudfoundry-incubator/garden/client"
	gconn "github.com/cloudfoundry-incubator/garden/client/connection"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/sclevine/agouti/matchers"
)

var _ = Describe("BuildsView", func() {
	var build atc.Build

	Context("with a job in the configuration", func() {
		var originGitServer *gitserver.Server

		BeforeEach(func() {
			workers, err := client.ListWorkers()
			Expect(err).NotTo(HaveOccurred())

			logger := lagertest.NewTestLogger("testflight")
			gLog := logger.Session("garden-connection")

			worker := workers[0]
			var gitServerRootfs string
			for _, r := range worker.ResourceTypes {
				if r.Type == "git" {
					gitServerRootfs = r.Image
				}
			}

			originGitServer = gitserver.Start(gitServerRootfs, gclient.New(gconn.NewWithLogger("tcp", worker.GardenAddr, gLog)))
			originGitServer.CommitResource()

			_, _, _, err = client.CreateOrUpdatePipelineConfig(pipelineName, "0", atc.Config{
				Jobs: []atc.JobConfig{
					{
						Name: "some-job",
						Plan: atc.PlanSequence{
							{
								Get: "some-input-resource",
							},
							{
								Task: "some-task",
								TaskConfig: &atc.TaskConfig{
									Platform: "linux",
									Inputs: []atc.TaskInputConfig{
										{Name: "some-input-resource"},
									},
									Outputs: []atc.TaskOutputConfig{
										{Name: "some-output-src"},
									},
									Run: atc.TaskRunConfig{
										Path: "cp",
										Args: []string{"-r", "some-input-resource/.", "some-output-src"},
									},
								},
							},
							{
								Put:    "some-output-resource",
								Params: atc.Params{"repository": "some-output-src"},
							},
						},
					},
				},
				Resources: []atc.ResourceConfig{
					{
						Name: "some-input-resource",
						Type: "git",
						Source: atc.Source{
							"branch": "master",
							"uri":    originGitServer.URI(),
						},
						CheckEvery: "",
					},
					{
						Name: "some-output-resource",
						Type: "git",
						Source: atc.Source{
							"branch": "master",
							"uri":    originGitServer.URI(),
						},
						CheckEvery: "",
					},
				},
			})
			Expect(err).NotTo(HaveOccurred())

			_, err = client.UnpausePipeline(pipelineName)
			Expect(err).NotTo(HaveOccurred())

			build, err = client.CreateJobBuild(pipelineName, "some-job")
			Expect(err).NotTo(HaveOccurred())
		})

		It("can view resource information of a job build", func() {
			url := atcRoute(fmt.Sprintf("/pipelines/%s/jobs/some-job", pipelineName))

			Expect(page.Navigate(url)).To(Succeed())
			Eventually(page.Find("#page-header.succeeded")).Should(BeFound())

			Eventually(page.All(".builds-list li")).Should(HaveCount(1))

			Expect(page.Find(".builds-list li:first-child a")).To(HaveText("#1"))
			Eventually(page.Find(".builds-list li:first-child a.succeeded"), 10*time.Second).Should(BeFound())

			buildTimes, err := page.Find(".builds-list li:first-child .build-duration").Text()
			Expect(err).NotTo(HaveOccurred())
			Expect(buildTimes).To(ContainSubstring("started"))
			Expect(buildTimes).To(MatchRegexp("started \\d+s ago"))
			Expect(buildTimes).To(MatchRegexp("finished \\d+s ago"))
			Expect(buildTimes).To(MatchRegexp("duration \\d+s"))

			Eventually(page.Find(".builds-list li:first-child .inputs .resource-name"), 10*time.Second).Should(BeFound())
			Expect(page.Find(".builds-list li:first-child .inputs .resource-name")).To(HaveText("some-input-resource"))
			Expect(page.Find(".builds-list li:first-child .inputs .resource-version .dict-key")).To(HaveText("ref"))
			Expect(page.Find(".builds-list li:first-child .inputs .resource-version .dict-value")).To(MatchText("[0-9a-f]{40}"))

			Expect(page.Find(".builds-list li:first-child .outputs .resource-name")).To(HaveText("some-output-resource"))
			Expect(page.Find(".builds-list li:first-child .outputs .resource-version .dict-key")).To(HaveText("ref"))
			Expect(page.Find(".builds-list li:first-child .outputs .resource-version .dict-value")).To(MatchText("[0-9a-z]{40}"))

			// button should not have the boolean attribute "disabled" set. agouti currently returns
			// an empty string in that case.
			Expect(page.Find("button.build-action")).ToNot(BeNil())
			Expect(page.Find("button.build-action")).To(HaveAttribute("disabled", ""))
		})

		Describe("paused pipeline", func() {
			BeforeEach(func() {
				_, err := client.PausePipeline(pipelineName)
				Expect(err).NotTo(HaveOccurred())
			})

			It("displays a blue header", func() {
				Expect(page.Navigate(atcRoute(build.URL))).To(Succeed())

				Expect(page.Navigate(atcRoute(fmt.Sprintf("/pipelines/%s/jobs/job-name/builds/%d", pipelineName, build.ID)))).To(Succeed())

				// top bar should show the pipeline is paused
				Eventually(page.Find(".js-groups.paused"), 10*time.Second).Should(BeFound())
			})
		})
	})

	Context("when manual triggering of the job is disabled", func() {
		var manualTriggerDisabledBuild atc.Build

		BeforeEach(func() {
			_, _, _, err := client.CreateOrUpdatePipelineConfig(pipelineName, "0", atc.Config{
				Jobs: []atc.JobConfig{
					{
						Name: "job-manual-trigger-disabled",
					},
				},
			})
			Expect(err).NotTo(HaveOccurred())

			_, err = client.UnpausePipeline(pipelineName)
			Expect(err).NotTo(HaveOccurred())

			manualTriggerDisabledBuild, err = client.CreateJobBuild(pipelineName, "job-manual-trigger-disabled")
			Expect(err).NotTo(HaveOccurred())

			_, _, pipelineVersion, _, err := client.PipelineConfig(pipelineName)
			Expect(err).NotTo(HaveOccurred())

			_, _, _, err = client.CreateOrUpdatePipelineConfig(pipelineName, pipelineVersion, atc.Config{
				Jobs: []atc.JobConfig{
					{
						Name:                 "job-manual-trigger-disabled",
						DisableManualTrigger: true,
					},
				},
			})
			Expect(err).NotTo(HaveOccurred())
		})

		It("should have a disabled button in the build details view", func() {
			Expect(page.Navigate(atcRoute(manualTriggerDisabledBuild.URL))).To(Succeed())

			// job detail w/build info -> job detail
			Eventually(page, 10*time.Second).Should(HaveURL(atcRoute(fmt.Sprintf(
				"/pipelines/%s/jobs/job-manual-trigger-disabled/builds/%s",
				pipelineName,
				manualTriggerDisabledBuild.Name,
			))))
			Eventually(page.Find("button.build-action"), 10*time.Second).Should(HaveAttribute("disabled", "true"))
		})

		It("should have a disabled button in the job details view", func() {
			Expect(page.Navigate(atcRoute(manualTriggerDisabledBuild.URL))).To(Succeed())

			// job detail w/build info -> job detail
			Eventually(page, 10*time.Second).Should(HaveURL(atcRoute(fmt.Sprintf(
				"/pipelines/%s/jobs/job-manual-trigger-disabled/builds/%s",
				pipelineName,
				manualTriggerDisabledBuild.Name,
			))))

			Eventually(page.Find("h1 a"), 10*time.Second).Should(BeFound())
			Expect(page.Find("h1 a").Click()).To(Succeed())
			Eventually(page, 10*time.Second).Should(HaveURL(atcRoute(fmt.Sprintf(
				"/pipelines/%s/jobs/job-manual-trigger-disabled",
				pipelineName,
			))))

			Expect(page.Find("button.build-action")).ToNot(BeNil())
			Expect(page.Find("button.build-action")).To(HaveAttribute("disabled", "true"))
		})
	})
})
<commit_msg>stop git server after running tests<commit_after>package web_test

import (
	"fmt"
	"time"

	"github.com/concourse/atc"
	"github.com/concourse/testflight/gitserver"
	"github.com/pivotal-golang/lager/lagertest"

	gclient "github.com/cloudfoundry-incubator/garden/client"
	gconn "github.com/cloudfoundry-incubator/garden/client/connection"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	. "github.com/sclevine/agouti/matchers"
)

var _ = Describe("BuildsView", func() {
	var build atc.Build

	Context("with a job in the configuration", func() {
		var originGitServer *gitserver.Server

		BeforeEach(func() {
			workers, err := client.ListWorkers()
			Expect(err).NotTo(HaveOccurred())

			logger := lagertest.NewTestLogger("testflight")
			gLog := logger.Session("garden-connection")

			worker := workers[0]
			var gitServerRootfs string
			for _, r := range worker.ResourceTypes {
				if r.Type == "git" {
					gitServerRootfs = r.Image
				}
			}

			originGitServer = gitserver.Start(gitServerRootfs, gclient.New(gconn.NewWithLogger("tcp", worker.GardenAddr, gLog)))
			originGitServer.CommitResource()

			_, _, _, err = client.CreateOrUpdatePipelineConfig(pipelineName, "0", atc.Config{
				Jobs: []atc.JobConfig{
					{
						Name: "some-job",
						Plan: atc.PlanSequence{
							{
								Get: "some-input-resource",
							},
							{
								Task: "some-task",
								TaskConfig: &atc.TaskConfig{
									Platform: "linux",
									Inputs: []atc.TaskInputConfig{
										{Name: "some-input-resource"},
									},
									Outputs: []atc.TaskOutputConfig{
										{Name: "some-output-src"},
									},
									Run: atc.TaskRunConfig{
										Path: "cp",
										Args: []string{"-r", "some-input-resource/.", "some-output-src"},
									},
								},
							},
							{
								Put:    "some-output-resource",
								Params: atc.Params{"repository": "some-output-src"},
							},
						},
					},
				},
				Resources: []atc.ResourceConfig{
					{
						Name: "some-input-resource",
						Type: "git",
						Source: atc.Source{
							"branch": "master",
							"uri":    originGitServer.URI(),
						},
						CheckEvery: "",
					},
					{
						Name: "some-output-resource",
						Type: "git",
						Source: atc.Source{
							"branch": "master",
							"uri":    originGitServer.URI(),
						},
						CheckEvery: "",
					},
				},
			})
			Expect(err).NotTo(HaveOccurred())

			_, err = client.UnpausePipeline(pipelineName)
			Expect(err).NotTo(HaveOccurred())

			build, err = client.CreateJobBuild(pipelineName, "some-job")
			Expect(err).NotTo(HaveOccurred())
		})

		AfterEach(func() {
			originGitServer.Stop()
		})

		It("can view resource information of a job build", func() {
			url := atcRoute(fmt.Sprintf("/pipelines/%s/jobs/some-job", pipelineName))

			Expect(page.Navigate(url)).To(Succeed())
			Eventually(page.Find("#page-header.succeeded")).Should(BeFound())

			Eventually(page.All(".builds-list li")).Should(HaveCount(1))

			Expect(page.Find(".builds-list li:first-child a")).To(HaveText("#1"))
			Eventually(page.Find(".builds-list li:first-child a.succeeded"), 10*time.Second).Should(BeFound())

			buildTimes, err := page.Find(".builds-list li:first-child .build-duration").Text()
			Expect(err).NotTo(HaveOccurred())
			Expect(buildTimes).To(ContainSubstring("started"))
			Expect(buildTimes).To(MatchRegexp("started \\d+s ago"))
			Expect(buildTimes).To(MatchRegexp("finished \\d+s ago"))
			Expect(buildTimes).To(MatchRegexp("duration \\d+s"))

			Eventually(page.Find(".builds-list li:first-child .inputs .resource-name"), 10*time.Second).Should(BeFound())
			Expect(page.Find(".builds-list li:first-child .inputs .resource-name")).To(HaveText("some-input-resource"))
			Expect(page.Find(".builds-list li:first-child .inputs .resource-version .dict-key")).To(HaveText("ref"))
			Expect(page.Find(".builds-list li:first-child .inputs .resource-version .dict-value")).To(MatchText("[0-9a-f]{40}"))

			Expect(page.Find(".builds-list li:first-child .outputs .resource-name")).To(HaveText("some-output-resource"))
			Expect(page.Find(".builds-list li:first-child .outputs .resource-version .dict-key")).To(HaveText("ref"))
			Expect(page.Find(".builds-list li:first-child .outputs .resource-version .dict-value")).To(MatchText("[0-9a-z]{40}"))

			// button should not have the boolean attribute "disabled" set. agouti currently returns
			// an empty string in that case.
			Expect(page.Find("button.build-action")).ToNot(BeNil())
			Expect(page.Find("button.build-action")).To(HaveAttribute("disabled", ""))
		})

		Describe("paused pipeline", func() {
			BeforeEach(func() {
				_, err := client.PausePipeline(pipelineName)
				Expect(err).NotTo(HaveOccurred())
			})

			It("displays a blue header", func() {
				Expect(page.Navigate(atcRoute(build.URL))).To(Succeed())

				Expect(page.Navigate(atcRoute(fmt.Sprintf("/pipelines/%s/jobs/some-job/builds/%s", pipelineName, build.Name)))).To(Succeed())

				// top bar should show the pipeline is paused
				Eventually(page.Find(".js-groups.paused"), 10*time.Second).Should(BeFound())
			})
		})
	})

	Context("when manual triggering of the job is disabled", func() {
		var manualTriggerDisabledBuild atc.Build

		BeforeEach(func() {
			_, _, _, err := client.CreateOrUpdatePipelineConfig(pipelineName, "0", atc.Config{
				Jobs: []atc.JobConfig{
					{
						Name: "job-manual-trigger-disabled",
					},
				},
			})
			Expect(err).NotTo(HaveOccurred())

			_, err = client.UnpausePipeline(pipelineName)
			Expect(err).NotTo(HaveOccurred())

			manualTriggerDisabledBuild, err = client.CreateJobBuild(pipelineName, "job-manual-trigger-disabled")
			Expect(err).NotTo(HaveOccurred())

			_, _, pipelineVersion, _, err := client.PipelineConfig(pipelineName)
			Expect(err).NotTo(HaveOccurred())

			_, _, _, err = client.CreateOrUpdatePipelineConfig(pipelineName, pipelineVersion, atc.Config{
				Jobs: []atc.JobConfig{
					{
						Name:                 "job-manual-trigger-disabled",
						DisableManualTrigger: true,
					},
				},
			})
			Expect(err).NotTo(HaveOccurred())
		})

		It("should have a disabled button in the build details view", func() {
			Expect(page.Navigate(atcRoute(manualTriggerDisabledBuild.URL))).To(Succeed())

			// job detail w/build info -> job detail
			Eventually(page, 10*time.Second).Should(HaveURL(atcRoute(fmt.Sprintf(
				"/pipelines/%s/jobs/job-manual-trigger-disabled/builds/%s",
				pipelineName,
				manualTriggerDisabledBuild.Name,
			))))
			Eventually(page.Find("button.build-action"), 10*time.Second).Should(HaveAttribute("disabled", "true"))
		})

		It("should have a disabled button in the job details view", func() {
			Expect(page.Navigate(atcRoute(manualTriggerDisabledBuild.URL))).To(Succeed())

			// job detail w/build info -> job detail
			Eventually(page, 10*time.Second).Should(HaveURL(atcRoute(fmt.Sprintf(
				"/pipelines/%s/jobs/job-manual-trigger-disabled/builds/%s",
				pipelineName,
				manualTriggerDisabledBuild.Name,
			))))

			Eventually(page.Find("h1 a"), 10*time.Second).Should(BeFound())
			Expect(page.Find("h1 a").Click()).To(Succeed())
			Eventually(page, 10*time.Second).Should(HaveURL(atcRoute(fmt.Sprintf(
				"/pipelines/%s/jobs/job-manual-trigger-disabled",
				pipelineName,
			))))

			Expect(page.Find("button.build-action")).ToNot(BeNil())
			Expect(page.Find("button.build-action")).To(HaveAttribute("disabled", "true"))
		})
	})
})
<|endoftext|>


<commit_before>package main

import "testing"

func ensureDimensions(t *testing.T, ic *ImageConfiguration, w int, h int) {
  if ic.width != w {
    t.Errorf("expected %v to be %v", ic.width, w)

  }
  if ic.height != h {
    t.Errorf("expected %v to be %v", ic.width, h)
  }
}

func TestRectangle(t *testing.T) {
  ic, _ := NameToConfiguration("300x400")
  ensureDimensions(t, ic, 300, 400)
}

func TestSquare(t *testing.T) {
  ic, _ := NameToConfiguration("x300")
  ensureDimensions(t, ic, 300, 300)
}

func TestWidth(t *testing.T) {
  ic, _ := NameToConfiguration("w300")
  ensureDimensions(t, ic, 300, 0)
}

func TestFullSize(t *testing.T) {
  ic, _ := NameToConfiguration("full_size")
  ensureDimensions(t, ic, 0, 0)
}

func TestUnsupported(t *testing.T) {
  _, err := NameToConfiguration("random")
  if err == nil {
    t.Errorf("expected to receive an error")
  }
}
<commit_msg>Fixes tests<commit_after>package main

import "testing"

func ensureDimensions(t *testing.T, ic *ImageConfiguration, w int, h int) {
	if ic.width != w {
		t.Errorf("expected %v to be %v", ic.width, w)

	}
	if ic.height != h {
		t.Errorf("expected %v to be %v", ic.width, h)
	}
}

func TestRectangle(t *testing.T) {
	ic, _ := NameToConfiguration("300x400.jpg")
	ensureDimensions(t, ic, 300, 400)
}

func TestSquare(t *testing.T) {
	ic, _ := NameToConfiguration("x300.jpg")
	ensureDimensions(t, ic, 300, 300)
}

func TestWidth(t *testing.T) {
	ic, _ := NameToConfiguration("w300.jpg")
	ensureDimensions(t, ic, 300, 0)
}

func TestFullSize(t *testing.T) {
	ic, _ := NameToConfiguration("full_size.jpg")
	ensureDimensions(t, ic, 0, 0)
}

func TestUnsupported(t *testing.T) {
	_, err := NameToConfiguration("random.jpg")
	if err == nil {
		t.Errorf("expected to receive an error")
	}
}
<|endoftext|>


<commit_before>package lmdb

/*
#include <stdlib.h>
#include <stdio.h>
#include "lmdb.h"
*/
import "C"

const (
	// Flags for Cursor.Get
	//
	// See MDB_cursor_op.
	First        = C.MDB_FIRST          // The first item.
	FirstDup     = C.MDB_FIRST_DUP      // The first value of current key (DupSort).
	GetBoth      = C.MDB_GET_BOTH       // Get the key as well as the value (DupSort).
	GetBothRange = C.MDB_GET_BOTH_RANGE // Get the key and the nearsest value (DupSort).
	GetCurrent   = C.MDB_GET_CURRENT    // Get the key and value at the current position.
	GetMultiple  = C.MDB_GET_MULTIPLE   // Get up to a page dup values for key at current position (DupFixed).
	Last         = C.MDB_LAST           // Last item.
	LastDup      = C.MDB_LAST_DUP       // Position at last value of current key (DupSort).
	Next         = C.MDB_NEXT           // Next value.
	NextDup      = C.MDB_NEXT_DUP       // Next value of the current key (DupSort).
	NextMultiple = C.MDB_NEXT_MULTIPLE  // Get key and up to a page of values from the next cursor position (DupFixed).
	NextNoDup    = C.MDB_NEXT_NODUP     // The first value of the next key (DupSort).
	Prev         = C.MDB_PREV           // The previous item.
	PrevDup      = C.MDB_PREV_DUP       // The previous item of the current key (DupSort).
	PrevNoDup    = C.MDB_PREV_NODUP     // The last data item of the previous key (DupSort).
	Set          = C.MDB_SET            // The specified key.
	SetKey       = C.MDB_SET_KEY        // Get key and data at the specified key.
	SetRange     = C.MDB_SET_RANGE      // The first key no less than the specified key.
)

// The MDB_MULTIPLE and MDB_RESERVE flags are special and do not fit the
// calling pattern of other calls to Put.  They are not exported because they
// require special methods, PutMultiple and PutReserve in which the flag is
// implied and does not need to be passed.
const (
	// Flags for Txn.Put and Cursor.Put.
	//
	// See mdb_put and mdb_cursor_put.
	Current     = C.MDB_CURRENT     // Replace the item at the current key position (Cursor only)
	NoDupData   = C.MDB_NODUPDATA   // Store the key-value pair only if key is not present (DupSort).
	NoOverwrite = C.MDB_NOOVERWRITE // Store a new key-value pair only if key is not present.
	Append      = C.MDB_APPEND      // Append an item to the database.
	AppendDup   = C.MDB_APPENDDUP   // Append an item to the database (DupSort).
)

// Cursor operates on data inside a transaction and holds a position in the
// database.
//
// See MDB_cursor.
type Cursor struct {
	txn     *Txn
	_cursor *C.MDB_cursor
}

func openCursor(txn *Txn, db DBI) (*Cursor, error) {
	var _cursor *C.MDB_cursor
	ret := C.mdb_cursor_open(txn._txn, C.MDB_dbi(db), &_cursor)
	if ret != success {
		return nil, errno(ret)
	}
	return &Cursor{txn, _cursor}, nil
}

// Renew associates readonly cursor with txn.
//
// See mdb_cursor_renew.
func (cursor *Cursor) Renew(txn *Txn) error {
	ret := C.mdb_cursor_renew(txn._txn, cursor._cursor)
	return errno(ret)
}

// Close the cursor handle.  The cursor must not be used after Close returns.
// Cursors in write transactions must be closed before their transaction is
// terminated.
//
// See mdb_cursor_close.
func (cursor *Cursor) Close() {
	C.mdb_cursor_close(cursor._cursor)
	cursor._cursor = nil
}

// Txn returns the cursor's transaction.
func (cursor *Cursor) Txn() *Txn {
	return cursor.txn
}

// DBI returns the cursors database.
func (cursor *Cursor) DBI() DBI {
	var _dbi C.MDB_dbi
	_dbi = C.mdb_cursor_dbi(cursor._cursor)
	return DBI(_dbi)
}

// Get retrieves items from the database. The slices returned by Get reference
// readonly sections of memory and attempts to mutate the region of memory will
// result in a panic.
//
// See mdb_cursor_get.
func (cursor *Cursor) Get(setkey, setval []byte, op uint) (key, val []byte, err error) {
	k, v, err := cursor.getVal(setkey, setval, op)
	if err != nil {
		return nil, nil, err
	}
	return k.Bytes(), v.Bytes(), nil
}

// getVal retrieves items from the database.
//
// See mdb_cursor_get.
func (cursor *Cursor) getVal(setkey, setval []byte, op uint) (key, val *mdbVal, err error) {
	key = wrapVal(setkey)
	val = wrapVal(setval)
	ret := C.mdb_cursor_get(cursor._cursor, (*C.MDB_val)(key), (*C.MDB_val)(val), C.MDB_cursor_op(op))
	return key, val, errno(ret)
}

// Put stores an item in the database.
//
// See mdb_cursor_put.
func (cursor *Cursor) Put(key, val []byte, flags uint) error {
	ckey := wrapVal(key)
	cval := wrapVal(val)
	return cursor.putVal(ckey, cval, flags)
}

// PutReserve returns a []byte of length n that can be written to, potentially
// avoiding a memcopy.  The returned byte slice is only valid in txn's thread,
// before it has terminated.
func (cursor *Cursor) PutReserve(key []byte, n int, flags uint) ([]byte, error) {
	ckey := wrapVal(key)
	cval := &mdbVal{mv_size: C.size_t(n)}
	ret := C.mdb_cursor_put(cursor._cursor, (*C.MDB_val)(ckey), (*C.MDB_val)(cval), C.uint(flags|C.MDB_RESERVE))
	err := errno(ret)
	if err != nil {
		return nil, err
	}
	return cval.Bytes(), nil
}

// PutMulti stores a set of contiguous items with stride size under key.
// PutMulti returns an error if len(page) is not a multiple of stride.  The
// cursor's database must be DupFixed and DupSort.
//
// See mdb_cursor_put.
func (cursor *Cursor) PutMulti(key []byte, page []byte, stride int, flags uint) error {
	ckey := wrapVal(key)
	cval, err := WrapMulti(page, stride)
	if err != nil {
		return err
	}
	return cursor.putVal(ckey, cval.val(), flags|C.MDB_MULTIPLE)
}

// putVal stores an item in the database.
//
// See mdb_cursor_put.
func (cursor *Cursor) putVal(key, val *mdbVal, flags uint) error {
	ret := C.mdb_cursor_put(cursor._cursor, (*C.MDB_val)(key), (*C.MDB_val)(val), C.uint(flags))
	return errno(ret)
}

// Del deletes the item referred to by the cursor from the database.
//
// See mdb_cursor_del.
func (cursor *Cursor) Del(flags uint) error {
	ret := C.mdb_cursor_del(cursor._cursor, C.uint(flags))
	return errno(ret)
}

// Count returns the number of duplicates for the current key.
//
// See mdb_cursor_count.
func (cursor *Cursor) Count() (uint64, error) {
	var _size C.size_t
	ret := C.mdb_cursor_count(cursor._cursor, &_size)
	if ret != success {
		return 0, errno(ret)
	}
	return uint64(_size), nil
}
<commit_msg>cursor cleanup<commit_after>package lmdb

/*
#include <stdlib.h>
#include <stdio.h>
#include "lmdb.h"
*/
import "C"

const (
	// Flags for Cursor.Get
	//
	// See MDB_cursor_op.
	First        = C.MDB_FIRST          // The first item.
	FirstDup     = C.MDB_FIRST_DUP      // The first value of current key (DupSort).
	GetBoth      = C.MDB_GET_BOTH       // Get the key as well as the value (DupSort).
	GetBothRange = C.MDB_GET_BOTH_RANGE // Get the key and the nearsest value (DupSort).
	GetCurrent   = C.MDB_GET_CURRENT    // Get the key and value at the current position.
	GetMultiple  = C.MDB_GET_MULTIPLE   // Get up to a page dup values for key at current position (DupFixed).
	Last         = C.MDB_LAST           // Last item.
	LastDup      = C.MDB_LAST_DUP       // Position at last value of current key (DupSort).
	Next         = C.MDB_NEXT           // Next value.
	NextDup      = C.MDB_NEXT_DUP       // Next value of the current key (DupSort).
	NextMultiple = C.MDB_NEXT_MULTIPLE  // Get key and up to a page of values from the next cursor position (DupFixed).
	NextNoDup    = C.MDB_NEXT_NODUP     // The first value of the next key (DupSort).
	Prev         = C.MDB_PREV           // The previous item.
	PrevDup      = C.MDB_PREV_DUP       // The previous item of the current key (DupSort).
	PrevNoDup    = C.MDB_PREV_NODUP     // The last data item of the previous key (DupSort).
	Set          = C.MDB_SET            // The specified key.
	SetKey       = C.MDB_SET_KEY        // Get key and data at the specified key.
	SetRange     = C.MDB_SET_RANGE      // The first key no less than the specified key.
)

// The MDB_MULTIPLE and MDB_RESERVE flags are special and do not fit the
// calling pattern of other calls to Put.  They are not exported because they
// require special methods, PutMultiple and PutReserve in which the flag is
// implied and does not need to be passed.
const (
	// Flags for Txn.Put and Cursor.Put.
	//
	// See mdb_put and mdb_cursor_put.
	Current     = C.MDB_CURRENT     // Replace the item at the current key position (Cursor only)
	NoDupData   = C.MDB_NODUPDATA   // Store the key-value pair only if key is not present (DupSort).
	NoOverwrite = C.MDB_NOOVERWRITE // Store a new key-value pair only if key is not present.
	Append      = C.MDB_APPEND      // Append an item to the database.
	AppendDup   = C.MDB_APPENDDUP   // Append an item to the database (DupSort).
)

// Cursor operates on data inside a transaction and holds a position in the
// database.
//
// See MDB_cursor.
type Cursor struct {
	txn *Txn
	_c  *C.MDB_cursor
}

func openCursor(txn *Txn, db DBI) (*Cursor, error) {
	var _c *C.MDB_cursor
	ret := C.mdb_cursor_open(txn._txn, C.MDB_dbi(db), &_c)
	if ret != success {
		return nil, errno(ret)
	}
	return &Cursor{txn, _c}, nil
}

// Renew associates readonly cursor with txn.
//
// See mdb_cursor_renew.
func (c *Cursor) Renew(txn *Txn) error {
	ret := C.mdb_cursor_renew(txn._txn, c._c)
	return errno(ret)
}

// Close the cursor handle.  A runtime panic occurs if a the cursor is used
// after Close is called.
//
// Cursors in write transactions must be closed before their transaction is
// terminated.
//
// See mdb_cursor_close.
func (c *Cursor) Close() {
	C.mdb_cursor_close(c._c)
	c._c = nil
}

// Txn returns the cursor's transaction.
func (cursor *Cursor) Txn() *Txn {
	return cursor.txn
}

// DBI returns the cursor's database handle.
func (c *Cursor) DBI() DBI {
	var _dbi C.MDB_dbi
	_dbi = C.mdb_cursor_dbi(c._c)
	return DBI(_dbi)
}

// Get retrieves items from the database. The slices returned by Get reference
// readonly sections of memory and attempts to mutate the region of memory will
// result in a panic.
//
// See mdb_cursor_get.
func (c *Cursor) Get(setkey, setval []byte, op uint) (key, val []byte, err error) {
	k, v, err := c.getVal(setkey, setval, op)
	if err != nil {
		return nil, nil, err
	}
	return k.Bytes(), v.Bytes(), nil
}

// getVal retrieves items from the database.
//
// See mdb_cursor_get.
func (c *Cursor) getVal(setkey, setval []byte, op uint) (key, val *mdbVal, err error) {
	key = wrapVal(setkey)
	val = wrapVal(setval)
	ret := C.mdb_cursor_get(c._c, (*C.MDB_val)(key), (*C.MDB_val)(val), C.MDB_cursor_op(op))
	return key, val, errno(ret)
}

// Put stores an item in the database.
//
// See mdb_cursor_put.
func (c *Cursor) Put(key, val []byte, flags uint) error {
	ckey := wrapVal(key)
	cval := wrapVal(val)
	return c.putVal(ckey, cval, flags)
}

// PutReserve returns a []byte of length n that can be written to, potentially
// avoiding a memcopy.  The returned byte slice is only valid in txn's thread,
// before it has terminated.
func (c *Cursor) PutReserve(key []byte, n int, flags uint) ([]byte, error) {
	ckey := wrapVal(key)
	cval := &mdbVal{mv_size: C.size_t(n)}
	ret := C.mdb_cursor_put(c._c, (*C.MDB_val)(ckey), (*C.MDB_val)(cval), C.uint(flags|C.MDB_RESERVE))
	err := errno(ret)
	if err != nil {
		return nil, err
	}
	return cval.Bytes(), nil
}

// PutMulti stores a set of contiguous items with stride size under key.
// PutMulti returns an error if len(page) is not a multiple of stride.  The
// cursor's database must be DupFixed and DupSort.
//
// See mdb_cursor_put.
func (c *Cursor) PutMulti(key []byte, page []byte, stride int, flags uint) error {
	ckey := wrapVal(key)
	cval, err := WrapMulti(page, stride)
	if err != nil {
		return err
	}
	return c.putVal(ckey, cval.val(), flags|C.MDB_MULTIPLE)
}

// putVal stores an item in the database.
//
// See mdb_cursor_put.
func (c *Cursor) putVal(key, val *mdbVal, flags uint) error {
	ret := C.mdb_cursor_put(c._c, (*C.MDB_val)(key), (*C.MDB_val)(val), C.uint(flags))
	return errno(ret)
}

// Del deletes the item referred to by the cursor from the database.
//
// See mdb_cursor_del.
func (c *Cursor) Del(flags uint) error {
	ret := C.mdb_cursor_del(c._c, C.uint(flags))
	return errno(ret)
}

// Count returns the number of duplicates for the current key.
//
// See mdb_cursor_count.
func (c *Cursor) Count() (uint64, error) {
	var _size C.size_t
	ret := C.mdb_cursor_count(c._c, &_size)
	if ret != success {
		return 0, errno(ret)
	}
	return uint64(_size), nil
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Damon Revoe. All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

package main

var appTemplateFiles = []embeddedTemplateFile{
	embeddedTemplateFile{"configure.ac", 0644,
		[]byte(`{{template "FileHeader" . -}}
AC_INIT([{{.name}}], [{{.version}}])
AC_CONFIG_AUX_DIR([config])
AC_CONFIG_MACRO_DIRS([m4]){{if .sources}}
AC_CONFIG_SRCDIR([src/{{index .sources 0}}]){{else}}
{{$ss := Dir "src"}}{{if eq (len $ss) 0}}
	{{Error "The app template requires at least one source file in src/"}}
{{end}}AC_CONFIG_SRCDIR([src/{{index $ss 0}}]){{end}}
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign])

test -z "$CXXFLAGS" && CXXFLAGS=""

dnl Checks for programs.
AC_PROG_CXX
AC_PROG_LIBTOOL

if test "x$GXX" = "xyes"; then
	CXXFLAGS="$CXXFLAGS -Wall"
elif test "$CXX" = cxx && cxx -V < /dev/null 2>&1 | \
	grep -Eiq 'digital|compaq'; then
	DIGITALCXX="yes"
	CXXFLAGS="$CXXFLAGS -w0 -msg_display_tag -std ansi -nousing_std"
	CXXFLAGS="$CXXFLAGS -D__USE_STD_IOSTREAM -D_POSIX_PII_SOCKET"
fi
{{if .snippets}}{{if index .snippets "configure.ac"}}
{{index .snippets "configure.ac"}}{{end}}{{end}}
ACX_PTHREAD(,[AC_MSG_ERROR([this package requires pthreads support])])

CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
LIBS="$LIBS $PTHREAD_LIBS"

AC_ARG_ENABLE(debug, changequote(<<, >>)<<  --enable-debug          >>dnl
<<enable debug info and runtime checks [default=no]>>changequote([, ]))

AM_CONDITIONAL(DEBUG, test "$enable_debug" = yes)

if test "$enable_debug" != yes; then
	CXXFLAGS="$CXXFLAGS -O3"
elif test "$DIGITALCXX" = yes; then
	CXXFLAGS="$CXXFLAGS -D_DEBUG -gall"
elif test "$GXX" = yes; then
	CXXFLAGS="$CXXFLAGS -D_DEBUG -ggdb"
elif test "$ac_cv_prog_cxx_g" = yes; then
	CXXFLAGS="$CXXFLAGS -D_DEBUG -g"
fi
{{if or .external_libs .requires}}
dnl Checks for libraries.{{end}}{{if .external_libs}}{{range .external_libs}}
AC_CHECK_LIB([{{.name}}], [{{.function}}],,
	AC_MSG_ERROR([unable to link with {{.name}}]){{if .other_libs}},
	[{{.other_libs}}]{{end}}){{end}}
{{end}}{{if .requires}}
PKG_PROG_PKG_CONFIG()
{{range .requires}}
PKG_CHECK_MODULES([{{VarNameUC .}}], [{{VarName .}}])
CXXFLAGS="$CXXFLAGS ${{VarNameUC .}}_CFLAGS"
LIBS="$LIBS ${{VarNameUC .}}_LIBS"
{{end}}{{end}}
AC_OUTPUT([Makefile
src/Makefile
config/Makefile
m4/Makefile])
`)},
	embeddedTemplateFile{"config/Makefile.am", 0644,
		[]byte(`{{template "FileHeader" . -}}
MAINTAINERCLEANFILES = \
	config.guess \
	config.sub \
	depcomp \
	install-sh \
	ltconfig \
	mkinstalldirs \
	test-driver \
	Makefile.in
`)},
	embeddedTemplateFile{"Makefile.am", 0644,
		[]byte(`{{template "FileHeader" . -}}
ACLOCAL_AMFLAGS = -I m4

AUTOMAKE_OPTIONS = foreign

SUBDIRS = . config m4 src

maintainer-clean-local:
	rm -rf autom4te.cache

EXTRA_DIST = autogen.sh

MAINTAINERCLEANFILES = Makefile.in
`)},
	embeddedTemplateFile{"src/Makefile.am", 0644,
		[]byte(`{{template "FileHeader" . -}}
{{if .snippets}}{{if index .snippets "src/Makefile.am" -}}
{{index .snippets "src/Makefile.am"}}
{{end}}{{end}}if DEBUG
bin_PROGRAMS = {{.name}}d
else
bin_PROGRAMS = {{.name}}
endif{{$srcFileTypes := StringList "*?.C" "*?.c" "*?.cc" "*?.cxx" "*?.cpp"}}

sources ={{if .sources}}{{template "Multiline" .sources}}
{{else}}{{template "Multiline" Select (Dir "src") $srcFileTypes}}
{{end}}
{{VarName .name}}d_SOURCES = $(sources)
{{VarName .name}}_SOURCES = $(sources)
{{if .src_extra_dist}}
EXTRA_DIST ={{template "Multiline" .src_extra_dist}}
{{else}}{{$extraFiles := Exclude (Dir "src") $srcFileTypes}}{{if $extraFiles}}
EXTRA_DIST ={{template "Multiline" $extraFiles}}
{{end}}{{end}}
MAINTAINERCLEANFILES = Makefile.in
`)},
	embeddedTemplateFile{"autogen.sh", 0755,
		[]byte(`#!/bin/sh

{{template "FileHeader" . -}}
aclocal &&
	libtoolize --automake && \
	autoheader && \
	automake --foreign --add-missing && \
	autoconf
`)},
	embeddedTemplateFile{"m4/Makefile.am", 0644,
		[]byte(`{{template "FileHeader" . -}}
EXTRA_DIST = ax_pthread.m4

MAINTAINERCLEANFILES = Makefile.in libtool.m4 lt*.m4
`)},
}
<commit_msg>Copy libtool and automake files for distribution<commit_after>// Copyright (C) 2017 Damon Revoe. All rights reserved.
// Use of this source code is governed by the MIT
// license, which can be found in the LICENSE file.

package main

var appTemplateFiles = []embeddedTemplateFile{
	embeddedTemplateFile{"configure.ac", 0644,
		[]byte(`{{template "FileHeader" . -}}
AC_INIT([{{.name}}], [{{.version}}])
AC_CONFIG_AUX_DIR([config])
AC_CONFIG_MACRO_DIRS([m4]){{if .sources}}
AC_CONFIG_SRCDIR([src/{{index .sources 0}}]){{else}}
{{$ss := Dir "src"}}{{if eq (len $ss) 0}}
	{{Error "The app template requires at least one source file in src/"}}
{{end}}AC_CONFIG_SRCDIR([src/{{index $ss 0}}]){{end}}
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign])

test -z "$CXXFLAGS" && CXXFLAGS=""

dnl Checks for programs.
AC_PROG_CXX
AC_PROG_LIBTOOL

if test "x$GXX" = "xyes"; then
	CXXFLAGS="$CXXFLAGS -Wall"
elif test "$CXX" = cxx && cxx -V < /dev/null 2>&1 | \
	grep -Eiq 'digital|compaq'; then
	DIGITALCXX="yes"
	CXXFLAGS="$CXXFLAGS -w0 -msg_display_tag -std ansi -nousing_std"
	CXXFLAGS="$CXXFLAGS -D__USE_STD_IOSTREAM -D_POSIX_PII_SOCKET"
fi
{{if .snippets}}{{if index .snippets "configure.ac"}}
{{index .snippets "configure.ac"}}{{end}}{{end}}
ACX_PTHREAD(,[AC_MSG_ERROR([this package requires pthreads support])])

CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
LIBS="$LIBS $PTHREAD_LIBS"

AC_ARG_ENABLE(debug, changequote(<<, >>)<<  --enable-debug          >>dnl
<<enable debug info and runtime checks [default=no]>>changequote([, ]))

AM_CONDITIONAL(DEBUG, test "$enable_debug" = yes)

if test "$enable_debug" != yes; then
	CXXFLAGS="$CXXFLAGS -O3"
elif test "$DIGITALCXX" = yes; then
	CXXFLAGS="$CXXFLAGS -D_DEBUG -gall"
elif test "$GXX" = yes; then
	CXXFLAGS="$CXXFLAGS -D_DEBUG -ggdb"
elif test "$ac_cv_prog_cxx_g" = yes; then
	CXXFLAGS="$CXXFLAGS -D_DEBUG -g"
fi
{{if or .external_libs .requires}}
dnl Checks for libraries.{{end}}{{if .external_libs}}{{range .external_libs}}
AC_CHECK_LIB([{{.name}}], [{{.function}}],,
	AC_MSG_ERROR([unable to link with {{.name}}]){{if .other_libs}},
	[{{.other_libs}}]{{end}}){{end}}
{{end}}{{if .requires}}
PKG_PROG_PKG_CONFIG()
{{range .requires}}
PKG_CHECK_MODULES([{{VarNameUC .}}], [{{VarName .}}])
CXXFLAGS="$CXXFLAGS ${{VarNameUC .}}_CFLAGS"
LIBS="$LIBS ${{VarNameUC .}}_LIBS"
{{end}}{{end}}
AC_OUTPUT([Makefile
src/Makefile
config/Makefile
m4/Makefile])
`)},
	embeddedTemplateFile{"config/Makefile.am", 0644,
		[]byte(`{{template "FileHeader" . -}}
MAINTAINERCLEANFILES = \
	config.guess \
	config.sub \
	depcomp \
	install-sh \
	ltconfig \
	mkinstalldirs \
	test-driver \
	Makefile.in
`)},
	embeddedTemplateFile{"Makefile.am", 0644,
		[]byte(`{{template "FileHeader" . -}}
ACLOCAL_AMFLAGS = -I m4

AUTOMAKE_OPTIONS = foreign

SUBDIRS = . config m4 src

maintainer-clean-local:
	rm -rf autom4te.cache

EXTRA_DIST = autogen.sh

MAINTAINERCLEANFILES = Makefile.in
`)},
	embeddedTemplateFile{"src/Makefile.am", 0644,
		[]byte(`{{template "FileHeader" . -}}
{{if .snippets}}{{if index .snippets "src/Makefile.am" -}}
{{index .snippets "src/Makefile.am"}}
{{end}}{{end}}if DEBUG
bin_PROGRAMS = {{.name}}d
else
bin_PROGRAMS = {{.name}}
endif{{$srcFileTypes := StringList "*?.C" "*?.c" "*?.cc" "*?.cxx" "*?.cpp"}}

sources ={{if .sources}}{{template "Multiline" .sources}}
{{else}}{{template "Multiline" Select (Dir "src") $srcFileTypes}}
{{end}}
{{VarName .name}}d_SOURCES = $(sources)
{{VarName .name}}_SOURCES = $(sources)
{{if .src_extra_dist}}
EXTRA_DIST ={{template "Multiline" .src_extra_dist}}
{{else}}{{$extraFiles := Exclude (Dir "src") $srcFileTypes}}{{if $extraFiles}}
EXTRA_DIST ={{template "Multiline" $extraFiles}}
{{end}}{{end}}
MAINTAINERCLEANFILES = Makefile.in
`)},
	embeddedTemplateFile{"autogen.sh", 0755,
		[]byte(`#!/bin/sh

{{template "FileHeader" . -}}
aclocal &&
	libtoolize --automake --copy && \
	autoheader && \
	automake --foreign --add-missing --copy && \
	autoconf
`)},
	embeddedTemplateFile{"m4/Makefile.am", 0644,
		[]byte(`{{template "FileHeader" . -}}
EXTRA_DIST = ax_pthread.m4

MAINTAINERCLEANFILES = Makefile.in libtool.m4 lt*.m4
`)},
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"syscall"

	"github.com/reconquest/go-lineflushwriter"
	"github.com/reconquest/go-prefixwriter"
	"github.com/seletskiy/hierr"
)

func startArchiveReceivers(
	cluster *distributedLock,
	rootDir string,
	sudo bool,
) (*remoteExecution, error) {
	command := []string{}

	prefix := []string{}
	if sudo {
		prefix = sudoCommand
	}

	command = append(command, prefix...)
	command = append(command, `mkdir`, `-p`, rootDir, `&&`)
	command = append(command, prefix...)
	command = append(command, `tar`, `--directory`, rootDir, `-x`)

	if verbose >= verbosityDebug {
		command = append(command, `--verbose`)
	}

	logMutex := &sync.Mutex{}

	runner := &remoteExecutionRunner{command: command}

	execution, err := runner.run(
		cluster,
		func(node *remoteExecutionNode) {
			node.stdout = lineflushwriter.New(
				prefixwriter.New(node.stdout, "{tar} "),
				logMutex,
				true,
			)

			node.stderr = lineflushwriter.New(
				prefixwriter.New(node.stderr, "{tar} "),
				logMutex,
				true,
			)
		},
	)
	if err != nil {
		return nil, hierr.Errorf(
			err,
			`can't start tar extraction command: '%v'`,
			command,
		)
	}

	return execution, nil
}

func archiveFilesToWriter(
	target io.WriteCloser,
	files []string,
	preserveUID, preserveGID bool,
) error {
	workDir, err := os.Getwd()
	if err != nil {
		return hierr.Errorf(
			err,
			`can't get current working directory`,
		)
	}

	archive := tar.NewWriter(target)
	for fileIndex, fileName := range files {
		infof(
			"%5d/%d sending file: '%s'",
			fileIndex+1,
			len(files),
			fileName,
		)

		err = writeFileToArchive(
			fileName,
			archive,
			workDir,
			preserveUID,
			preserveGID,
		)
		if err != nil {
			return hierr.Errorf(
				err,
				`can't write file to archive: '%s'`,
				fileName,
			)
		}
	}

	tracef("closing archive stream, %d files sent", len(files))

	err = archive.Close()
	if err != nil {
		return hierr.Errorf(
			err,
			`can't close tar stream`,
		)
	}

	err = target.Close()
	if err != nil {
		return hierr.Errorf(
			err,
			`can't close target stdin`,
		)
	}

	return nil
}

func writeFileToArchive(
	fileName string,
	archive *tar.Writer,
	workDir string,
	preserveUID, preserveGID bool,
) error {
	fileInfo, err := os.Stat(fileName)

	if err != nil {
		return hierr.Errorf(
			err,
			`can't stat file for archiving: '%s`, fileName,
		)
	}

	// avoid tar warnings about leading slash
	tarFileName := fileName
	if tarFileName[0] == '/' {
		tarFileName = tarFileName[1:]

		fileName, err = filepath.Rel(workDir, fileName)
		if err != nil {
			return hierr.Errorf(
				err,
				`can't make relative path from: '%s'`,
				fileName,
			)
		}
	}

	header := &tar.Header{
		Name: tarFileName,
		Mode: int64(fileInfo.Sys().(*syscall.Stat_t).Mode),
		Size: fileInfo.Size(),

		ModTime: fileInfo.ModTime(),
	}

	if preserveUID {
		header.Uid = int(fileInfo.Sys().(*syscall.Stat_t).Uid)
	}

	if preserveGID {
		header.Gid = int(fileInfo.Sys().(*syscall.Stat_t).Gid)
	}

	tracef(
		hierr.Errorf(
			fmt.Sprintf(
				"size: %d bytes; mode: %o; uid/gid: %d/%d; modtime: %s",
				header.Size,
				header.Mode,
				header.Uid,
				header.Gid,
				header.ModTime,
			),
			`local file: %s; remote file: %s`,
			fileName,
			tarFileName,
		).Error(),
	)

	err = archive.WriteHeader(header)

	if err != nil {
		return hierr.Errorf(
			err,
			`can't write tar header for fileName: '%s'`, fileName,
		)
	}

	fileToArchive, err := os.Open(fileName)
	if err != nil {
		return hierr.Errorf(
			err,
			`can't open fileName for reading: '%s'`,
			fileName,
		)
	}

	_, err = io.Copy(archive, fileToArchive)
	if err != nil {
		return hierr.Errorf(
			err,
			`can't copy file to the archive: '%s'`,
			fileName,
		)
	}

	return nil
}

func getFilesList(relative bool, sources ...string) ([]string, error) {
	files := []string{}

	for _, source := range sources {
		err := filepath.Walk(
			source,
			func(path string, info os.FileInfo, err error) error {
				if err != nil {
					return err
				}

				if info.IsDir() {
					return nil
				}

				if !relative {
					path, err = filepath.Abs(path)
					if err != nil {
						return hierr.Errorf(
							err,
							`can't get absolute path for local file: '%s'`,
							path,
						)
					}
				}

				files = append(files, path)

				return nil
			},
		)

		if err != nil {
			return nil, err
		}
	}

	return files, nil
}
<commit_msg>beautify vars in startArchiveReceivers<commit_after>package main

import (
	"archive/tar"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sync"
	"syscall"

	"github.com/reconquest/go-lineflushwriter"
	"github.com/reconquest/go-prefixwriter"
	"github.com/seletskiy/hierr"
)

func startArchiveReceivers(
	cluster *distributedLock,
	rootDir string,
	sudo bool,
) (*remoteExecution, error) {
	var (
		command = []string{}
		prefix  = []string{}
	)

	if sudo {
		prefix = sudoCommand
	}

	command = append(command, prefix...)
	command = append(command, `mkdir`, `-p`, rootDir, `&&`)
	command = append(command, prefix...)
	command = append(command, `tar`, `--directory`, rootDir, `-x`)

	if verbose >= verbosityDebug {
		command = append(command, `--verbose`)
	}

	logMutex := &sync.Mutex{}

	runner := &remoteExecutionRunner{command: command}

	execution, err := runner.run(
		cluster,
		func(node *remoteExecutionNode) {
			node.stdout = lineflushwriter.New(
				prefixwriter.New(node.stdout, "{tar} "),
				logMutex,
				true,
			)

			node.stderr = lineflushwriter.New(
				prefixwriter.New(node.stderr, "{tar} "),
				logMutex,
				true,
			)
		},
	)
	if err != nil {
		return nil, hierr.Errorf(
			err,
			`can't start tar extraction command: '%v'`,
			command,
		)
	}

	return execution, nil
}

func archiveFilesToWriter(
	target io.WriteCloser,
	files []string,
	preserveUID, preserveGID bool,
) error {
	workDir, err := os.Getwd()
	if err != nil {
		return hierr.Errorf(
			err,
			`can't get current working directory`,
		)
	}

	archive := tar.NewWriter(target)
	for fileIndex, fileName := range files {
		infof(
			"%5d/%d sending file: '%s'",
			fileIndex+1,
			len(files),
			fileName,
		)

		err = writeFileToArchive(
			fileName,
			archive,
			workDir,
			preserveUID,
			preserveGID,
		)
		if err != nil {
			return hierr.Errorf(
				err,
				`can't write file to archive: '%s'`,
				fileName,
			)
		}
	}

	tracef("closing archive stream, %d files sent", len(files))

	err = archive.Close()
	if err != nil {
		return hierr.Errorf(
			err,
			`can't close tar stream`,
		)
	}

	err = target.Close()
	if err != nil {
		return hierr.Errorf(
			err,
			`can't close target stdin`,
		)
	}

	return nil
}

func writeFileToArchive(
	fileName string,
	archive *tar.Writer,
	workDir string,
	preserveUID, preserveGID bool,
) error {
	fileInfo, err := os.Stat(fileName)

	if err != nil {
		return hierr.Errorf(
			err,
			`can't stat file for archiving: '%s`, fileName,
		)
	}

	// avoid tar warnings about leading slash
	tarFileName := fileName
	if tarFileName[0] == '/' {
		tarFileName = tarFileName[1:]

		fileName, err = filepath.Rel(workDir, fileName)
		if err != nil {
			return hierr.Errorf(
				err,
				`can't make relative path from: '%s'`,
				fileName,
			)
		}
	}

	header := &tar.Header{
		Name: tarFileName,
		Mode: int64(fileInfo.Sys().(*syscall.Stat_t).Mode),
		Size: fileInfo.Size(),

		ModTime: fileInfo.ModTime(),
	}

	if preserveUID {
		header.Uid = int(fileInfo.Sys().(*syscall.Stat_t).Uid)
	}

	if preserveGID {
		header.Gid = int(fileInfo.Sys().(*syscall.Stat_t).Gid)
	}

	tracef(
		hierr.Errorf(
			fmt.Sprintf(
				"size: %d bytes; mode: %o; uid/gid: %d/%d; modtime: %s",
				header.Size,
				header.Mode,
				header.Uid,
				header.Gid,
				header.ModTime,
			),
			`local file: %s; remote file: %s`,
			fileName,
			tarFileName,
		).Error(),
	)

	err = archive.WriteHeader(header)

	if err != nil {
		return hierr.Errorf(
			err,
			`can't write tar header for fileName: '%s'`, fileName,
		)
	}

	fileToArchive, err := os.Open(fileName)
	if err != nil {
		return hierr.Errorf(
			err,
			`can't open fileName for reading: '%s'`,
			fileName,
		)
	}

	_, err = io.Copy(archive, fileToArchive)
	if err != nil {
		return hierr.Errorf(
			err,
			`can't copy file to the archive: '%s'`,
			fileName,
		)
	}

	return nil
}

func getFilesList(relative bool, sources ...string) ([]string, error) {
	files := []string{}

	for _, source := range sources {
		err := filepath.Walk(
			source,
			func(path string, info os.FileInfo, err error) error {
				if err != nil {
					return err
				}

				if info.IsDir() {
					return nil
				}

				if !relative {
					path, err = filepath.Abs(path)
					if err != nil {
						return hierr.Errorf(
							err,
							`can't get absolute path for local file: '%s'`,
							path,
						)
					}
				}

				files = append(files, path)

				return nil
			},
		)

		if err != nil {
			return nil, err
		}
	}

	return files, nil
}
<|endoftext|>