<commit_before>package builder

import (
	"errors"
	"io"
	"io/ioutil"
	"regexp"

	l "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/archive"
	"github.com/modcloth/go-fileutils"
	"github.com/onsi/gocleanup"
	"github.com/rafecolton/go-dockerclient-quick"

	"github.com/sylphon/builder-core/communication"
	"github.com/sylphon/builder-core/filecheck"
	"github.com/sylphon/builder-core/parser"
)

var (
	// SkipPush will, when set to true, override any behavior set by a Bobfile and
	// will cause builders *NOT* to run `docker push` commands.  SkipPush is also set
	// by the `--skip-push` option when used on the command line.
	SkipPush bool

	imageWithTagRegex = regexp.MustCompile("^(.*):(.*)$")
)

/*
A Builder is the struct that actually does the work of moving files around and
executing the commands that do the docker build.
*/
type Builder struct {
	dockerClient    dockerclient.DockerClient
	workdir         string
	nextSubSequence *parser.SubSequence
	Stdout          io.Writer
	log             comm.LogChan
	status          comm.StatusChan
	Builderfile     string
	contextDir      string
}

/*
SetNextSubSequence sets the next subsequence within bob to be processed. This
function is exported because it is used explicitly in tests, but in Build(), it
is intended to be used as a helper function.
*/
func (bob *Builder) SetNextSubSequence(subSeq *parser.SubSequence) {
	bob.nextSubSequence = subSeq
}

// NewBuilderOptions encapsulates all of the options necessary for creating a
// new builder
type NewBuilderOptions struct {
	Log          comm.LogChan
	Status       comm.StatusChan
	ContextDir   string
	dockerClient dockerclient.DockerClient // default to nil for regular docker client
}

/*
NewBuilder returns an instance of a Builder struct.  The function exists in
case we want to initialize our Builders with something.
*/
func NewBuilder(opts NewBuilderOptions) (*Builder, error) {
	var ret = &Builder{
		log:        opts.Log,
		status:     opts.Status,
		contextDir: opts.ContextDir,
	}

	var client = opts.dockerClient
	if client == nil {
		var err error
		client, err = dockerclient.NewDockerClient()
		if err != nil {
			return nil, err
		}
	}
	ret.dockerClient = client

	if opts.Log != nil {
		ret.Stdout = comm.NewLogEntryWriter(opts.Log)
	}

	return ret, nil
}

// BuildCommandSequence performs a build from a parser-generated CommandSequence struct
func (bob *Builder) BuildCommandSequence(commandSequence *parser.CommandSequence) error {
	for _, seq := range commandSequence.Commands {
		var imageID string
		var err error

		if err := bob.cleanWorkdir(); err != nil {
			return err
		}
		bob.SetNextSubSequence(seq)
		if err := bob.setup(); err != nil {
			return err
		}

		bob.Log(
			l.WithField("container_section", seq.Metadata.Name),
			"running commands for container section",
		)

		for _, cmd := range seq.SubCommand {
			opts := &parser.DockerCmdOpts{
				DockerClient: bob.dockerClient,
				Image:        imageID,
				ImageUUID:    seq.Metadata.UUID,
				SkipPush:     SkipPush,
				Stdout:       bob.Stdout,
				Workdir:      bob.workdir,
			}
			cmd = cmd.WithOpts(opts)

			bob.Log(l.WithField("command", cmd.Message()), "running docker command")

			if imageID, err = cmd.Run(); err != nil {<commit_msg>Moving docker-client instantiation to BuildCommandSequence<commit_after>package builder

import (
	"errors"
	"io"
	"io/ioutil"
	"regexp"

	l "github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/archive"
	"github.com/modcloth/go-fileutils"
	"github.com/onsi/gocleanup"
	"github.com/rafecolton/go-dockerclient-quick"

	"github.com/sylphon/builder-core/communication"
	"github.com/sylphon/builder-core/filecheck"
	"github.com/sylphon/builder-core/parser"
)

var (
	// SkipPush will, when set to true, override any behavior set by a Bobfile and
	// will cause builders *NOT* to run `docker push` commands.  SkipPush is also set
	// by the `--skip-push` option when used on the command line.
	SkipPush bool

	imageWithTagRegex = regexp.MustCompile("^(.*):(.*)$")
)

/*
A Builder is the struct that actually does the work of moving files around and
executing the commands that do the docker build.
*/
type Builder struct {
	dockerClient    dockerclient.DockerClient
	workdir         string
	nextSubSequence *parser.SubSequence
	Stdout          io.Writer
	log             comm.LogChan
	status          comm.StatusChan
	Builderfile     string
	contextDir      string
}

/*
SetNextSubSequence sets the next subsequence within bob to be processed. This
function is exported because it is used explicitly in tests, but in Build(), it
is intended to be used as a helper function.
*/
func (bob *Builder) SetNextSubSequence(subSeq *parser.SubSequence) {
	bob.nextSubSequence = subSeq
}

// NewBuilderOptions encapsulates all of the options necessary for creating a
// new builder
type NewBuilderOptions struct {
	Log          comm.LogChan
	Status       comm.StatusChan
	ContextDir   string
	dockerClient dockerclient.DockerClient // default to nil for regular docker client
}

/*
NewBuilder returns an instance of a Builder struct.  The function exists in
case we want to initialize our Builders with something.
*/
func NewBuilder(opts NewBuilderOptions) *Builder {
	var ret = &Builder{
		log:        opts.Log,
		status:     opts.Status,
		contextDir: opts.ContextDir,
	}

	ret.dockerClient = opts.dockerClient

	if opts.Log != nil {
		ret.Stdout = comm.NewLogEntryWriter(opts.Log)
	}

	return ret
}

// BuildCommandSequence performs a build from a parser-generated CommandSequence struct
func (bob *Builder) BuildCommandSequence(commandSequence *parser.CommandSequence) error {
	if bob.client == nil {
		var err error
		client, err = dockerclient.NewDockerClient()
		if err != nil {
			return err
		}
	}

	for _, seq := range commandSequence.Commands {
		var imageID string
		var err error

		if err := bob.cleanWorkdir(); err != nil {
			return err
		}
		bob.SetNextSubSequence(seq)
		if err := bob.setup(); err != nil {
			return err
		}

		bob.Log(
			l.WithField("container_section", seq.Metadata.Name),
			"running commands for container section",
		)

		for _, cmd := range seq.SubCommand {
			opts := &parser.DockerCmdOpts{
				DockerClient: bob.dockerClient,
				Image:        imageID,
				ImageUUID:    seq.Metadata.UUID,
				SkipPush:     SkipPush,
				Stdout:       bob.Stdout,
				Workdir:      bob.workdir,
			}
			cmd = cmd.WithOpts(opts)

			bob.Log(l.WithField("command", cmd.Message()), "running docker command")

			if imageID, err = cmd.Run(); err != nil {
{'fraction_non_alphanumeric': 0.09589460784313726, 'fraction_numerical': 0.0, 'mean_word_length': 3.4114864864864867, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1310147', 'n_tokens_mistral': 2196, 'n_tokens_neox': 2000, 'n_words': 624}