xref: /aosp_15_r20/tools/treble/build/treble_build/local/cmd.go (revision 105f628577ac4ba0e277a494fbb614ed8c12a994)
1*105f6285SAndroid Build Coastguard Worker// Copyright 2022 The Android Open Source Project
2*105f6285SAndroid Build Coastguard Worker//
3*105f6285SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*105f6285SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*105f6285SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*105f6285SAndroid Build Coastguard Worker//
7*105f6285SAndroid Build Coastguard Worker//      http://www.apache.org/licenses/LICENSE-2.0
8*105f6285SAndroid Build Coastguard Worker//
9*105f6285SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*105f6285SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*105f6285SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*105f6285SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*105f6285SAndroid Build Coastguard Worker// limitations under the License.
14*105f6285SAndroid Build Coastguard Worker
15*105f6285SAndroid Build Coastguard Workerpackage local
16*105f6285SAndroid Build Coastguard Worker
17*105f6285SAndroid Build Coastguard Workerimport (
18*105f6285SAndroid Build Coastguard Worker	"bufio"
19*105f6285SAndroid Build Coastguard Worker	"bytes"
20*105f6285SAndroid Build Coastguard Worker	"context"
21*105f6285SAndroid Build Coastguard Worker	"errors"
22*105f6285SAndroid Build Coastguard Worker	"io"
23*105f6285SAndroid Build Coastguard Worker	"os/exec"
24*105f6285SAndroid Build Coastguard Worker	"time"
25*105f6285SAndroid Build Coastguard Worker)
26*105f6285SAndroid Build Coastguard Worker
27*105f6285SAndroid Build Coastguard Worker// Run the input command via pipe with given arguments, stdout of the pipe is passed to input parser
28*105f6285SAndroid Build Coastguard Worker// argument.
29*105f6285SAndroid Build Coastguard Workerfunc runPipe(ctx context.Context, timeout time.Duration, cmdName string, args []string, parser func(r io.Reader)) (err error, stdErr string) {
30*105f6285SAndroid Build Coastguard Worker	ctx, cancel := context.WithTimeout(ctx, timeout)
31*105f6285SAndroid Build Coastguard Worker	defer cancel()
32*105f6285SAndroid Build Coastguard Worker
33*105f6285SAndroid Build Coastguard Worker	cmd := exec.CommandContext(ctx, cmdName, args[0:]...)
34*105f6285SAndroid Build Coastguard Worker	errorBuf := bytes.Buffer{}
35*105f6285SAndroid Build Coastguard Worker	cmd.Stderr = &errorBuf
36*105f6285SAndroid Build Coastguard Worker	stdout, err := cmd.StdoutPipe()
37*105f6285SAndroid Build Coastguard Worker	if err != nil {
38*105f6285SAndroid Build Coastguard Worker		return err, errorBuf.String()
39*105f6285SAndroid Build Coastguard Worker	}
40*105f6285SAndroid Build Coastguard Worker
41*105f6285SAndroid Build Coastguard Worker	if err = cmd.Start(); err != nil {
42*105f6285SAndroid Build Coastguard Worker		return err, errorBuf.String()
43*105f6285SAndroid Build Coastguard Worker	}
44*105f6285SAndroid Build Coastguard Worker	parser(stdout)
45*105f6285SAndroid Build Coastguard Worker	if err = cmd.Wait(); err != nil {
46*105f6285SAndroid Build Coastguard Worker		return err, errorBuf.String()
47*105f6285SAndroid Build Coastguard Worker	}
48*105f6285SAndroid Build Coastguard Worker	return nil, ""
49*105f6285SAndroid Build Coastguard Worker}
50*105f6285SAndroid Build Coastguard Worker
51*105f6285SAndroid Build Coastguard Worker// Run input command, stdout is passed via out parameter to user, if error the stderr is provided via
52*105f6285SAndroid Build Coastguard Worker// stdErr string to the user.
53*105f6285SAndroid Build Coastguard Workerfunc run(ctx context.Context, timeout time.Duration, cmdName string, args []string) (out *bytes.Buffer, err error, stdErr string) {
54*105f6285SAndroid Build Coastguard Worker	ctx, cancel := context.WithTimeout(ctx, timeout)
55*105f6285SAndroid Build Coastguard Worker	defer cancel()
56*105f6285SAndroid Build Coastguard Worker
57*105f6285SAndroid Build Coastguard Worker	cmd := exec.CommandContext(ctx, cmdName, args[0:]...)
58*105f6285SAndroid Build Coastguard Worker	errorBuf := bytes.Buffer{}
59*105f6285SAndroid Build Coastguard Worker	outputBuf := bytes.Buffer{}
60*105f6285SAndroid Build Coastguard Worker	cmd.Stderr = &errorBuf
61*105f6285SAndroid Build Coastguard Worker	cmd.Stdout = &outputBuf
62*105f6285SAndroid Build Coastguard Worker	if err = cmd.Run(); err != nil {
63*105f6285SAndroid Build Coastguard Worker		return nil, err, errorBuf.String()
64*105f6285SAndroid Build Coastguard Worker	}
65*105f6285SAndroid Build Coastguard Worker
66*105f6285SAndroid Build Coastguard Worker	return &outputBuf, nil, ""
67*105f6285SAndroid Build Coastguard Worker}
68*105f6285SAndroid Build Coastguard Worker
69*105f6285SAndroid Build Coastguard Worker// lineScanner
70*105f6285SAndroid Build Coastguard Worker//
71*105f6285SAndroid Build Coastguard Worker//  Map output lines to strings, with expected number of
72*105f6285SAndroid Build Coastguard Worker// lines
73*105f6285SAndroid Build Coastguard Workertype lineScanner struct {
74*105f6285SAndroid Build Coastguard Worker	Lines []string
75*105f6285SAndroid Build Coastguard Worker}
76*105f6285SAndroid Build Coastguard Worker
77*105f6285SAndroid Build Coastguard Worker// Parse into lines
78*105f6285SAndroid Build Coastguard Workerfunc (l *lineScanner) Parse(s *bufio.Scanner) error {
79*105f6285SAndroid Build Coastguard Worker	i := 0
80*105f6285SAndroid Build Coastguard Worker	for s.Scan() {
81*105f6285SAndroid Build Coastguard Worker		if i < len(l.Lines) {
82*105f6285SAndroid Build Coastguard Worker			l.Lines[i] = s.Text()
83*105f6285SAndroid Build Coastguard Worker		} else {
84*105f6285SAndroid Build Coastguard Worker			i++
85*105f6285SAndroid Build Coastguard Worker			break
86*105f6285SAndroid Build Coastguard Worker		}
87*105f6285SAndroid Build Coastguard Worker		i++
88*105f6285SAndroid Build Coastguard Worker	}
89*105f6285SAndroid Build Coastguard Worker	if i != len(l.Lines) {
90*105f6285SAndroid Build Coastguard Worker		return errors.New("cmd: incorrect number of lines")
91*105f6285SAndroid Build Coastguard Worker	}
92*105f6285SAndroid Build Coastguard Worker	return nil
93*105f6285SAndroid Build Coastguard Worker}
94*105f6285SAndroid Build Coastguard Worker
95*105f6285SAndroid Build Coastguard Workerfunc newLineScanner(numLines int) *lineScanner {
96*105f6285SAndroid Build Coastguard Worker	out := &lineScanner{Lines: make([]string, numLines)}
97*105f6285SAndroid Build Coastguard Worker	return (out)
98*105f6285SAndroid Build Coastguard Worker}
99