github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/runbits/buildscript/buildscript.go (about)

     1  package buildscript
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"path/filepath"
     7  
     8  	"github.com/ActiveState/cli/internal/constants"
     9  	"github.com/ActiveState/cli/internal/errs"
    10  	"github.com/ActiveState/cli/internal/fileutils"
    11  	"github.com/ActiveState/cli/internal/locale"
    12  	"github.com/ActiveState/cli/pkg/platform/runtime/buildscript"
    13  	"github.com/ActiveState/cli/pkg/project"
    14  	"github.com/sergi/go-diff/diffmatchpatch"
    15  )
    16  
    17  func generateDiff(script *buildscript.Script, otherScript *buildscript.Script) (string, error) {
    18  	local := locale.Tl("diff_local", "local")
    19  	remote := locale.Tl("diff_remote", "remote")
    20  
    21  	var result bytes.Buffer
    22  
    23  	diff := diffmatchpatch.New()
    24  	scriptLines, newScriptLines, lines := diff.DiffLinesToChars(script.String(), otherScript.String())
    25  	hunks := diff.DiffMain(scriptLines, newScriptLines, false)
    26  	hunks = diff.DiffCharsToLines(hunks, lines)
    27  	hunks = diff.DiffCleanupSemantic(hunks)
    28  	for i := 0; i < len(hunks); i++ {
    29  		switch hunk := hunks[i]; hunk.Type {
    30  		case diffmatchpatch.DiffEqual:
    31  			result.WriteString(hunk.Text)
    32  		case diffmatchpatch.DiffDelete:
    33  			result.WriteString(fmt.Sprintf("<<<<<<< %s\n", local))
    34  			result.WriteString(hunk.Text)
    35  			result.WriteString("=======\n")
    36  			if i+1 < len(hunks) && hunks[i+1].Type == diffmatchpatch.DiffInsert {
    37  				result.WriteString(hunks[i+1].Text)
    38  				i++ // do not process this hunk again
    39  			}
    40  			result.WriteString(fmt.Sprintf(">>>>>>> %s\n", remote))
    41  		case diffmatchpatch.DiffInsert:
    42  			result.WriteString(fmt.Sprintf("<<<<<<< %s\n", local))
    43  			result.WriteString("=======\n")
    44  			result.WriteString(hunk.Text)
    45  			result.WriteString(fmt.Sprintf(">>>>>>> %s\n", remote))
    46  		}
    47  	}
    48  
    49  	return result.String(), nil
    50  }
    51  
    52  func GenerateAndWriteDiff(proj *project.Project, script *buildscript.Script, otherScript *buildscript.Script) error {
    53  	result, err := generateDiff(script, otherScript)
    54  	if err != nil {
    55  		return errs.Wrap(err, "Could not generate diff between local and remote build scripts")
    56  	}
    57  	return fileutils.WriteFile(filepath.Join(proj.Dir(), constants.BuildScriptFileName), []byte(result))
    58  }