github.com/gitbundle/modules@v0.0.0-20231025071548-85b91c5c3b01/process/manager_exec.go (about)

     1  // Copyright 2023 The GitBundle Inc. All rights reserved.
     2  // Copyright 2017 The Gitea Authors. All rights reserved.
     3  // Use of this source code is governed by a MIT-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package process
     7  
     8  import (
     9  	"bytes"
    10  	"context"
    11  	"io"
    12  	"os/exec"
    13  	"time"
    14  )
    15  
    16  // Exec a command and use the default timeout.
    17  func (pm *Manager) Exec(desc, cmdName string, args ...string) (string, string, error) {
    18  	return pm.ExecDir(DefaultContext, -1, "", desc, cmdName, args...)
    19  }
    20  
    21  // ExecTimeout a command and use a specific timeout duration.
    22  func (pm *Manager) ExecTimeout(timeout time.Duration, desc, cmdName string, args ...string) (string, string, error) {
    23  	return pm.ExecDir(DefaultContext, timeout, "", desc, cmdName, args...)
    24  }
    25  
    26  // ExecDir a command and use the default timeout.
    27  func (pm *Manager) ExecDir(ctx context.Context, timeout time.Duration, dir, desc, cmdName string, args ...string) (string, string, error) {
    28  	return pm.ExecDirEnv(ctx, timeout, dir, desc, nil, cmdName, args...)
    29  }
    30  
    31  // ExecDirEnv runs a command in given path and environment variables, and waits for its completion
    32  // up to the given timeout (or DefaultTimeout if -1 is given).
    33  // Returns its complete stdout and stderr
    34  // outputs and an error, if any (including timeout)
    35  func (pm *Manager) ExecDirEnv(ctx context.Context, timeout time.Duration, dir, desc string, env []string, cmdName string, args ...string) (string, string, error) {
    36  	return pm.ExecDirEnvStdIn(ctx, timeout, dir, desc, env, nil, cmdName, args...)
    37  }
    38  
    39  // ExecDirEnvStdIn runs a command in given path and environment variables with provided stdIN, and waits for its completion
    40  // up to the given timeout (or DefaultTimeout if timeout <= 0 is given).
    41  // Returns its complete stdout and stderr
    42  // outputs and an error, if any (including timeout)
    43  func (pm *Manager) ExecDirEnvStdIn(ctx context.Context, timeout time.Duration, dir, desc string, env []string, stdIn io.Reader, cmdName string, args ...string) (string, string, error) {
    44  	if timeout <= 0 {
    45  		timeout = 60 * time.Second
    46  	}
    47  
    48  	stdOut := new(bytes.Buffer)
    49  	stdErr := new(bytes.Buffer)
    50  
    51  	ctx, _, finished := pm.AddContextTimeout(ctx, timeout, desc)
    52  	defer finished()
    53  
    54  	cmd := exec.CommandContext(ctx, cmdName, args...)
    55  	cmd.Dir = dir
    56  	cmd.Env = env
    57  	cmd.Stdout = stdOut
    58  	cmd.Stderr = stdErr
    59  	if stdIn != nil {
    60  		cmd.Stdin = stdIn
    61  	}
    62  	SetSysProcAttribute(cmd)
    63  
    64  	if err := cmd.Start(); err != nil {
    65  		return "", "", err
    66  	}
    67  
    68  	err := cmd.Wait()
    69  	if err != nil {
    70  		err = &Error{
    71  			PID:         GetPID(ctx),
    72  			Description: desc,
    73  			Err:         err,
    74  			CtxErr:      ctx.Err(),
    75  			Stdout:      stdOut.String(),
    76  			Stderr:      stdErr.String(),
    77  		}
    78  	}
    79  
    80  	return stdOut.String(), stdErr.String(), err
    81  }