diff --git a/glide.lock b/glide.lock index 3d3222867ddd50d4f9b9d5432a7c265af17d35a7..62620c5ded26d6461e28801b4c5ce280fdfcb974 100644 --- a/glide.lock +++ b/glide.lock @@ -228,4 +228,6 @@ imports: - term - name: github.com/streadway/simpleuuid version: 6617b501e485b77e61b98cd533aefff9e258b5a7 +- name: github.com/Masterminds/glide + version: 84607742b10f492430762d038e954236bbaf23f7 devImports: [] diff --git a/glide.yaml b/glide.yaml index 6b1ab4221fd9d4dfccf5d67eaea6e9ed43438e48..d832bc2213309b201c8c52bda69fbb9e87ef52f5 100644 --- a/glide.yaml +++ b/glide.yaml @@ -29,3 +29,5 @@ import: - package: github.com/Sirupsen/logrus version: ^0.11.0 - package: github.com/streadway/simpleuuid +- package: github.com/Masterminds/glide + version: ~0.12.3 \ No newline at end of file diff --git a/hell/README.md b/hell/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8fe7fdb9ee299488204c8a9dda55a9b7542ce2dc --- /dev/null +++ b/hell/README.md @@ -0,0 +1,4 @@ +> 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 diff --git a/hell/cmd/hell/main.go b/hell/cmd/hell/main.go new file mode 100644 index 0000000000000000000000000000000000000000..c6837b008a2fbe35fb3e8ff2222c4b99e0fbba0f --- /dev/null +++ b/hell/cmd/hell/main.go @@ -0,0 +1,44 @@ +package main + +import ( + "io/ioutil" + + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" + "fmt" + "os" +) + +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() }, + } + + var baseGlideLockFile, depGlideLockFile string + dependCmd := &cobra.Command{ + Use: "lock-merge", + Short: "Merge glide.lock files together", + Long: "", + Run: func(cmd *cobra.Command, args []string) { + bytes, err := ioutil.ReadFile(baseGlideLockFile) + if err != nil { + fmt.Printf("Could not read file: %s\n", err) + os.Exit(1) + } + err = yaml.Unmarshal(bytes, &m) + bytes, err = ioutil.ReadFile(depGlideLockFile) + if err != nil { + fmt.Printf("Could not read file: %s\n", err) + os.Exit(1) + } + m := make(map[interface{}]interface{}) + }, + } + dependCmd.PersistentFlags().StringVarP(&baseGlideLockFile, "base", "b", "", "") + dependCmd.PersistentFlags().StringVarP(&depGlideLockFile, "dep", "d", "", "") + hellCmd.AddCommand(dependCmd) + dependCmd.Execute() +} diff --git a/hell/merge.go b/hell/merge.go new file mode 100644 index 0000000000000000000000000000000000000000..89137da5c5c566583017acdac386f7bf8e0ebed2 --- /dev/null +++ b/hell/merge.go @@ -0,0 +1,102 @@ +package main + +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(baseGlideLockFileBytes, overrideGlideLockFileBytes []byte) ([]byte, error) { + baseLockFile, err := cfg.LockfileFromYaml(baseGlideLockFileBytes) + if err != nil { + return nil, err + } + overrideLockFile, err := cfg.LockfileFromYaml(overrideGlideLockFileBytes) + if err != nil { + return nil, err + } + + 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(baseGlideLockFileBytes) + hasher.Write(overrideGlideLockFileBytes) + + lockFile, err := cfg.NewLockfile(deps, devDeps, fmt.Sprintf("%x", hasher.Sum(nil))) + if err != nil { + return nil, err + } + + return lockFile.Marshal() +} + +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 +} diff --git a/hell/merge_test.go b/hell/merge_test.go new file mode 100644 index 0000000000000000000000000000000000000000..7194f01bf2ec7a72bc270b6c2651c6c7b4b46cf4 --- /dev/null +++ b/hell/merge_test.go @@ -0,0 +1,65 @@ +package main + +import ( + "testing" + "github.com/stretchr/testify/assert" + "fmt" +) + + +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 + - node + - proxy + - types + - version + - consensus + - rpc/core/types + - blockchain + - mempool + - rpc/core + - state +` + + +func TestMergeGlideLockFiles(t *testing.T) { + lockYml, err := MergeGlideLockFiles(([]byte)(baseLockYml), ([]byte)(overrideLockYml)) + assert.NoError(t, err, "Lockfiles should merge") + fmt.Println(string(lockYml)) + assert.Equal(t, expectedLockYml, string(lockYml)) + +}