<commit_before>package msi

import (
	"fmt"
	"strings"

	"github.com/go-errors/errors"
	"github.com/itchio/butler/cmd/msi"
	"github.com/itchio/butler/comm"
	"github.com/itchio/butler/installer"
	"github.com/itchio/butler/installer/bfs"
)

func (m *Manager) Install(params *installer.InstallParams) (*installer.InstallResult, error) {
	consumer := params.Consumer

	// we need the installer on disk to run it. this'll err if it's not,
	// and the caller is in charge of downloading it and calling us again.
	f, err := installer.AsLocalFile(params.File)
	if err != nil {
		return nil, errors.Wrap(err, 0)
	}

	angelParams := &bfs.SaveAngelsParams{
		Consumer: consumer,
		Folder:   params.InstallFolderPath,
		Receipt:  params.ReceiptIn,
	}

	cancel := make(chan struct{})
	defer close(cancel)
	bfs.StartAsymptoticProgress(consumer, cancel)

	var msiProductCode string

	angelResult, err := bfs.SaveAngels(angelParams, func() error {
		infoRes, err := msi.Info(consumer, f.Name())
		if err != nil {
			return errors.Wrap(err, 0)
		}

		msiProductCode = infoRes.ProductCode

		var msiErrors []msi.MSIWindowsInstallerError

		onError := func(me msi.MSIWindowsInstallerError) {
			msiErrors = append(msiErrors, me)
		}

		err = msi.Install(consumer, f.Name(), "", params.InstallFolderPath, onError)
		if err != nil {
			comm.Warnf("MSI installation failed: %s", err.Error())

			for _, me := range msiErrors {
				comm.Warnf("MSI error %d: %s", me.Code, me.Text)
			}

			// try to make a nice error:
			if len(msiErrors) > 0 {
				var errorStrings []string
				for _, me := range msiErrors {
					errorStrings = append(errorStrings, fmt.Sprintf("%d: %s", me.Code, me.Text))
				}
				return fmt.Errorf("MSI installation failed: %s", strings.Join(errorStrings, ", "))
			}
			return fmt.Errorf("MSI installation failed: %s", err.Error())
		}
<commit_msg>better MSI error formatting<commit_after>package msi

import (
	"fmt"
	"strings"

	"github.com/go-errors/errors"
	"github.com/itchio/butler/cmd/msi"
	"github.com/itchio/butler/comm"
	"github.com/itchio/butler/installer"
	"github.com/itchio/butler/installer/bfs"
)

func (m *Manager) Install(params *installer.InstallParams) (*installer.InstallResult, error) {
	consumer := params.Consumer

	// we need the installer on disk to run it. this'll err if it's not,
	// and the caller is in charge of downloading it and calling us again.
	f, err := installer.AsLocalFile(params.File)
	if err != nil {
		return nil, errors.Wrap(err, 0)
	}

	angelParams := &bfs.SaveAngelsParams{
		Consumer: consumer,
		Folder:   params.InstallFolderPath,
		Receipt:  params.ReceiptIn,
	}

	cancel := make(chan struct{})
	defer close(cancel)
	bfs.StartAsymptoticProgress(consumer, cancel)

	var msiProductCode string

	angelResult, err := bfs.SaveAngels(angelParams, func() error {
		infoRes, err := msi.Info(consumer, f.Name())
		if err != nil {
			return errors.Wrap(err, 0)
		}

		msiProductCode = infoRes.ProductCode

		var msiErrors []msi.MSIWindowsInstallerError

		onError := func(me msi.MSIWindowsInstallerError) {
			msiErrors = append(msiErrors, me)
		}

		err = msi.Install(consumer, f.Name(), "", params.InstallFolderPath, onError)
		if err != nil {
			comm.Warnf("MSI installation failed: %s", err.Error())

			for _, me := range msiErrors {
				comm.Warnf(me.Text)
			}

			// try to make a nice error:
			if len(msiErrors) > 0 {
				var errorStrings []string
				for _, me := range msiErrors {
					errorStrings = append(errorStrings, me.Text)
				}
				return fmt.Errorf("MSI installation failed:\n%s", strings.Join(errorStrings, "\n"))
			}
			return fmt.Errorf("MSI installation failed: %s", err.Error())
		}

{'fraction_non_alphanumeric': 0.13417305585980285, 'fraction_numerical': 0.0016429353778751369, 'mean_word_length': 3.851261620185923, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4406110', 'n_tokens_mistral': 1416, 'n_tokens_neox': 1261, 'n_words': 309}