Skip to content
Snippets Groups Projects
Commit 942ce0a2 authored by Benjamin Bollen's avatar Benjamin Bollen Committed by GitHub
Browse files

Merge pull request #454 from silasdavis/hell

Glide dependency updating tool
parents c8fb9175 90659d22
No related branches found
No related tags found
No related merge requests found
...@@ -228,4 +228,6 @@ imports: ...@@ -228,4 +228,6 @@ imports:
- term - term
- name: github.com/streadway/simpleuuid - name: github.com/streadway/simpleuuid
version: 6617b501e485b77e61b98cd533aefff9e258b5a7 version: 6617b501e485b77e61b98cd533aefff9e258b5a7
- name: github.com/Masterminds/glide
version: 84607742b10f492430762d038e954236bbaf23f7
devImports: [] devImports: []
...@@ -29,3 +29,5 @@ import: ...@@ -29,3 +29,5 @@ import:
- package: github.com/Sirupsen/logrus - package: github.com/Sirupsen/logrus
version: ^0.11.0 version: ^0.11.0
- package: github.com/streadway/simpleuuid - package: github.com/streadway/simpleuuid
- package: github.com/Masterminds/glide
version: ~0.12.3
\ No newline at end of file
> Hell is other people's packages
While we wait for working package management in go we need a way to make
maintaining the glide.lock by hand less painful.
\ No newline at end of file
package main
import (
"fmt"
"os"
"path/filepath"
"github.com/Masterminds/glide/cache"
"github.com/Masterminds/glide/cfg"
"github.com/Masterminds/glide/msg"
"github.com/Masterminds/glide/path"
"github.com/Masterminds/glide/util"
"github.com/eris-ltd/eris-db/util/hell"
"github.com/spf13/cobra"
"github.com/Masterminds/glide/action"
"github.com/Masterminds/glide/repo"
)
func main() {
hellCmd := &cobra.Command{
Use: "hell",
Short: "Hell makes the most of it being warm",
Long: "",
Run: func(cmd *cobra.Command, args []string) { cmd.Help() },
}
// Lock merge command
var baseGlideLockFile, depGlideLockFile string
lockMergeCmd := &cobra.Command{
Use: "lock-merge",
Short: "Merge glide.lock files together",
Long: "This command merges two glide.lock files into a single one by copying all dependencies " +
"from a base glide.lock and an override glide.lock to an output glide.lock with dependencies " +
"from override taking precedence over those from base.",
Run: func(cmd *cobra.Command, args []string) {
baseLockFile, err := cfg.ReadLockFile(baseGlideLockFile)
if err != nil {
fmt.Printf("Could not read file: %s\n", err)
os.Exit(1)
}
overrideLockFile, err := cfg.ReadLockFile(depGlideLockFile)
if err != nil {
fmt.Printf("Could not read file: %s\n", err)
os.Exit(1)
}
mergedLockFile, err := hell.MergeGlideLockFiles(baseLockFile, overrideLockFile)
if err != nil {
fmt.Printf("Could not merge lock files: %s\n", err)
os.Exit(1)
}
mergedBytes, err := mergedLockFile.Marshal()
if err != nil {
fmt.Printf("Could not marshal lock file: %s\n", err)
os.Exit(1)
}
os.Stdout.Write(mergedBytes)
},
}
lockMergeCmd.PersistentFlags().StringVarP(&baseGlideLockFile, "base", "b", "", "base lock file")
lockMergeCmd.PersistentFlags().StringVarP(&depGlideLockFile, "override", "o", "", "override lock file")
// Lock update
interactive := false
getTransitiveCmd := &cobra.Command{
Use: "get",
Short: "gets a remote dependency to this project along with its transtive dependencies.",
Long: "Gets a remote dependency and its transitive dependencies by adding the remote " +
"depednency to this project's glide.yaml and merging the remote dependency's " +
"glide.lock into this project's glide.lock",
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 {
msg.Die("%s requires a single argument of the remote dependency\n", cmd.Name())
}
rootPackage, _ := util.NormalizeName(args[0])
// Add dependency to glide
action.Get(args, repo.NewInstaller() , false, true, false, !interactive, false)
// Now hunt down the repo cache
dep := action.EnsureConfig().Imports.Get(rootPackage)
key, err := cache.Key(dep.Remote())
if err != nil {
msg.Die("%s requires a single argument of the remote dependency\n", cmd.Name())
}
cacheDir := filepath.Join(cache.Location(), "src", key)
if path.HasLock(cacheDir) {
msg.Info("Found dependency lock file, merging into project lock file")
lockPath := filepath.Join(".", path.LockFile)
baseLockFile, err := cfg.ReadLockFile(lockPath)
if err != nil {
msg.Die("Could not read base lock file: %s", err)
}
overrideLockFile, err := cfg.ReadLockFile(filepath.Join(cacheDir, path.LockFile))
if err != nil {
msg.Die("Could not read dependency lock file: %s", err)
}
mergedLockFile, err := hell.MergeGlideLockFiles(baseLockFile, overrideLockFile)
if err != nil {
msg.Die("Could not merge lock files: %s\n", err)
}
err = mergedLockFile.WriteFile(lockPath)
if err != nil {
msg.Die("Could not write merged lock file: %s", err)
}
} else {
msg.Info("Did not find dependency lock file, so nothing merged intoo project lock file")
}
},
}
getTransitiveCmd.PersistentFlags().BoolVarP(&interactive, "interactive", "i", false,
"set dependency verion interactively")
hellCmd.AddCommand(lockMergeCmd)
hellCmd.AddCommand(getTransitiveCmd)
lockMergeCmd.Execute()
}
package hell
import (
"crypto/sha256"
"fmt"
"sort"
"github.com/Masterminds/glide/cfg"
)
// Merges two glide lock files together, letting dependencies from 'base' be overwritten
// by those from 'override'. Returns the resultant glide lock file bytes
func MergeGlideLockFiles(baseLockFile, overrideLockFile *cfg.Lockfile) (*cfg.Lockfile, error) {
imports := make(map[string]*cfg.Lock, len(baseLockFile.Imports))
devImports := make(map[string]*cfg.Lock, len(baseLockFile.DevImports))
// Copy the base dependencies into a map
for _, lock := range baseLockFile.Imports {
imports[lock.Name] = lock
}
for _, lock := range baseLockFile.DevImports {
devImports[lock.Name] = lock
}
// Override base dependencies and add any extra ones
for _, lock := range overrideLockFile.Imports {
imports[lock.Name] = mergeLocks(imports[lock.Name], lock)
}
for _, lock := range overrideLockFile.DevImports {
devImports[lock.Name] = mergeLocks(imports[lock.Name], lock)
}
deps := make([]*cfg.Dependency, 0, len(imports))
devDeps := make([]*cfg.Dependency, 0, len(devImports))
// Flatten to Dependencies
for _, lock := range imports {
deps = append(deps, pinnedDependencyFromLock(lock))
}
for _, lock := range devImports {
devDeps = append(devDeps, pinnedDependencyFromLock(lock))
}
hasher := sha256.New()
hasher.Write(([]byte)(baseLockFile.Hash))
hasher.Write(([]byte)(overrideLockFile.Hash))
return cfg.NewLockfile(deps, devDeps, fmt.Sprintf("%x", hasher.Sum(nil)))
}
func mergeLocks(baseLock, overrideLock *cfg.Lock) *cfg.Lock {
lock := overrideLock.Clone()
if baseLock == nil {
return lock
}
// Merge and dedupe subpackages
subpackages := make([]string, 0, len(lock.Subpackages)+len(baseLock.Subpackages))
for _, sp := range lock.Subpackages {
subpackages = append(subpackages, sp)
}
for _, sp := range baseLock.Subpackages {
subpackages = append(subpackages, sp)
}
sort.Stable(sort.StringSlice(subpackages))
dedupeSubpackages := make([]string, 0, len(subpackages))
lastSp := ""
elided := 0
for _, sp := range subpackages {
if lastSp == sp {
elided++
} else {
dedupeSubpackages = append(dedupeSubpackages, sp)
lastSp = sp
}
}
lock.Subpackages = dedupeSubpackages[:len(dedupeSubpackages)-elided]
return lock
}
func pinnedDependencyFromLock(lock *cfg.Lock) *cfg.Dependency {
dep := cfg.DependencyFromLock(lock)
dep.Pin = lock.Version
return dep
}
package hell
import (
"testing"
"strings"
"github.com/Masterminds/glide/cfg"
"github.com/stretchr/testify/assert"
)
const baseLockYml = `imports:
- name: github.com/gogo/protobuf
version: 82d16f734d6d871204a3feb1a73cb220cc92574c
- name: github.com/tendermint/tendermint
version: aaea0c5d2e3ecfbf29f2608f9d43649ec7f07f50
subpackages:
- node
- proxy
- types
- version
- consensus
- rpc/core/types
- blockchain
- mempool
- rpc/core
- state
`
const overrideLockYml = `imports:
- name: github.com/tendermint/tendermint
version: 764091dfbb035f1b28da4b067526e04c6a849966
subpackages:
- benchmarks
- proxy
- types
- version
`
const expectedLockYml = `imports:
- name: github.com/gogo/protobuf
version: 82d16f734d6d871204a3feb1a73cb220cc92574c
- name: github.com/tendermint/tendermint
version: 764091dfbb035f1b28da4b067526e04c6a849966
subpackages:
- benchmarks
- blockchain
- consensus
- mempool
- node
- proxy
- rpc/core
- rpc/core/types
testImports: []
`
func TestMergeGlideLockFiles(t *testing.T) {
baseLockFile, err := cfg.LockfileFromYaml(([]byte)(baseLockYml))
assert.NoError(t, err, "Lockfile should parse")
overrideLockFile, err := cfg.LockfileFromYaml(([]byte)(overrideLockYml))
assert.NoError(t, err, "Lockfile should parse")
mergedLockFile, err := MergeGlideLockFiles(baseLockFile, overrideLockFile)
assert.NoError(t, err, "Lockfiles should merge")
mergedYmlBytes, err := mergedLockFile.Marshal()
assert.NoError(t, err, "Lockfile should marshal")
ymlLines := strings.Split(string(mergedYmlBytes), "\n")
// Drop the updated and hash lines
actualYml := strings.Join(ymlLines[2:], "\n")
assert.Equal(t, expectedLockYml, actualYml)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment