Skip to content

fix: redirect postinstall script output to runtime output #2090

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Mar 10, 2023
4 changes: 4 additions & 0 deletions arduino/cores/packagemanager/install_uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package packagemanager
import (
"encoding/json"
"fmt"
"os"
"runtime"

"github.com/arduino/arduino-cli/arduino"
Expand Down Expand Up @@ -237,6 +238,9 @@ func (pme *Explorer) RunPostInstallScript(installDir *paths.Path) error {
if err != nil {
return err
}
cmd.RedirectStdoutTo(os.Stdout)
cmd.RedirectStderrTo(os.Stderr)

cmd.SetDirFromPath(installDir)
if err := cmd.Run(); err != nil {
return err
Expand Down
72 changes: 72 additions & 0 deletions arduino/cores/packagemanager/package_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ package packagemanager_test

import (
"fmt"
"io"
"net/url"
"os"
"runtime"
"strings"
"sync"
"testing"

"github.com/arduino/arduino-cli/arduino/cores"
Expand Down Expand Up @@ -639,3 +643,71 @@ func TestLegacyPackageConversionToPluggableDiscovery(t *testing.T) {
require.Equal(t, `"{network_cmd}" -address {upload.port.address} -port {upload.port.properties.port} -sketch "{build.path}/{build.project_name}.hex" -upload {upload.port.properties.endpoint_upload} -sync {upload.port.properties.endpoint_sync} -reset {upload.port.properties.endpoint_reset} -sync_exp {upload.port.properties.sync_return}`, platformProps.Get("tools.avrdude__pluggable_network.upload.pattern"))
}
}

func TestRunPostInstall(t *testing.T) {
pmb := packagemanager.NewBuilder(nil, nil, nil, nil, "test")
pm := pmb.Build()
pme, release := pm.NewExplorer()
defer release()

// prepare dummy post install script
dir := paths.New(t.TempDir())

// check that the script output is redirected to the current process
// standard one
outputR, outputW, err := os.Pipe()
require.NoError(t, err)
errorR, errorW, err := os.Pipe()
require.NoError(t, err)

prevStdout, prevStderr := os.Stdout, os.Stderr

var stdout []byte
var stderr []byte
wg := sync.WaitGroup{}
wg.Add(2)

go func() {
defer wg.Done()
var err error
stdout, err = io.ReadAll(outputR)
require.NoError(t, err)
}()

go func() {
defer wg.Done()
var err error
stderr, err = io.ReadAll(errorR)
require.NoError(t, err)
}()
var scriptPath *paths.Path
if runtime.GOOS == "windows" {
scriptPath = dir.Join("post_install.bat")

err = scriptPath.WriteFile([]byte(
`@echo off
echo sent in stdout
echo sent in stderr 1>&2`))
} else {
scriptPath = dir.Join("post_install.sh")
err = scriptPath.WriteFile([]byte(
`#!/bin/sh
echo "sent in stdout"
echo "sent in stderr" 1>&2`))
}
require.NoError(t, err)
err = os.Chmod(scriptPath.String(), 0777)
require.NoError(t, err)
os.Stdout = outputW
os.Stderr = errorW
pme.RunPostInstallScript(dir)

outputW.Close()
errorW.Close()
wg.Wait()
os.Stdout = prevStdout
os.Stderr = prevStderr

require.True(t, strings.HasPrefix(string(stdout), "sent in stdout"), "Unexpected stdout %s", string(stdout))
require.True(t, strings.HasPrefix(string(stderr), "sent in stderr"), "Unexpected stdout %s", string(stderr))
}