Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support importing of dependencies from Trash #740

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ install: build
install -m 755 ./glide ${DESTDIR}/usr/local/bin/glide

test:
${GLIDE_GO_EXECUTABLE} test . ./gb ./path ./action ./tree ./util ./godep ./godep/strip ./gpm ./cfg ./dependency ./importer ./msg ./repo ./mirrors
${GLIDE_GO_EXECUTABLE} test . ./gb ./path ./action ./tree ./util ./godep ./godep/strip ./gpm ./trash ./cfg ./dependency ./importer ./msg ./repo ./mirrors

integration-test:
${GLIDE_GO_EXECUTABLE} build
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ When a dependent package is encountered its imports are scanned to determine
dependencies of dependencies (transitive dependencies). If the dependent project
contains a `glide.yaml` file that information is used to help determine the
dependency rules when fetching from a location or version to use. Configuration
from Godep, GB, GOM, and GPM is also imported.
from Godep, GB, GOM, GPM and Trash is also imported.

The dependencies are exported to the `vendor/` directory where the `go` tools
can find and use them. A `glide.lock` file is generated containing all the
Expand Down Expand Up @@ -186,7 +186,7 @@ $ glide get github.com/Masterminds/cookoo
```

When `glide get` is used it will introspect the listed package to resolve its
dependencies including using Godep, GPM, Gom, and GB config files.
dependencies including using Godep, GPM, Gom, GB and Trash config files.

### glide update (aliased to up)

Expand All @@ -199,7 +199,7 @@ $ glide up
```

This will recurse over the packages looking for other projects managed by Glide,
Godep, gb, gom, and GPM. When one is found those packages will be installed as needed.
Godep, gb, gom, GPM and Trash. When one is found those packages will be installed as needed.

A `glide.lock` file will be created or updated with the dependencies pinned to
specific versions. For example, if in the `glide.yaml` file a version was
Expand Down Expand Up @@ -403,16 +403,16 @@ That's up to you. It's not necessary, but it may also cause you extra
work and lots of extra space in your VCS. There may also be unforeseen errors
([see an example](https://github.com/mattfarina/golang-broken-vendor)).

#### Q: How do I import settings from GPM, Godep, gom or gb?
#### Q: How do I import settings from GPM, Godep, gom, gb or Trash?

There are two parts to importing.

1. If a package you import has configuration for GPM, Godep, gom or gb Glide will
recursively install the dependencies automatically.
2. If you would like to import configuration from GPM, Godep, gom or gb to Glide see
the `glide import` command. For example, you can run `glide import godep` for
Glide to detect the projects Godep configuration and generate a `glide.yaml`
file for you.
1. If a package you import has configuration for GPM, Godep, gom, gb or Trash
Glide will recursively install the dependencies automatically.
2. If you would like to import configuration from GPM, Godep, gom, gb or Trash
to Glide see the `glide import` command. For example, you can run
`glide import godep` for Glide to detect the projects Godep configuration
and generate a `glide.yaml` file for you.

Each of these will merge your existing `glide.yaml` file with the
dependencies it finds for those managers, and then emit the file as
Expand Down
13 changes: 13 additions & 0 deletions action/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/Masterminds/glide/gpm"
"github.com/Masterminds/glide/msg"
gpath "github.com/Masterminds/glide/path"
"github.com/Masterminds/glide/trash"
"github.com/Masterminds/glide/util"
)

Expand Down Expand Up @@ -204,6 +205,9 @@ func guessImportDeps(base string, config *cfg.Config) {
} else if d, ok := guessImportGB(absBase); ok {
msg.Info("Importing GB configuration")
deps = d
} else if d, ok := guessImportTrash(absBase); ok {
msg.Info("Importing Trash configuration")
deps = d
}

for _, i := range deps {
Expand Down Expand Up @@ -243,3 +247,12 @@ func guessImportGB(dir string) ([]*cfg.Dependency, bool) {

return d, true
}

func guessImportTrash(dir string) ([]*cfg.Dependency, bool) {
d, err := trash.Parse(dir)
if err != nil || len(d) == 0 {
return []*cfg.Dependency{}, false
}

return d, true
}
21 changes: 21 additions & 0 deletions action/import_trash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package action

import (
"github.com/Masterminds/glide/msg"
"github.com/Masterminds/glide/trash"
)

// ImporTrash imports a Trash vendor file.
func ImporTrash(dest string) {
base := "."
config := EnsureConfig()
if !trash.Has(base) {
msg.Die("No Trash vendor file found.")
}
deps, err := trash.Parse(base)
if err != nil {
msg.Die("Failed to extract Trash vendor file: %s", err)
}
appendImports(deps, config)
writeConfigToFileOrStdout(config, dest)
}
22 changes: 18 additions & 4 deletions glide.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func commands() []cli.Command {
the subpackage 'web'.

If a fetched dependency has a glide.yaml file, configuration from Godep,
GPM, GOM, or GB Glide that configuration will be used to find the dependencies
GPM, GOM, GB or Trash Glide that configuration will be used to find the dependencies
and versions to fetch. If those are not available the dependent packages will
be fetched as either a version specified elsewhere or the latest version.

Expand Down Expand Up @@ -374,6 +374,20 @@ func commands() []cli.Command {
return nil
},
},
{
Name: "trash",
Usage: "Import Trash vendor file and display the would-be yaml file",
Flags: []cli.Flag{
cli.StringFlag{
Name: "file, f",
Usage: "Save all of the discovered dependencies to a Glide YAML file.",
},
},
Action: func(c *cli.Context) error {
action.ImporTrash(c.String("file"))
return nil
},
},
},
},
{
Expand Down Expand Up @@ -527,9 +541,9 @@ Example:
'--no-recursive'. When this behavior is skipped a glide.lock file is not
generated because the full dependency tree cannot be known.

Glide will also import Godep, GB, GOM, and GPM files as it finds them in dependencies.
It will create a glide.yaml file from the Godeps data, and then update. This
has no effect if '--no-recursive' is set.
Glide will also import Godep, GB, GOM, GPM and Trash files as it finds them
in dependencies. It will create a glide.yaml file from the Godeps data, and
then update. This has no effect if '--no-recursive' is set.

The '--strip-vendor' flag will remove any nested 'vendor' folders and
'Godeps/_workspace' folders after an update (along with undoing any Godep
Expand Down
20 changes: 16 additions & 4 deletions importer/importer.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Package importer imports dependency configuration from Glide, Godep, GPM, GB and gom
// Package importer imports dependency configuration from Glide, Godep, GPM, GB, gom
// and Trash
package importer

import (
Expand All @@ -11,11 +12,13 @@ import (
"github.com/Masterminds/glide/godep"
"github.com/Masterminds/glide/gom"
"github.com/Masterminds/glide/gpm"
"github.com/Masterminds/glide/trash"
)

var i = &DefaultImporter{}

// Import uses the DefaultImporter to import from Glide, Godep, GPM, GB and gom.
// Import uses the DefaultImporter to import from Glide, Godep, GPM, GB, gom
// and Trash.
func Import(path string) (bool, []*cfg.Dependency, error) {
return i.Import(path)
}
Expand All @@ -30,10 +33,10 @@ type Importer interface {
Import(path string) (bool, []*cfg.Dependency, error)
}

// DefaultImporter imports from Glide, Godep, GPM, GB and gom.
// DefaultImporter imports from Glide, Godep, GPM, GB, gom and Trash.
type DefaultImporter struct{}

// Import tries to import configuration from Glide, Godep, GPM, GB and gom.
// Import tries to import configuration from Glide, Godep, GPM, GB, gom and Trash.
func (d *DefaultImporter) Import(path string) (bool, []*cfg.Dependency, error) {

// Try importing from Glide first.
Expand Down Expand Up @@ -87,6 +90,15 @@ func (d *DefaultImporter) Import(path string) (bool, []*cfg.Dependency, error) {
return true, deps, nil
}

// Try importing from Trash
if trash.Has(path) {
deps, err := trash.Parse(path)
if err != nil {
return false, []*cfg.Dependency{}, err
}
return true, deps, nil
}

// When none are found.
return false, []*cfg.Dependency{}, nil
}
126 changes: 126 additions & 0 deletions trash/conf/conf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Package govendor provides compatibility with govendor vendorfiles.

// This is a copy of Trash's `conf/conf.go` file, and has been ported
// to use gopkg.in/yaml.v2
// Trash is governed by a MIT license that can be found in the
// LICENSE file of Trash project

package conf

import (
"bufio"
"os"
"sort"
"strings"

"io/ioutil"

"gopkg.in/yaml.v2"
)

// Conf of a Trash vendor file.
type Conf struct {
Package string `yaml:"package,omitempty"`
Imports []Import `yaml:"import,omitempty"`
Excludes []string `yaml:"exclude,omitempty"`
importMap map[string]Import
confFile string
yamlType bool
}

// Import as defined in a Trash vendor file.
type Import struct {
Package string `yaml:"package,omitempty"`
Version string `yaml:"version,omitempty"`
Repo string `yaml:"repo,omitempty"`
}

// Parse a Trash vendor conf file.
func Parse(path string) (*Conf, error) {
ymlfile, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}

trashConf := &Conf{confFile: path}
err = yaml.Unmarshal(ymlfile, &trashConf)
if err == nil {
trashConf.yamlType = true
trashConf.Dedupe()
return trashConf, nil
}

trashConf = &Conf{confFile: path}
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

scanner := bufio.NewScanner(bufio.NewReader(file))
for scanner.Scan() {
line := scanner.Text()
if commentStart := strings.Index(line, "#"); commentStart >= 0 {
line = line[0:commentStart]
}
if line = strings.TrimSpace(line); line == "" {
continue
}
fields := strings.Fields(line)

if len(fields) == 1 && trashConf.Package == "" {
trashConf.Package = fields[0] // use the first 1-field line as the root package
continue
}
// If we have a `-` suffix, it's an exclude pattern
if fields[0][0] == '-' {
trashConf.Excludes = append(trashConf.Excludes, strings.TrimSpace(fields[0][1:]))
continue
}
// Otherwise it's an import pattern
packageImport := Import{}
packageImport.Package = fields[0] // at least 1 field at this point: trimmed the line and skipped empty
if len(fields) > 2 {
packageImport.Repo = fields[2]
}
if len(fields) > 1 {
packageImport.Version = fields[1]
}
trashConf.Imports = append(trashConf.Imports, packageImport)
}

trashConf.Dedupe()
return trashConf, nil
}

// Dedupe deletes duplicates and sorts the imports
func (t *Conf) Dedupe() {
t.importMap = map[string]Import{}
for _, i := range t.Imports {
if _, ok := t.importMap[i.Package]; ok {
continue
}
t.importMap[i.Package] = i
}
ps := make([]string, 0, len(t.importMap))
for p := range t.importMap {
ps = append(ps, p)
}
sort.Strings(ps)
imports := make([]Import, 0, len(t.importMap))
for _, p := range ps {
imports = append(imports, t.importMap[p])
}
t.Imports = imports
}

// Get the import of a specified package.
func (t *Conf) Get(pkg string) (Import, bool) {
i, ok := t.importMap[pkg]
return i, ok
}

// ConfFile from which the config has been read.
func (t *Conf) ConfFile() string {
return t.confFile
}
52 changes: 52 additions & 0 deletions trash/trash.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Package trash reads Trash's vendor files.
//
// It is not a complete implementaton of Trash.
package trash

import (
"os"
"path/filepath"

"github.com/Masterminds/glide/cfg"
"github.com/Masterminds/glide/msg"
gpath "github.com/Masterminds/glide/path"
"github.com/Masterminds/glide/trash/conf"
)

// Has indicates whether a Trash file exists.
func Has(dir string) bool {
path := filepath.Join(dir, "vendor.conf")
_, err := os.Stat(path)
return err == nil
}

// Parse parses a Trash vendor.conf file.
func Parse(dir string) ([]*cfg.Dependency, error) {
path := filepath.Join(dir, "vendor.conf")
if i, err := os.Stat(path); err != nil {
return []*cfg.Dependency{}, nil
} else if i.IsDir() {
msg.Info("vendor.conf is a directory.\n")
return []*cfg.Dependency{}, nil
}
msg.Info("Found vendor.conf file in %s", gpath.StripBasepath(dir))
msg.Info("--> Parsing Trash metadata...")

buf := []*cfg.Dependency{}

trashconf, err := conf.Parse(path)
if err != nil {
return buf, err
}

for _, trashimport := range trashconf.Imports {
dep := &cfg.Dependency{}
dep.Name = trashimport.Package
dep.Reference = trashimport.Version
dep.Repository = trashimport.Repo

buf = append(buf, dep)
}

return buf, nil
}