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

     1  // Copyright 2016 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 glock
     6  
     7  import (
     8  	"bufio"
     9  	"fmt"
    10  	"log"
    11  	"os"
    12  	"path/filepath"
    13  	"strings"
    14  
    15  	"github.com/golang/dep"
    16  	"github.com/golang/dep/gps"
    17  	"github.com/golang/dep/internal/importers/base"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  const glockfile = "GLOCKFILE"
    22  
    23  // Importer imports glock configuration into the dep configuration format.
    24  type Importer struct {
    25  	*base.Importer
    26  
    27  	packages []glockPackage
    28  }
    29  
    30  // NewImporter for glock.
    31  func NewImporter(logger *log.Logger, verbose bool, sm gps.SourceManager) *Importer {
    32  	return &Importer{Importer: base.NewImporter(logger, verbose, sm)}
    33  }
    34  
    35  // Name of the importer.
    36  func (g *Importer) Name() string {
    37  	return "glock"
    38  }
    39  
    40  // HasDepMetadata checks if a directory contains config that the importer can handle.
    41  func (g *Importer) HasDepMetadata(dir string) bool {
    42  	path := filepath.Join(dir, glockfile)
    43  	if _, err := os.Stat(path); err != nil {
    44  		return false
    45  	}
    46  
    47  	return true
    48  }
    49  
    50  // Import the config found in the directory.
    51  func (g *Importer) Import(dir string, pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock, error) {
    52  	err := g.load(dir)
    53  	if err != nil {
    54  		return nil, nil, err
    55  	}
    56  
    57  	m, l := g.convert(pr)
    58  	return m, l, nil
    59  }
    60  
    61  type glockPackage struct {
    62  	importPath string
    63  	revision   string
    64  }
    65  
    66  func (g *Importer) load(projectDir string) error {
    67  	g.Logger.Println("Detected glock configuration files...")
    68  	path := filepath.Join(projectDir, glockfile)
    69  	if g.Verbose {
    70  		g.Logger.Printf("  Loading %s", path)
    71  	}
    72  
    73  	f, err := os.Open(path)
    74  	if err != nil {
    75  		return errors.Wrapf(err, "unable to open %s", path)
    76  	}
    77  	defer f.Close()
    78  
    79  	scanner := bufio.NewScanner(f)
    80  	for scanner.Scan() {
    81  		pkg, err := parseGlockLine(scanner.Text())
    82  		if err != nil {
    83  			g.Logger.Printf("  Warning: Skipping line. Unable to parse: %s\n", err)
    84  			continue
    85  		}
    86  		if pkg == nil {
    87  			continue
    88  		}
    89  		g.packages = append(g.packages, *pkg)
    90  	}
    91  
    92  	if err := scanner.Err(); err != nil {
    93  		g.Logger.Printf("  Warning: Ignoring errors found while parsing %s: %s\n", path, err)
    94  	}
    95  
    96  	return nil
    97  }
    98  
    99  func parseGlockLine(line string) (*glockPackage, error) {
   100  	fields := strings.Fields(line)
   101  	switch len(fields) {
   102  	case 2: // Valid.
   103  	case 0: // Skip empty lines.
   104  		return nil, nil
   105  	default:
   106  		return nil, fmt.Errorf("invalid glock configuration: %s", line)
   107  	}
   108  
   109  	// Skip commands.
   110  	if fields[0] == "cmd" {
   111  		return nil, nil
   112  	}
   113  	return &glockPackage{
   114  		importPath: fields[0],
   115  		revision:   fields[1],
   116  	}, nil
   117  }
   118  
   119  func (g *Importer) convert(pr gps.ProjectRoot) (*dep.Manifest, *dep.Lock) {
   120  	g.Logger.Println("Converting from GLOCKFILE ...")
   121  
   122  	packages := make([]base.ImportedPackage, 0, len(g.packages))
   123  	for _, pkg := range g.packages {
   124  		// Validate
   125  		if pkg.importPath == "" {
   126  			g.Logger.Println(
   127  				"  Warning: Skipping project. Invalid glock configuration, import path is required",
   128  			)
   129  			continue
   130  		}
   131  
   132  		if pkg.revision == "" {
   133  			// Do not add 'empty constraints' to the manifest. Solve will add to lock if required.
   134  			g.Logger.Printf(
   135  				"  Warning: Skipping import with empty constraints. "+
   136  					"The solve step will add the dependency to the lock if needed: %q\n",
   137  				pkg.importPath,
   138  			)
   139  			continue
   140  		}
   141  
   142  		packages = append(packages, base.ImportedPackage{
   143  			Name:     pkg.importPath,
   144  			LockHint: pkg.revision,
   145  		})
   146  	}
   147  
   148  	g.ImportPackages(packages, true)
   149  	return g.Manifest, g.Lock
   150  }