<commit_before>package format

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"sort"
	"strings"

	"github.com/mitchellh/colorstring"
	"github.com/zclconf/go-cty/cty"
	ctyjson "github.com/zclconf/go-cty/cty/json"

	"github.com/hashicorp/terraform/addrs"
	"github.com/hashicorp/terraform/configs/configschema"
	"github.com/hashicorp/terraform/helper/experiment"
	"github.com/hashicorp/terraform/plans"
	"github.com/hashicorp/terraform/plans/objchange"
	"github.com/hashicorp/terraform/states"
)

// ResourceChange returns a string representation of a change to a particular
// resource, for inclusion in user-facing plan output.
//
// The resource schema must be provided along with the change so that the
// formatted change can reflect the configuration structure for the associated
// resource.
//
// If "color" is non-nil, it will be used to color the result. Otherwise,
// no color codes will be included.
func ResourceChange(
	change *plans.ResourceInstanceChangeSrc,
	tainted bool,
	schema *configschema.Block,
	color *colorstring.Colorize,
) string {
	addr := change.Addr
	var buf bytes.Buffer

	if color == nil {
		color = &colorstring.Colorize{
			Colors:  colorstring.DefaultColors,
			Disable: true,
			Reset:   false,
		}
	}

	dispAddr := addr.String()
	if change.DeposedKey != states.NotDeposed {
		dispAddr = fmt.Sprintf("%s (deposed object %s)", dispAddr, change.DeposedKey)
	}

	switch change.Action {
	case plans.Create:
		buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] will be created", dispAddr)))
	case plans.Read:
		buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] will be read during apply\n  # (config refers to values not yet known)", dispAddr)))
	case plans.Update:
		buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] will be updated in-place", dispAddr)))
	case plans.CreateThenDelete, plans.DeleteThenCreate:
		if tainted {
			buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] is tainted, so must be [bold][red]replaced", dispAddr)))
		} else {
			buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] must be [bold][red]replaced", dispAddr)))
		}
	case plans.Delete:
		buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] will be [bold][red]destroyed", dispAddr)))
	default:
		// should never happen, since the above is exhaustive
		buf.WriteString(fmt.Sprintf("%s has an action the plan renderer doesn't support (this is a bug)", dispAddr))
	}
	buf.WriteString(color.Color("[reset]\n"))

	buf.WriteString(color.Color(DiffActionSymbol(change.Action)) + " ")

	switch addr.Resource.Resource.Mode {
	case addrs.ManagedResourceMode:
		buf.WriteString(fmt.Sprintf(
			"resource %q %q",
			addr.Resource.Resource.Type,
			addr.Resource.Resource.Name,
		))
	case addrs.DataResourceMode:
		buf.WriteString(fmt.Sprintf(
			"data %q %q ",
			addr.Resource.Resource.Type,
			addr.Resource.Resource.Name,
		))
	default:
		// should never happen, since the above is exhaustive
		buf.WriteString(addr.String())
	}

	buf.WriteString(" {")

	p := blockBodyDiffPrinter{
		buf:             &buf,
		color:           color,
		action:          change.Action,
		requiredReplace: change.RequiredReplace,
		concise:         experiment.Enabled(experiment.X_concise_diff),
	}

	// Most commonly-used resources have nested blocks that result in us
	// going at least three traversals deep while we recurse here, so we'll
	// start with that much capacity and then grow as needed for deeper
	// structures.
	path := make(cty.Path, 0, 3)

	changeV, err := change.Decode(schema.ImpliedType())
	if err != nil {
		// Should never happen in here, since we've already been through
		// loads of layers of encode/decode of the planned changes before now.
		panic(fmt.Sprintf("failed to decode plan for %s while rendering diff: %s", addr, err))
	}

	// We currently have an opt-out that permits the legacy SDK to return values
	// that defy our usual conventions around handling of nesting blocks. To
	// avoid the rendering code from needing to handle all of these, we'll
	// normalize first.
	// (Ideally we'd do this as part of the SDK opt-out implementation in core,
	// but we've added it here for now to reduce risk of unexpected impacts
	// on other code in core.)
	changeV.Change.Before = objchange.NormalizeObjectFromLegacySDK(changeV.Change.Before, schema)
	changeV.Change.After = objchange.NormalizeObjectFromLegacySDK(changeV.Change.After, schema)

	// Now that the change is decoded, add back the marks at the defined paths
	if len(change.BeforeValMarks) > 0 {
		changeV.Change.Before = changeV.Change.Before.MarkWithPaths(change.BeforeValMarks)
	}
	if len(change.AfterValMarks) > 0 {
		changeV.Change.After = changeV.Change.After.MarkWithPaths(change.AfterValMarks)
	}

	bodyWritten := p.writeBlockBodyDiff(schema, changeV.Before, changeV.After, 6, path)
	if bodyWritten {
		buf.WriteString("\n")
		buf.WriteString(strings.Repeat(" ", 4))
	}
	buf.WriteString("}\n")
<commit_msg>Rebase fix<commit_after>package format

import (
	"bufio"
	"bytes"
	"fmt"
	"log"
	"sort"
	"strings"

	"github.com/mitchellh/colorstring"
	"github.com/zclconf/go-cty/cty"
	ctyjson "github.com/zclconf/go-cty/cty/json"

	"github.com/hashicorp/terraform/addrs"
	"github.com/hashicorp/terraform/configs/configschema"
	"github.com/hashicorp/terraform/helper/experiment"
	"github.com/hashicorp/terraform/plans"
	"github.com/hashicorp/terraform/plans/objchange"
	"github.com/hashicorp/terraform/states"
)

// ResourceChange returns a string representation of a change to a particular
// resource, for inclusion in user-facing plan output.
//
// The resource schema must be provided along with the change so that the
// formatted change can reflect the configuration structure for the associated
// resource.
//
// If "color" is non-nil, it will be used to color the result. Otherwise,
// no color codes will be included.
func ResourceChange(
	change *plans.ResourceInstanceChangeSrc,
	tainted bool,
	schema *configschema.Block,
	color *colorstring.Colorize,
) string {
	addr := change.Addr
	var buf bytes.Buffer

	if color == nil {
		color = &colorstring.Colorize{
			Colors:  colorstring.DefaultColors,
			Disable: true,
			Reset:   false,
		}
	}

	dispAddr := addr.String()
	if change.DeposedKey != states.NotDeposed {
		dispAddr = fmt.Sprintf("%s (deposed object %s)", dispAddr, change.DeposedKey)
	}

	switch change.Action {
	case plans.Create:
		buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] will be created", dispAddr)))
	case plans.Read:
		buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] will be read during apply\n  # (config refers to values not yet known)", dispAddr)))
	case plans.Update:
		buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] will be updated in-place", dispAddr)))
	case plans.CreateThenDelete, plans.DeleteThenCreate:
		if tainted {
			buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] is tainted, so must be [bold][red]replaced", dispAddr)))
		} else {
			buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] must be [bold][red]replaced", dispAddr)))
		}
	case plans.Delete:
		buf.WriteString(color.Color(fmt.Sprintf("[bold]  # %s[reset] will be [bold][red]destroyed", dispAddr)))
	default:
		// should never happen, since the above is exhaustive
		buf.WriteString(fmt.Sprintf("%s has an action the plan renderer doesn't support (this is a bug)", dispAddr))
	}
	buf.WriteString(color.Color("[reset]\n"))

	buf.WriteString(color.Color(DiffActionSymbol(change.Action)) + " ")

	switch addr.Resource.Resource.Mode {
	case addrs.ManagedResourceMode:
		buf.WriteString(fmt.Sprintf(
			"resource %q %q",
			addr.Resource.Resource.Type,
			addr.Resource.Resource.Name,
		))
	case addrs.DataResourceMode:
		buf.WriteString(fmt.Sprintf(
			"data %q %q ",
			addr.Resource.Resource.Type,
			addr.Resource.Resource.Name,
		))
	default:
		// should never happen, since the above is exhaustive
		buf.WriteString(addr.String())
	}

	buf.WriteString(" {")

	p := blockBodyDiffPrinter{
		buf:             &buf,
		color:           color,
		action:          change.Action,
		requiredReplace: change.RequiredReplace,
		concise:         experiment.Enabled(experiment.X_concise_diff),
	}

	// Most commonly-used resources have nested blocks that result in us
	// going at least three traversals deep while we recurse here, so we'll
	// start with that much capacity and then grow as needed for deeper
	// structures.
	path := make(cty.Path, 0, 3)

	changeV, err := change.Decode(schema.ImpliedType())
	if err != nil {
		// Should never happen in here, since we've already been through
		// loads of layers of encode/decode of the planned changes before now.
		panic(fmt.Sprintf("failed to decode plan for %s while rendering diff: %s", addr, err))
	}

	// We currently have an opt-out that permits the legacy SDK to return values
	// that defy our usual conventions around handling of nesting blocks. To
	// avoid the rendering code from needing to handle all of these, we'll
	// normalize first.
	// (Ideally we'd do this as part of the SDK opt-out implementation in core,
	// but we've added it here for now to reduce risk of unexpected impacts
	// on other code in core.)
	changeV.Change.Before = objchange.NormalizeObjectFromLegacySDK(changeV.Change.Before, schema)
	changeV.Change.After = objchange.NormalizeObjectFromLegacySDK(changeV.Change.After, schema)

	// Now that the change is decoded, add back the marks at the defined paths
	if len(change.BeforeValMarks) > 0 {
		changeV.Change.Before = changeV.Change.Before.MarkWithPaths(change.BeforeValMarks)
	}
	if len(change.AfterValMarks) > 0 {
		changeV.Change.After = changeV.Change.After.MarkWithPaths(change.AfterValMarks)
	}

	result := p.writeBlockBodyDiff(schema, changeV.Before, changeV.After, 6, path)
	if result.bodyWritten {
		buf.WriteString("\n")
		buf.WriteString(strings.Repeat(" ", 4))
	}
	buf.WriteString("}\n")

{'fraction_non_alphanumeric': 0.12050996660932915, 'fraction_numerical': 0.001214206212688455, 'mean_word_length': 4.097472924187725, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, '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': '5734071', 'n_tokens_mistral': 3325, 'n_tokens_neox': 3165, 'n_words': 879}