github.com/docker-library/go-dockerlibrary@v0.0.0-20200821205225-669fbe5c1d52/manifest/line-based.go (about)

     1  package manifest
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"strings"
     8  )
     9  
    10  const DefaultLineBasedFetch = "refs/heads/*" // backwards compatibility
    11  
    12  // TODO write more of a proper parser? (probably not worthwhile given that 2822 is the preferred format)
    13  func ParseLineBasedLine(line string, defaults Manifest2822Entry) (*Manifest2822Entry, error) {
    14  	entry := defaults.Clone()
    15  
    16  	parts := strings.SplitN(line, ":", 2)
    17  	if len(parts) < 2 {
    18  		return nil, fmt.Errorf("manifest line missing ':': %s", line)
    19  	}
    20  	entry.Tags = []string{strings.TrimSpace(parts[0])}
    21  
    22  	parts = strings.SplitN(parts[1], "@", 2)
    23  	if len(parts) < 2 {
    24  		return nil, fmt.Errorf("manifest line missing '@': %s", line)
    25  	}
    26  	entry.GitRepo = strings.TrimSpace(parts[0])
    27  
    28  	parts = strings.SplitN(parts[1], " ", 2)
    29  	entry.GitCommit = strings.TrimSpace(parts[0])
    30  	if len(parts) > 1 {
    31  		entry.Directory = strings.TrimSpace(parts[1])
    32  	}
    33  
    34  	if entry.GitFetch == DefaultLineBasedFetch && !GitCommitRegex.MatchString(entry.GitCommit) {
    35  		// doesn't look like a commit, must be a tag
    36  		entry.GitFetch = "refs/tags/" + entry.GitCommit
    37  		entry.GitCommit = "FETCH_HEAD"
    38  	}
    39  
    40  	return &entry, nil
    41  }
    42  
    43  func ParseLineBased(readerIn io.Reader) (*Manifest2822, error) {
    44  	reader := bufio.NewReader(readerIn)
    45  
    46  	manifest := &Manifest2822{
    47  		Global: DefaultManifestEntry.Clone(),
    48  	}
    49  	manifest.Global.GitFetch = DefaultLineBasedFetch
    50  
    51  	for {
    52  		line, err := reader.ReadString('\n')
    53  
    54  		line = strings.TrimSpace(line)
    55  		if len(line) > 0 {
    56  			if line[0] == '#' {
    57  				maintainerLine := strings.TrimPrefix(line, "# maintainer: ")
    58  				if line != maintainerLine {
    59  					// if the prefix was removed, it must be a maintainer line!
    60  					manifest.Global.Maintainers = append(manifest.Global.Maintainers, maintainerLine)
    61  				}
    62  			} else {
    63  				entry, parseErr := ParseLineBasedLine(line, manifest.Global)
    64  				if parseErr != nil {
    65  					return nil, parseErr
    66  				}
    67  
    68  				err = manifest.AddEntry(*entry)
    69  				if err != nil {
    70  					return nil, err
    71  				}
    72  			}
    73  		}
    74  
    75  		if err == io.EOF {
    76  			break
    77  		}
    78  		if err != nil {
    79  			return nil, err
    80  		}
    81  	}
    82  
    83  	if len(manifest.Global.Maintainers) < 1 {
    84  		return nil, fmt.Errorf("missing Maintainers")
    85  	}
    86  	if invalidMaintainers := manifest.Global.InvalidMaintainers(); len(invalidMaintainers) > 0 {
    87  		return nil, fmt.Errorf("invalid Maintainers: %q (expected format %q)", strings.Join(invalidMaintainers, ", "), MaintainersFormat)
    88  	}
    89  
    90  	return manifest, nil
    91  }