| Index: go/src/infra/tools/cipd/pkgdef.go
|
| diff --git a/go/src/infra/tools/cipd/pkgdef.go b/go/src/infra/tools/cipd/pkgdef.go
|
| deleted file mode 100644
|
| index 847a6bd28dd2cc33b819da4a002940a456caf064..0000000000000000000000000000000000000000
|
| --- a/go/src/infra/tools/cipd/pkgdef.go
|
| +++ /dev/null
|
| @@ -1,261 +0,0 @@
|
| -// Copyright 2015 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package cipd
|
| -
|
| -import (
|
| - "fmt"
|
| - "io"
|
| - "io/ioutil"
|
| - "path/filepath"
|
| - "regexp"
|
| - "sort"
|
| -
|
| - "github.com/go-yaml/yaml"
|
| -)
|
| -
|
| -// PackageDef defines how exactly to build a package: what files to put into it,
|
| -// how to name them, how to name the package itself, etc. It is loaded from
|
| -// *.yaml file.
|
| -type PackageDef struct {
|
| - // Package defines a name of the package.
|
| - Package string
|
| - // Root defines where to search for files, relative to package file itself.
|
| - Root string
|
| - // Data describe what to add to the package.
|
| - Data []PackageChunkDef
|
| -}
|
| -
|
| -// PackageChunkDef represents one entry in 'data' section of package definition
|
| -// file. It is either a single file, or a recursively scanned directory (with
|
| -// optional list of regexps for files to skip).
|
| -type PackageChunkDef struct {
|
| - // Dir is a directory to add to the package (recursively).
|
| - Dir string
|
| - // File is a single file to add to the package.
|
| - File string
|
| - // Exclude is a list of glob patterns to exclude when scanning a directory.
|
| - Exclude []string
|
| -}
|
| -
|
| -// LoadPackageDef loads package definition from a YAML source code. In
|
| -// substitutes %{...} strings in the definition with corresponding values
|
| -// from 'vars' map.
|
| -func LoadPackageDef(r io.Reader, vars map[string]string) (out PackageDef, err error) {
|
| - data, err := ioutil.ReadAll(r)
|
| - if err != nil {
|
| - return
|
| - }
|
| - err = yaml.Unmarshal(data, &out)
|
| - if err != nil {
|
| - return
|
| - }
|
| -
|
| - // Substitute variables in all strings.
|
| - for _, str := range out.strings() {
|
| - *str, err = subVars(*str, vars)
|
| - if err != nil {
|
| - return
|
| - }
|
| - }
|
| -
|
| - // Validate package name right away.
|
| - err = ValidatePackageName(out.Package)
|
| - if err != nil {
|
| - return
|
| - }
|
| -
|
| - // Make sure "file" or "dir" are used, but not both.
|
| - for i, chunk := range out.Data {
|
| - if chunk.File == "" && chunk.Dir == "" {
|
| - return out, fmt.Errorf("files entry #%d needs 'file' or 'dir' key", i)
|
| - }
|
| - if chunk.File != "" && chunk.Dir != "" {
|
| - return out, fmt.Errorf("files entry #%d can't have both 'files' and 'dir' keys", i)
|
| - }
|
| - }
|
| -
|
| - // Default 'root' to a directory with the package def file.
|
| - if out.Root == "" {
|
| - out.Root = "."
|
| - }
|
| -
|
| - return
|
| -}
|
| -
|
| -// FindFiles scans files system and returns all files to be added to the
|
| -// package. It uses a path to package definition file directory ('cwd' argument)
|
| -// to find a root of the package.
|
| -func (def *PackageDef) FindFiles(cwd string) ([]File, error) {
|
| - // Root of the package is defined relative to package def YAML file.
|
| - absCwd, err := filepath.Abs(cwd)
|
| - if err != nil {
|
| - return nil, err
|
| - }
|
| - root := filepath.Clean(filepath.Join(absCwd, filepath.FromSlash(def.Root)))
|
| -
|
| - // Helper to get absolute path to a file given path relative to root.
|
| - makeAbs := func(p string) string {
|
| - return filepath.Join(root, filepath.FromSlash(p))
|
| - }
|
| -
|
| - // Used to skip duplicates.
|
| - seen := map[string]File{}
|
| - add := func(f File) {
|
| - if seen[f.Name()] == nil {
|
| - seen[f.Name()] = f
|
| - }
|
| - }
|
| -
|
| - log.Info("Enumerating files to zip...")
|
| - for _, chunk := range def.Data {
|
| - // Individual file.
|
| - if chunk.File != "" {
|
| - file, err := WrapFile(makeAbs(chunk.File), root, nil)
|
| - if err != nil {
|
| - return nil, err
|
| - }
|
| - add(file)
|
| - continue
|
| - }
|
| -
|
| - // A subdirectory to scan (with filtering).
|
| - if chunk.Dir != "" {
|
| - // Absolute path to directory to scan.
|
| - startDir := makeAbs(chunk.Dir)
|
| - // Exclude files as specified in 'exclude' section.
|
| - exclude, err := makeExclusionFilter(startDir, chunk.Exclude)
|
| - if err != nil {
|
| - return nil, err
|
| - }
|
| - // Run the scan.
|
| - files, err := ScanFileSystem(startDir, root, exclude)
|
| - if err != nil {
|
| - return nil, err
|
| - }
|
| - for _, f := range files {
|
| - add(f)
|
| - }
|
| - continue
|
| - }
|
| -
|
| - // LoadPackageDef does validation, so this should not happen.
|
| - return nil, fmt.Errorf("Unexpected definition: %v", chunk)
|
| - }
|
| -
|
| - // Sort by Name().
|
| - names := make([]string, 0, len(seen))
|
| - for n := range seen {
|
| - names = append(names, n)
|
| - }
|
| - sort.Strings(names)
|
| -
|
| - // Final sorted array of File.
|
| - out := make([]File, 0, len(names))
|
| - for _, n := range names {
|
| - out = append(out, seen[n])
|
| - }
|
| - return out, nil
|
| -}
|
| -
|
| -// makeExclusionFilter produces a predicate that checks an absolute file path
|
| -// against a list of regexps (defined against slash separated paths relative to
|
| -// 'startDir'). The predicate takes absolute native path, converts it to slash
|
| -// separated path relative to 'startDir' and checks against list of regexps in
|
| -// 'patterns'. Returns true on match.
|
| -func makeExclusionFilter(startDir string, patterns []string) (ScanFilter, error) {
|
| - if len(patterns) == 0 {
|
| - return nil, nil
|
| - }
|
| -
|
| - // Compile regular expressions.
|
| - exps := []*regexp.Regexp{}
|
| - for _, expr := range patterns {
|
| - if expr == "" {
|
| - continue
|
| - }
|
| - if expr[0] != '^' {
|
| - expr = "^" + expr
|
| - }
|
| - if expr[len(expr)-1] != '$' {
|
| - expr = expr + "$"
|
| - }
|
| - re, err := regexp.Compile(expr)
|
| - if err != nil {
|
| - return nil, err
|
| - }
|
| - exps = append(exps, re)
|
| - }
|
| -
|
| - return func(abs string) bool {
|
| - rel, err := filepath.Rel(startDir, abs)
|
| - if err != nil {
|
| - log.Warnf("Unexpected error when evaluating %s: %s", abs, err)
|
| - return true
|
| - }
|
| - // Do not evaluate paths outside of startDir.
|
| - rel = filepath.ToSlash(rel)
|
| - if rel[:3] == "../" {
|
| - return false
|
| - }
|
| - for _, exp := range exps {
|
| - if exp.MatchString(rel) {
|
| - return true
|
| - }
|
| - }
|
| - return false
|
| - }, nil
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -// Variable substitution.
|
| -
|
| -var subVarsRe = regexp.MustCompile(`\$\{[^\}]+\}`)
|
| -
|
| -// strings return array of pointers to all strings in PackageDef that can
|
| -// contain ${var} variables.
|
| -func (def *PackageDef) strings() []*string {
|
| - out := []*string{
|
| - &def.Package,
|
| - &def.Root,
|
| - }
|
| - // Important to use index here, to get a point to a real object, not its copy.
|
| - for i := range def.Data {
|
| - out = append(out, def.Data[i].strings()...)
|
| - }
|
| - return out
|
| -}
|
| -
|
| -// strings return array of pointers to all strings in PackageChunkDef that can
|
| -// contain ${var} variables.
|
| -func (def *PackageChunkDef) strings() []*string {
|
| - out := []*string{
|
| - &def.Dir,
|
| - &def.File,
|
| - }
|
| - for i := range def.Exclude {
|
| - out = append(out, &def.Exclude[i])
|
| - }
|
| - return out
|
| -}
|
| -
|
| -// subVars replaces "${key}" in strings with values from 'vars' map. Returns
|
| -// error if some keys weren't found in 'vars' map.
|
| -func subVars(s string, vars map[string]string) (string, error) {
|
| - badKeys := []string{}
|
| - res := subVarsRe.ReplaceAllStringFunc(s, func(match string) string {
|
| - // Strip '${' and '}'.
|
| - key := match[2 : len(match)-1]
|
| - val, ok := vars[key]
|
| - if !ok {
|
| - badKeys = append(badKeys, key)
|
| - return match
|
| - }
|
| - return val
|
| - })
|
| - if len(badKeys) != 0 {
|
| - return res, fmt.Errorf("Values for some variables are not provided: %v", badKeys)
|
| - }
|
| - return res, nil
|
| -}
|
|
|