1package common
2
3import (
4	"fmt"
5
6	"github.com/sirupsen/logrus"
7
8	"gitlab.com/gitlab-org/gitlab-runner/helpers"
9)
10
11type ShellConfiguration struct {
12	Environment   []string
13	DockerCommand []string
14	Command       string
15	Arguments     []string
16	PassFile      bool
17	Extension     string
18}
19
20type ShellType int
21
22const (
23	NormalShell ShellType = iota
24	LoginShell
25)
26
27func (s *ShellConfiguration) GetCommandWithArguments() []string {
28	parts := []string{s.Command}
29	parts = append(parts, s.Arguments...)
30	return parts
31}
32
33func (s *ShellConfiguration) String() string {
34	return helpers.ToYAML(s)
35}
36
37type ShellScriptInfo struct {
38	Shell           string
39	Build           *Build
40	Type            ShellType
41	User            string
42	RunnerCommand   string
43	PreCloneScript  string
44	PreBuildScript  string
45	PostBuildScript string
46}
47
48type Shell interface {
49	GetName() string
50	GetFeatures(features *FeaturesInfo)
51	IsDefault() bool
52
53	GetConfiguration(info ShellScriptInfo) (*ShellConfiguration, error)
54	GenerateScript(buildStage BuildStage, info ShellScriptInfo) (string, error)
55}
56
57var shells map[string]Shell
58
59func RegisterShell(shell Shell) {
60	logrus.Debugln("Registering", shell.GetName(), "shell...")
61
62	if shells == nil {
63		shells = make(map[string]Shell)
64	}
65	if shells[shell.GetName()] != nil {
66		panic("Shell already exist: " + shell.GetName())
67	}
68	shells[shell.GetName()] = shell
69}
70
71func GetShell(shell string) Shell {
72	if shells == nil {
73		return nil
74	}
75
76	return shells[shell]
77}
78
79func GetShellConfiguration(info ShellScriptInfo) (*ShellConfiguration, error) {
80	shell := GetShell(info.Shell)
81	if shell == nil {
82		return nil, fmt.Errorf("shell %s not found", info.Shell)
83	}
84
85	return shell.GetConfiguration(info)
86}
87
88func GenerateShellScript(buildStage BuildStage, info ShellScriptInfo) (string, error) {
89	shell := GetShell(info.Shell)
90	if shell == nil {
91		return "", fmt.Errorf("shell %s not found", info.Shell)
92	}
93
94	return shell.GenerateScript(buildStage, info)
95}
96
97func GetDefaultShell() string {
98	if shells == nil {
99		panic("no shells defined")
100	}
101
102	for _, shell := range shells {
103		if shell.IsDefault() {
104			return shell.GetName()
105		}
106	}
107	panic("no default shell defined")
108}
109