github.com/golang/dep@v0.5.4/internal/importers/vndr/importer.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package vndr
     6  
     7  import (
     8  	"bufio"
     9  	"log"
    10  	"os"
    11  	"path/filepath"
    12  	"strings"
    13  
    14  	"github.com/golang/dep"
    15  	"github.com/golang/dep/gps"
    16  	"github.com/golang/dep/internal/importers/base"
    17  	"github.com/pkg/errors"
    18  )
    19  
    20  func vndrFile(dir string) string {
    21  	return filepath.Join(dir, "vendor.conf")
    22  }
    23  
    24  // Importer imports vndr configuration into the dep configuration format.
    25  type Importer struct {
    26  	*base.Importer
    27  	packages []vndrPackage
    28  }
    29  
    30  // NewImporter for vndr.
    31  func NewImporter(log *log.Logger, verbose bool, sm gps.SourceManager) *Importer {
    32  	return &Importer{Importer: base.NewImporter(log, verbose, sm)}
    33  }
    34  
    35  // Name of the importer.
    36  func (v *Importer) Name() string { return "vndr" }
    37  
    38  // HasDepMetadata checks if a directory contains config that the importer can handle.
    39  func (v *Importer) HasDepMetadata(dir string) bool {
    40  	_, err := os.Stat(vndrFile(dir))
    41  	return err == nil
    42  }
    43  
    44  // Import the config found in the directory.
    45  func (v *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) {
    46  	v.Logger.Println("Detected vndr configuration file...")
    47  
    48  	err := v.loadVndrFile(dir)
    49  	if err != nil {
    50  		return nil, nil, errors.Wrapf(err, "unable to load vndr file")
    51  	}
    52  
    53  	m, l := v.convert(pr)
    54  	return m, l, nil
    55  }
    56  
    57  func (v *Importer) loadVndrFile(dir string) error {
    58  	v.Logger.Printf("Converting from vendor.conf...")
    59  
    60  	path := vndrFile(dir)
    61  	f, err := os.Open(path)
    62  	if err != nil {
    63  		return errors.Wrapf(err, "unable to open %s", path)
    64  	}
    65  	defer f.Close()
    66  
    67  	scanner := bufio.NewScanner(f)
    68  	for scanner.Scan() {
    69  		pkg, err := parseVndrLine(scanner.Text())
    70  		if err != nil {
    71  			v.Logger.Printf("  Warning: Skipping line. Unable to parse: %s\n", err)
    72  			continue
    73  		}
    74  		if pkg == nil {
    75  			// Could be an empty line or one which is just a comment
    76  			continue
    77  		}
    78  		v.packages = append(v.packages, *pkg)
    79  	}
    80  
    81  	if err := scanner.Err(); err != nil {
    82  		v.Logger.Printf("  Warning: Ignoring errors found while parsing %s: %s\n", path, err)
    83  	}
    84  
    85  	return nil
    86  }
    87  
    88  func (v *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) {
    89  	packages := make([]base.ImportedPackage, 0, len(v.packages))
    90  	for _, pkg := range v.packages {
    91  		// Validate
    92  		if pkg.importPath == "" {
    93  			v.Logger.Println(
    94  				"  Warning: Skipping project. Invalid vndr configuration, import path is required",
    95  			)
    96  			continue
    97  		}
    98  
    99  		if pkg.reference == "" {
   100  			v.Logger.Printf(
   101  				"  Warning: Invalid vndr configuration, reference not found for import path %q\n",
   102  				pkg.importPath,
   103  			)
   104  		}
   105  
   106  		ip := base.ImportedPackage{
   107  			Name:     pkg.importPath,
   108  			Source:   pkg.repository,
   109  			LockHint: pkg.reference,
   110  		}
   111  		packages = append(packages, ip)
   112  	}
   113  	v.ImportPackages(packages, true)
   114  	return v.Manifest, v.Lock
   115  }
   116  
   117  type vndrPackage struct {
   118  	importPath string
   119  	reference  string
   120  	repository string
   121  }
   122  
   123  func parseVndrLine(line string) (*vndrPackage, error) {
   124  	commentIdx := strings.Index(line, "#")
   125  	if commentIdx >= 0 {
   126  		line = line[:commentIdx]
   127  	}
   128  	line = strings.TrimSpace(line)
   129  
   130  	if line == "" {
   131  		return nil, nil
   132  	}
   133  
   134  	parts := strings.Fields(line)
   135  
   136  	if !(len(parts) == 2 || len(parts) == 3) {
   137  		return nil, errors.Errorf("invalid config format: %q", line)
   138  	}
   139  
   140  	pkg := &vndrPackage{
   141  		importPath: parts[0],
   142  		reference:  parts[1],
   143  	}
   144  	if len(parts) == 3 {
   145  		pkg.repository = parts[2]
   146  	}
   147  
   148  	return pkg, nil
   149  }