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 }