File: args.go

package info (click to toggle)
singularity-container 4.0.3%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 21,672 kB
  • sloc: asm: 3,857; sh: 2,125; ansic: 1,677; awk: 414; makefile: 110; python: 99
file content (101 lines) | stat: -rw-r--r-- 2,740 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Copyright (c) 2019-2023, Sylabs Inc. All rights reserved.
// Copyright (c) Contributors to the Apptainer project, established as
//   Apptainer a Series of LF Projects LLC.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.

package args

import (
	"bufio"
	"fmt"
	"os"
	"strings"

	"github.com/sylabs/singularity/v4/pkg/build/types"
	"github.com/sylabs/singularity/v4/pkg/sylog"
)

func ReadBuildArgs(args []string, argFile string) (map[string]string, error) {
	buildVarsMap := make(map[string]string)
	if argFile != "" {
		file, err := os.Open(argFile)
		if err != nil {
			return buildVarsMap, fmt.Errorf("error while opening file %q: %s", argFile, err)
		}
		defer file.Close()

		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			text := scanner.Text()
			k, v, err := getKeyVal(text)
			if err != nil {
				sylog.Warningf("Skipping %q in build arg file: %s", text, err)
				continue
			}

			buildVarsMap[k] = v
		}

		if err := scanner.Err(); err != nil {
			return buildVarsMap, fmt.Errorf("error reading build arg file %q: %s", argFile, err)
		}
	}

	for _, arg := range args {
		k, v, err := getKeyVal(arg)
		if err != nil {
			return nil, err
		}

		buildVarsMap[k] = v
	}

	return buildVarsMap, nil
}

// ReadDefaults reads in the '%arguments' section of (one build stage of) a
// definition file, and returns the default argument values specified in that
// section as a map. If file contained no '%arguments' section, an empty map is
// returned.
func ReadDefaults(def types.Definition) map[string]string {
	defaultArgsMap := make(map[string]string)
	if def.BuildData.Arguments.Script != "" {
		scanner := bufio.NewScanner(strings.NewReader(def.BuildData.Arguments.Script))
		for scanner.Scan() {
			text := strings.TrimSpace(scanner.Text())
			if text != "" && !strings.HasPrefix(text, "#") {
				k, v, err := getKeyVal(text)
				if err != nil {
					sylog.Warningf("Skipping %q in 'arguments' section: %s", text, err)
					continue
				}
				defaultArgsMap[k] = v
			}
		}
	}

	return defaultArgsMap
}

func getKeyVal(text string) (string, string, error) {
	if !strings.Contains(text, "=") {
		return "", "", fmt.Errorf("%q is not a key=value pair", text)
	}

	matches := strings.SplitN(text, "=", 2)
	if len(matches) != 2 {
		return "", "", fmt.Errorf("%q is not a key=value pair", text)
	}

	key := strings.TrimSpace(matches[0])
	if key == "" {
		return "", "", fmt.Errorf("missing key portion in %q", text)
	}
	val := strings.TrimSpace(matches[1])
	if val == "" {
		return "", "", fmt.Errorf("missing value portion in %q", text)
	}
	return key, val, nil
}