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