File: util.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 (82 lines) | stat: -rw-r--r-- 2,649 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
// Copyright (c) 2018-2020, Sylabs Inc. All rights reserved.
// 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 shub

import (
	"errors"
	"regexp"
	"strings"
)

// isShubPullRef returns true if the provided string is a valid Shub
// reference for a pull operation.
func isShubPullRef(shubRef string) bool {
	// define regex for each URI component
	registryRegexp := `([-.a-zA-Z0-9/]{1,64}\/)?`           // target is very open, outside registry
	nameRegexp := `([-a-zA-Z0-9]{1,39}\/)`                  // target valid github usernames
	containerRegexp := `([-_.a-zA-Z0-9]{1,64})`             // target valid github repo names
	tagRegexp := `(:[-_.a-zA-Z0-9]{1,64})?`                 // target is very open, file extensions or branch names
	digestRegexp := `((\@[a-f0-9]{32})|(\@[a-f0-9]{40}))?$` // target file md5 has, git commit hash, git branch

	// expression is anchored
	shubRegex, err := regexp.Compile(`^(shub://)` + registryRegexp + nameRegexp + containerRegexp + tagRegexp + digestRegexp + `$`)
	if err != nil {
		return false
	}

	found := shubRegex.FindString(shubRef)

	// sanity check
	// if found string is not equal to the input, input isn't a valid URI
	return shubRef == found
}

// ParseReference accepts a valid Shub reference string and parses its content
// It will return an error if the given URI is not valid,
// otherwise it will parse the contents into a URI struct
func ParseReference(src string) (URI, error) {
	uri := URI{}

	ShubRef := strings.TrimPrefix(src, "shub://")
	refParts := strings.Split(ShubRef, "/")

	if l := len(refParts); l > 2 {
		// more than two pieces indicates a custom registry
		uri.registry = strings.Join(refParts[:l-2], "/") + shubAPIRoute
		uri.user = refParts[l-2]
		src = refParts[l-1]
	} else if l == 2 {
		// two pieces means default registry
		uri.registry = defaultRegistry + shubAPIRoute
		uri.user = refParts[l-2]
		src = refParts[l-1]
	} else if l < 2 {
		return URI{}, errors.New("not a valid Shub reference")
	}

	// look for an @ and split if it exists
	if strings.Contains(src, `@`) {
		refParts = strings.Split(src, `@`)
		uri.digest = `@` + refParts[1]
		src = refParts[0]
	}

	// look for a : and split if it exists
	if strings.Contains(src, `:`) {
		refParts = strings.Split(src, `:`)
		uri.tag = `:` + refParts[1]
		src = refParts[0]
	}

	// container name is left over after other parts are split from it
	uri.container = src

	if uri.tag == "" && uri.digest == "" {
		uri.tag = ":latest"
	}

	return uri, nil
}