| 1 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,60 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "fmt" |
|
| 6 |
- "io/ioutil" |
|
| 7 |
- "os" |
|
| 8 |
- "path/filepath" |
|
| 9 |
- |
|
| 10 |
- "github.com/openshift/origin/pkg/cmd/admin" |
|
| 11 |
- "github.com/openshift/origin/pkg/cmd/cli" |
|
| 12 |
- "github.com/openshift/origin/pkg/cmd/openshift" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-func OutDir(path string) (string, error) {
|
|
| 16 |
- outDir, err := filepath.Abs(path) |
|
| 17 |
- if err != nil {
|
|
| 18 |
- return "", err |
|
| 19 |
- } |
|
| 20 |
- |
|
| 21 |
- stat, err := os.Stat(outDir) |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return "", err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- if !stat.IsDir() {
|
|
| 27 |
- return "", fmt.Errorf("output directory %s is not a directory\n", outDir)
|
|
| 28 |
- } |
|
| 29 |
- outDir = outDir + "/" |
|
| 30 |
- return outDir, nil |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-func main() {
|
|
| 34 |
- // use os.Args instead of "flags" because "flags" will mess up the man pages! |
|
| 35 |
- path := "contrib/completions/bash/" |
|
| 36 |
- if len(os.Args) == 2 {
|
|
| 37 |
- path = os.Args[1] |
|
| 38 |
- } else if len(os.Args) > 2 {
|
|
| 39 |
- fmt.Fprintf(os.Stderr, "usage: %s [output directory]\n", os.Args[0]) |
|
| 40 |
- os.Exit(1) |
|
| 41 |
- } |
|
| 42 |
- |
|
| 43 |
- outDir, err := OutDir(path) |
|
| 44 |
- if err != nil {
|
|
| 45 |
- fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err) |
|
| 46 |
- os.Exit(1) |
|
| 47 |
- } |
|
| 48 |
- outFile_openshift := outDir + "openshift" |
|
| 49 |
- openshift := openshift.NewCommandOpenShift("openshift")
|
|
| 50 |
- openshift.GenBashCompletionFile(outFile_openshift) |
|
| 51 |
- |
|
| 52 |
- outFile_osc := outDir + "oc" |
|
| 53 |
- out := os.Stdout |
|
| 54 |
- oc := cli.NewCommandCLI("oc", "openshift cli", &bytes.Buffer{}, out, ioutil.Discard)
|
|
| 55 |
- oc.GenBashCompletionFile(outFile_osc) |
|
| 56 |
- |
|
| 57 |
- outFile_osadm := outDir + "oadm" |
|
| 58 |
- oadm := admin.NewCommandAdmin("oadm", "openshift admin", ioutil.Discard)
|
|
| 59 |
- oadm.GenBashCompletionFile(outFile_osadm) |
|
| 60 |
-} |
| 61 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,71 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "io" |
|
| 6 |
- "os" |
|
| 7 |
- "runtime" |
|
| 8 |
- "strings" |
|
| 9 |
- |
|
| 10 |
- "k8s.io/kubernetes/pkg/api" |
|
| 11 |
- pkg_runtime "k8s.io/kubernetes/pkg/runtime" |
|
| 12 |
- "k8s.io/kubernetes/pkg/util/sets" |
|
| 13 |
- |
|
| 14 |
- "github.com/golang/glog" |
|
| 15 |
- flag "github.com/spf13/pflag" |
|
| 16 |
- |
|
| 17 |
- _ "github.com/openshift/origin/pkg/api" |
|
| 18 |
- _ "github.com/openshift/origin/pkg/api/v1" |
|
| 19 |
- _ "github.com/openshift/origin/pkg/api/v1beta3" |
|
| 20 |
-) |
|
| 21 |
- |
|
| 22 |
-var ( |
|
| 23 |
- functionDest = flag.StringP("funcDest", "f", "-", "Output for conversion functions; '-' means stdout")
|
|
| 24 |
- version = flag.StringP("version", "v", "v1beta3", "Version for conversion.")
|
|
| 25 |
-) |
|
| 26 |
- |
|
| 27 |
-func main() {
|
|
| 28 |
- runtime.GOMAXPROCS(runtime.NumCPU()) |
|
| 29 |
- flag.Parse() |
|
| 30 |
- |
|
| 31 |
- var funcOut io.Writer |
|
| 32 |
- if *functionDest == "-" {
|
|
| 33 |
- funcOut = os.Stdout |
|
| 34 |
- } else {
|
|
| 35 |
- file, err := os.Create(*functionDest) |
|
| 36 |
- if err != nil {
|
|
| 37 |
- glog.Fatalf("Couldn't open %v: %v", *functionDest, err)
|
|
| 38 |
- } |
|
| 39 |
- defer file.Close() |
|
| 40 |
- funcOut = file |
|
| 41 |
- } |
|
| 42 |
- |
|
| 43 |
- generator := pkg_runtime.NewConversionGenerator(api.Scheme.Raw(), "github.com/openshift/origin/pkg/api") |
|
| 44 |
- apiShort := generator.AddImport("k8s.io/kubernetes/pkg/api")
|
|
| 45 |
- generator.AddImport("k8s.io/kubernetes/pkg/api/resource")
|
|
| 46 |
- generator.AssumePrivateConversions() |
|
| 47 |
- // TODO(wojtek-t): Change the overwrites to a flag. |
|
| 48 |
- generator.OverwritePackage(*version, "") |
|
| 49 |
- for _, knownType := range api.Scheme.KnownTypes(*version) {
|
|
| 50 |
- if !strings.Contains(knownType.PkgPath(), "openshift/origin") {
|
|
| 51 |
- continue |
|
| 52 |
- } |
|
| 53 |
- if err := generator.GenerateConversionsForType(*version, knownType); err != nil {
|
|
| 54 |
- glog.Errorf("error while generating conversion functions for %v: %v", knownType, err)
|
|
| 55 |
- } |
|
| 56 |
- } |
|
| 57 |
- |
|
| 58 |
- generator.RepackImports(sets.NewString("k8s.io/kubernetes/pkg/runtime"))
|
|
| 59 |
- // the repack changes the name of the import |
|
| 60 |
- apiShort = generator.AddImport("k8s.io/kubernetes/pkg/api")
|
|
| 61 |
- |
|
| 62 |
- if err := generator.WriteImports(funcOut); err != nil {
|
|
| 63 |
- glog.Fatalf("error while writing imports: %v", err)
|
|
| 64 |
- } |
|
| 65 |
- if err := generator.WriteConversionFunctions(funcOut); err != nil {
|
|
| 66 |
- glog.Fatalf("Error while writing conversion functions: %v", err)
|
|
| 67 |
- } |
|
| 68 |
- if err := generator.RegisterConversionFunctions(funcOut, fmt.Sprintf("%s.Scheme", apiShort)); err != nil {
|
|
| 69 |
- glog.Fatalf("Error while writing conversion functions: %v", err)
|
|
| 70 |
- } |
|
| 71 |
-} |
| 72 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,94 +0,0 @@ |
| 1 |
-/* |
|
| 2 |
-Copyright 2015 The Kubernetes Authors All rights reserved. |
|
| 3 |
- |
|
| 4 |
-Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 5 |
-you may not use this file except in compliance with the License. |
|
| 6 |
-You may obtain a copy of the License at |
|
| 7 |
- |
|
| 8 |
- http://www.apache.org/licenses/LICENSE-2.0 |
|
| 9 |
- |
|
| 10 |
-Unless required by applicable law or agreed to in writing, software |
|
| 11 |
-distributed under the License is distributed on an "AS IS" BASIS, |
|
| 12 |
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 13 |
-See the License for the specific language governing permissions and |
|
| 14 |
-limitations under the License. |
|
| 15 |
-*/ |
|
| 16 |
- |
|
| 17 |
-package main |
|
| 18 |
- |
|
| 19 |
-import ( |
|
| 20 |
- "fmt" |
|
| 21 |
- "io" |
|
| 22 |
- "os" |
|
| 23 |
- "runtime" |
|
| 24 |
- "strings" |
|
| 25 |
- |
|
| 26 |
- "k8s.io/kubernetes/pkg/api" |
|
| 27 |
- pkg_runtime "k8s.io/kubernetes/pkg/runtime" |
|
| 28 |
- "k8s.io/kubernetes/pkg/util/sets" |
|
| 29 |
- |
|
| 30 |
- "github.com/golang/glog" |
|
| 31 |
- flag "github.com/spf13/pflag" |
|
| 32 |
- |
|
| 33 |
- _ "github.com/openshift/origin/pkg/api" |
|
| 34 |
- _ "github.com/openshift/origin/pkg/api/v1" |
|
| 35 |
- _ "github.com/openshift/origin/pkg/api/v1beta3" |
|
| 36 |
-) |
|
| 37 |
- |
|
| 38 |
-var ( |
|
| 39 |
- functionDest = flag.StringP("func-dest", "f", "-", "Output for deep copy functions; '-' means stdout")
|
|
| 40 |
- version = flag.StringP("version", "v", "v1beta3", "Version for deep copies.")
|
|
| 41 |
- overwrites = flag.StringP("overwrites", "o", "", "Comma-separated overwrites for package names")
|
|
| 42 |
-) |
|
| 43 |
- |
|
| 44 |
-func main() {
|
|
| 45 |
- runtime.GOMAXPROCS(runtime.NumCPU()) |
|
| 46 |
- flag.Parse() |
|
| 47 |
- |
|
| 48 |
- var funcOut io.Writer |
|
| 49 |
- if *functionDest == "-" {
|
|
| 50 |
- funcOut = os.Stdout |
|
| 51 |
- } else {
|
|
| 52 |
- file, err := os.Create(*functionDest) |
|
| 53 |
- if err != nil {
|
|
| 54 |
- glog.Fatalf("Couldn't open %v: %v", *functionDest, err)
|
|
| 55 |
- } |
|
| 56 |
- defer file.Close() |
|
| 57 |
- funcOut = file |
|
| 58 |
- } |
|
| 59 |
- |
|
| 60 |
- knownVersion := *version |
|
| 61 |
- if knownVersion == "api" {
|
|
| 62 |
- knownVersion = api.Scheme.Raw().InternalVersion |
|
| 63 |
- } |
|
| 64 |
- generator := pkg_runtime.NewDeepCopyGenerator(api.Scheme.Raw(), "github.com/openshift/origin/pkg/api", sets.NewString("github.com/openshift/origin"))
|
|
| 65 |
- apiShort := generator.AddImport("k8s.io/kubernetes/pkg/api")
|
|
| 66 |
- generator.ReplaceType("k8s.io/kubernetes/pkg/util/sets", "empty", struct{}{})
|
|
| 67 |
- |
|
| 68 |
- for _, overwrite := range strings.Split(*overwrites, ",") {
|
|
| 69 |
- vals := strings.Split(overwrite, "=") |
|
| 70 |
- generator.OverwritePackage(vals[0], vals[1]) |
|
| 71 |
- } |
|
| 72 |
- for _, knownType := range api.Scheme.KnownTypes(knownVersion) {
|
|
| 73 |
- if !strings.Contains(knownType.PkgPath(), "openshift/origin") {
|
|
| 74 |
- continue |
|
| 75 |
- } |
|
| 76 |
- if err := generator.AddType(knownType); err != nil {
|
|
| 77 |
- glog.Errorf("error while generating deep copy functions for %v: %v", knownType, err)
|
|
| 78 |
- } |
|
| 79 |
- } |
|
| 80 |
- |
|
| 81 |
- generator.RepackImports() |
|
| 82 |
- // the repack changes the name of the import |
|
| 83 |
- apiShort = generator.AddImport("k8s.io/kubernetes/pkg/api")
|
|
| 84 |
- |
|
| 85 |
- if err := generator.WriteImports(funcOut); err != nil {
|
|
| 86 |
- glog.Fatalf("error while writing imports: %v", err)
|
|
| 87 |
- } |
|
| 88 |
- if err := generator.WriteDeepCopyFunctions(funcOut); err != nil {
|
|
| 89 |
- glog.Fatalf("error while writing deep copy functions: %v", err)
|
|
| 90 |
- } |
|
| 91 |
- if err := generator.RegisterDeepCopyFunctions(funcOut, fmt.Sprintf("%s.Scheme", apiShort)); err != nil {
|
|
| 92 |
- glog.Fatalf("error while registering deep copy functions: %v", err)
|
|
| 93 |
- } |
|
| 94 |
-} |
| 95 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,56 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "fmt" |
|
| 6 |
- "io/ioutil" |
|
| 7 |
- "os" |
|
| 8 |
- "path/filepath" |
|
| 9 |
- |
|
| 10 |
- "github.com/openshift/origin/pkg/cmd/admin" |
|
| 11 |
- "github.com/openshift/origin/pkg/cmd/cli" |
|
| 12 |
- "github.com/openshift/origin/pkg/cmd/util/gendocs" |
|
| 13 |
-) |
|
| 14 |
- |
|
| 15 |
-func OutDir(path string) (string, error) {
|
|
| 16 |
- outDir, err := filepath.Abs(path) |
|
| 17 |
- if err != nil {
|
|
| 18 |
- return "", err |
|
| 19 |
- } |
|
| 20 |
- |
|
| 21 |
- stat, err := os.Stat(outDir) |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return "", err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- if !stat.IsDir() {
|
|
| 27 |
- return "", fmt.Errorf("output directory %s is not a directory\n", outDir)
|
|
| 28 |
- } |
|
| 29 |
- outDir = outDir + "/" |
|
| 30 |
- return outDir, nil |
|
| 31 |
-} |
|
| 32 |
- |
|
| 33 |
-func main() {
|
|
| 34 |
- path := "docs/generated/" |
|
| 35 |
- if len(os.Args) == 2 {
|
|
| 36 |
- path = os.Args[1] |
|
| 37 |
- } else if len(os.Args) > 2 {
|
|
| 38 |
- fmt.Fprintf(os.Stderr, "usage: %s [output directory]\n", os.Args[0]) |
|
| 39 |
- os.Exit(1) |
|
| 40 |
- } |
|
| 41 |
- |
|
| 42 |
- outDir, err := OutDir(path) |
|
| 43 |
- if err != nil {
|
|
| 44 |
- fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err) |
|
| 45 |
- os.Exit(1) |
|
| 46 |
- } |
|
| 47 |
- |
|
| 48 |
- outFile := outDir + "oc_by_example_content.adoc" |
|
| 49 |
- out := os.Stdout |
|
| 50 |
- cmd := cli.NewCommandCLI("oc", "oc", &bytes.Buffer{}, out, ioutil.Discard)
|
|
| 51 |
- gendocs.GenDocs(cmd, outFile) |
|
| 52 |
- |
|
| 53 |
- outFile = outDir + "oadm_by_example_content.adoc" |
|
| 54 |
- cmd = admin.NewCommandAdmin("oadm", "oadm", ioutil.Discard)
|
|
| 55 |
- gendocs.GenDocs(cmd, outFile) |
|
| 56 |
-} |
| 57 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,46 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "flag" |
|
| 5 |
- "fmt" |
|
| 6 |
- "os" |
|
| 7 |
- "strings" |
|
| 8 |
- |
|
| 9 |
- "github.com/openshift/origin/cmd/rebasehelpers/util" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-func main() {
|
|
| 13 |
- var start, end string |
|
| 14 |
- flag.StringVar(&start, "start", "master", "The start of the revision range for analysis") |
|
| 15 |
- flag.StringVar(&end, "end", "HEAD", "The end of the revision range for analysis") |
|
| 16 |
- flag.Parse() |
|
| 17 |
- |
|
| 18 |
- commits, err := util.CommitsBetween(start, end) |
|
| 19 |
- if err != nil {
|
|
| 20 |
- os.Stderr.WriteString(fmt.Sprintf("ERROR: couldn't find commits from %s..%s: %v\n", start, end, err))
|
|
| 21 |
- os.Exit(1) |
|
| 22 |
- } |
|
| 23 |
- |
|
| 24 |
- // TODO: Filter out bump commits for now until we decide how to deal with |
|
| 25 |
- // them correctly. |
|
| 26 |
- nonbumpCommits := []util.Commit{}
|
|
| 27 |
- for _, commit := range commits {
|
|
| 28 |
- if commit.DeclaresUpstreamChange() && |
|
| 29 |
- !strings.HasPrefix(commit.Summary, "bump(") {
|
|
| 30 |
- nonbumpCommits = append(nonbumpCommits, commit) |
|
| 31 |
- } |
|
| 32 |
- } |
|
| 33 |
- |
|
| 34 |
- errs := []string{}
|
|
| 35 |
- for _, validate := range AllValidators {
|
|
| 36 |
- err := validate(nonbumpCommits) |
|
| 37 |
- if err != nil {
|
|
| 38 |
- errs = append(errs, err.Error()) |
|
| 39 |
- } |
|
| 40 |
- } |
|
| 41 |
- |
|
| 42 |
- if len(errs) > 0 {
|
|
| 43 |
- os.Stderr.WriteString(strings.Join(errs, "\n\n")) |
|
| 44 |
- os.Exit(2) |
|
| 45 |
- } |
|
| 46 |
-} |
| 47 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,185 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "fmt" |
|
| 6 |
- "regexp" |
|
| 7 |
- "strings" |
|
| 8 |
- "text/template" |
|
| 9 |
- |
|
| 10 |
- "github.com/openshift/origin/cmd/rebasehelpers/util" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-var CommitSummaryErrorTemplate = ` |
|
| 14 |
-The following UPSTREAM commits have invalid summaries: |
|
| 15 |
- |
|
| 16 |
-{{ range .Commits }} [{{ .Sha }}] {{ .Summary }}
|
|
| 17 |
-{{ end }}
|
|
| 18 |
-UPSTREAM commit summaries should look like: |
|
| 19 |
- |
|
| 20 |
- UPSTREAM: [non-kube-repo/name: ]<PR number|carry|drop>: description |
|
| 21 |
- |
|
| 22 |
-UPSTREAM commits which revert previous UPSTREAM commits should look like: |
|
| 23 |
- |
|
| 24 |
- UPSTREAM: revert: <sha>: <normal upstream format> |
|
| 25 |
- |
|
| 26 |
-UPSTREAM commits are validated against the following regular expression: |
|
| 27 |
- |
|
| 28 |
- {{ .Pattern }}
|
|
| 29 |
- |
|
| 30 |
-Examples of valid summaries: |
|
| 31 |
- |
|
| 32 |
- UPSTREAM: 12345: A kube fix |
|
| 33 |
- UPSTREAM: coreos/etcd: 12345: An etcd fix |
|
| 34 |
- UPSTREAM: <carry>: A carried kube change |
|
| 35 |
- UPSTREAM: <drop>: A dropped kube change |
|
| 36 |
- UPSTREAM: revert: abcd123: coreos/etcd: 12345: An etcd fix |
|
| 37 |
- UPSTREAM: k8s.io/heapster: 12345: A heapster fix |
|
| 38 |
- |
|
| 39 |
-` |
|
| 40 |
- |
|
| 41 |
-var AllValidators = []func([]util.Commit) error{
|
|
| 42 |
- ValidateUpstreamCommitSummaries, |
|
| 43 |
- ValidateUpstreamCommitsWithoutGodepsChanges, |
|
| 44 |
- ValidateUpstreamCommitModifiesSingleGodepsRepo, |
|
| 45 |
- ValidateUpstreamCommitModifiesOnlyGodeps, |
|
| 46 |
- ValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo, |
|
| 47 |
-} |
|
| 48 |
- |
|
| 49 |
-// ValidateUpstreamCommitsWithoutGodepsChanges returns an error if any |
|
| 50 |
-// upstream commits have no Godeps changes. |
|
| 51 |
-func ValidateUpstreamCommitsWithoutGodepsChanges(commits []util.Commit) error {
|
|
| 52 |
- problemCommits := []util.Commit{}
|
|
| 53 |
- for _, commit := range commits {
|
|
| 54 |
- if commit.HasGodepsChanges() && !commit.DeclaresUpstreamChange() {
|
|
| 55 |
- problemCommits = append(problemCommits, commit) |
|
| 56 |
- } |
|
| 57 |
- } |
|
| 58 |
- if len(problemCommits) > 0 {
|
|
| 59 |
- label := "The following commits contain Godeps changes but aren't declared as UPSTREAM" |
|
| 60 |
- msg := renderGodepFilesError(label, problemCommits, RenderOnlyGodepsFiles) |
|
| 61 |
- return fmt.Errorf(msg) |
|
| 62 |
- } |
|
| 63 |
- return nil |
|
| 64 |
-} |
|
| 65 |
- |
|
| 66 |
-// ValidateUpstreamCommitModifiesSingleGodepsRepo returns an error if any |
|
| 67 |
-// upstream commits have changes that span more than one Godeps repo. |
|
| 68 |
-func ValidateUpstreamCommitModifiesSingleGodepsRepo(commits []util.Commit) error {
|
|
| 69 |
- problemCommits := []util.Commit{}
|
|
| 70 |
- for _, commit := range commits {
|
|
| 71 |
- godepsChanges, err := commit.GodepsReposChanged() |
|
| 72 |
- if err != nil {
|
|
| 73 |
- return err |
|
| 74 |
- } |
|
| 75 |
- if len(godepsChanges) > 1 {
|
|
| 76 |
- problemCommits = append(problemCommits, commit) |
|
| 77 |
- } |
|
| 78 |
- } |
|
| 79 |
- if len(problemCommits) > 0 {
|
|
| 80 |
- label := "The following UPSTREAM commits modify more than one repo in their changelist" |
|
| 81 |
- msg := renderGodepFilesError(label, problemCommits, RenderOnlyGodepsFiles) |
|
| 82 |
- return fmt.Errorf(msg) |
|
| 83 |
- } |
|
| 84 |
- return nil |
|
| 85 |
-} |
|
| 86 |
- |
|
| 87 |
-// ValidateUpstreamCommitSummaries ensures that any commits which declare to |
|
| 88 |
-// be upstream match the regular expressions for UPSTREAM summaries. |
|
| 89 |
-func ValidateUpstreamCommitSummaries(commits []util.Commit) error {
|
|
| 90 |
- problemCommits := []util.Commit{}
|
|
| 91 |
- for _, commit := range commits {
|
|
| 92 |
- if commit.DeclaresUpstreamChange() && !commit.MatchesUpstreamSummaryPattern() {
|
|
| 93 |
- problemCommits = append(problemCommits, commit) |
|
| 94 |
- } |
|
| 95 |
- } |
|
| 96 |
- if len(problemCommits) > 0 {
|
|
| 97 |
- tmpl, _ := template.New("problems").Parse(CommitSummaryErrorTemplate)
|
|
| 98 |
- data := struct {
|
|
| 99 |
- Pattern *regexp.Regexp |
|
| 100 |
- Commits []util.Commit |
|
| 101 |
- }{
|
|
| 102 |
- Pattern: util.UpstreamSummaryPattern, |
|
| 103 |
- Commits: problemCommits, |
|
| 104 |
- } |
|
| 105 |
- buffer := &bytes.Buffer{}
|
|
| 106 |
- tmpl.Execute(buffer, data) |
|
| 107 |
- return fmt.Errorf(buffer.String()) |
|
| 108 |
- } |
|
| 109 |
- return nil |
|
| 110 |
-} |
|
| 111 |
- |
|
| 112 |
-// ValidateUpstreamCommitModifiesOnlyGodeps ensures that any Godeps commits |
|
| 113 |
-// modify ONLY Godeps files. |
|
| 114 |
-func ValidateUpstreamCommitModifiesOnlyGodeps(commits []util.Commit) error {
|
|
| 115 |
- problemCommits := []util.Commit{}
|
|
| 116 |
- for _, commit := range commits {
|
|
| 117 |
- if commit.HasGodepsChanges() && commit.HasNonGodepsChanges() {
|
|
| 118 |
- problemCommits = append(problemCommits, commit) |
|
| 119 |
- } |
|
| 120 |
- } |
|
| 121 |
- if len(problemCommits) > 0 {
|
|
| 122 |
- label := "The following UPSTREAM commits modify files outside Godeps" |
|
| 123 |
- msg := renderGodepFilesError(label, problemCommits, RenderAllFiles) |
|
| 124 |
- return fmt.Errorf(msg) |
|
| 125 |
- } |
|
| 126 |
- return nil |
|
| 127 |
-} |
|
| 128 |
- |
|
| 129 |
-// ValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo ensures that an |
|
| 130 |
-// upstream commit only modifies the Godep repo the summary declares. |
|
| 131 |
-func ValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo(commits []util.Commit) error {
|
|
| 132 |
- problemCommits := []util.Commit{}
|
|
| 133 |
- for _, commit := range commits {
|
|
| 134 |
- if commit.DeclaresUpstreamChange() {
|
|
| 135 |
- declaredRepo, err := commit.DeclaredUpstreamRepo() |
|
| 136 |
- if err != nil {
|
|
| 137 |
- return err |
|
| 138 |
- } |
|
| 139 |
- reposChanged, err := commit.GodepsReposChanged() |
|
| 140 |
- if err != nil {
|
|
| 141 |
- return err |
|
| 142 |
- } |
|
| 143 |
- for _, changedRepo := range reposChanged {
|
|
| 144 |
- if !strings.Contains(changedRepo, declaredRepo) {
|
|
| 145 |
- problemCommits = append(problemCommits, commit) |
|
| 146 |
- } |
|
| 147 |
- } |
|
| 148 |
- } |
|
| 149 |
- } |
|
| 150 |
- if len(problemCommits) > 0 {
|
|
| 151 |
- label := "The following UPSTREAM commits modify Godeps repos other than the repo the commit declares" |
|
| 152 |
- msg := renderGodepFilesError(label, problemCommits, RenderAllFiles) |
|
| 153 |
- return fmt.Errorf(msg) |
|
| 154 |
- } |
|
| 155 |
- return nil |
|
| 156 |
-} |
|
| 157 |
- |
|
| 158 |
-type CommitFilesRenderOption int |
|
| 159 |
- |
|
| 160 |
-const ( |
|
| 161 |
- RenderNoFiles CommitFilesRenderOption = iota |
|
| 162 |
- RenderOnlyGodepsFiles |
|
| 163 |
- RenderOnlyNonGodepsFiles |
|
| 164 |
- RenderAllFiles |
|
| 165 |
-) |
|
| 166 |
- |
|
| 167 |
-// renderGodepFilesError formats commits and their file lists into readable |
|
| 168 |
-// output prefixed with label. |
|
| 169 |
-func renderGodepFilesError(label string, commits []util.Commit, opt CommitFilesRenderOption) string {
|
|
| 170 |
- msg := fmt.Sprintf("%s:\n\n", label)
|
|
| 171 |
- for _, commit := range commits {
|
|
| 172 |
- msg += fmt.Sprintf("[%s] %s\n", commit.Sha, commit.Summary)
|
|
| 173 |
- if opt == RenderNoFiles {
|
|
| 174 |
- continue |
|
| 175 |
- } |
|
| 176 |
- for _, file := range commit.Files {
|
|
| 177 |
- if opt == RenderAllFiles || |
|
| 178 |
- (opt == RenderOnlyGodepsFiles && file.HasGodepsChanges()) || |
|
| 179 |
- (opt == RenderOnlyNonGodepsFiles && !file.HasGodepsChanges()) {
|
|
| 180 |
- msg += fmt.Sprintf(" - %s\n", file)
|
|
| 181 |
- } |
|
| 182 |
- } |
|
| 183 |
- } |
|
| 184 |
- return msg |
|
| 185 |
-} |
| 186 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,379 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "testing" |
|
| 5 |
- |
|
| 6 |
- "github.com/openshift/origin/cmd/rebasehelpers/util" |
|
| 7 |
-) |
|
| 8 |
- |
|
| 9 |
-func TestValidateUpstreamCommitsWithoutGodepsChanges(t *testing.T) {
|
|
| 10 |
- tests := []struct {
|
|
| 11 |
- name string |
|
| 12 |
- commits []util.Commit |
|
| 13 |
- errorExpected bool |
|
| 14 |
- }{
|
|
| 15 |
- {
|
|
| 16 |
- name: "test 1", |
|
| 17 |
- commits: []util.Commit{
|
|
| 18 |
- {
|
|
| 19 |
- Sha: "aaa0000", |
|
| 20 |
- Summary: "commit 1", |
|
| 21 |
- Files: []util.File{"file1", "pkg/file2"},
|
|
| 22 |
- }, |
|
| 23 |
- {
|
|
| 24 |
- Sha: "aaa0001", |
|
| 25 |
- Summary: "commit 2", |
|
| 26 |
- Files: []util.File{"Godeps/file1", "pkg/file2"},
|
|
| 27 |
- }, |
|
| 28 |
- }, |
|
| 29 |
- errorExpected: true, |
|
| 30 |
- }, |
|
| 31 |
- {
|
|
| 32 |
- name: "test 2", |
|
| 33 |
- commits: []util.Commit{
|
|
| 34 |
- {
|
|
| 35 |
- Sha: "aaa0000", |
|
| 36 |
- Summary: "commit 1", |
|
| 37 |
- Files: []util.File{"file1", "pkg/file2"},
|
|
| 38 |
- }, |
|
| 39 |
- {
|
|
| 40 |
- Sha: "aaa0001", |
|
| 41 |
- Summary: "UPSTREAM: commit 2", |
|
| 42 |
- Files: []util.File{"Godeps/file1", "pkg/file2"},
|
|
| 43 |
- }, |
|
| 44 |
- }, |
|
| 45 |
- errorExpected: false, |
|
| 46 |
- }, |
|
| 47 |
- } |
|
| 48 |
- for _, test := range tests {
|
|
| 49 |
- t.Logf("evaluating test %q", test.name)
|
|
| 50 |
- err := ValidateUpstreamCommitsWithoutGodepsChanges(test.commits) |
|
| 51 |
- if err != nil {
|
|
| 52 |
- if test.errorExpected {
|
|
| 53 |
- t.Logf("got expected error:\n%s", err)
|
|
| 54 |
- continue |
|
| 55 |
- } else {
|
|
| 56 |
- t.Fatalf("unexpected error:\n%s", err)
|
|
| 57 |
- } |
|
| 58 |
- } else {
|
|
| 59 |
- if test.errorExpected {
|
|
| 60 |
- t.Fatalf("expected an error, got none")
|
|
| 61 |
- } |
|
| 62 |
- } |
|
| 63 |
- } |
|
| 64 |
-} |
|
| 65 |
- |
|
| 66 |
-func TestValidateUpstreamCommitModifiesSingleGodepsRepo(t *testing.T) {
|
|
| 67 |
- tests := []struct {
|
|
| 68 |
- name string |
|
| 69 |
- commits []util.Commit |
|
| 70 |
- errorExpected bool |
|
| 71 |
- }{
|
|
| 72 |
- {
|
|
| 73 |
- name: "test 1", |
|
| 74 |
- commits: []util.Commit{
|
|
| 75 |
- {
|
|
| 76 |
- Sha: "aaa0000", |
|
| 77 |
- Summary: "commit 1", |
|
| 78 |
- Files: []util.File{"file1", "pkg/file2"},
|
|
| 79 |
- }, |
|
| 80 |
- {
|
|
| 81 |
- Sha: "aaa0001", |
|
| 82 |
- Summary: "commit 2", |
|
| 83 |
- Files: []util.File{
|
|
| 84 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 85 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 86 |
- }, |
|
| 87 |
- }, |
|
| 88 |
- }, |
|
| 89 |
- errorExpected: false, |
|
| 90 |
- }, |
|
| 91 |
- {
|
|
| 92 |
- name: "test 2", |
|
| 93 |
- commits: []util.Commit{
|
|
| 94 |
- {
|
|
| 95 |
- Sha: "aaa0000", |
|
| 96 |
- Summary: "commit 1", |
|
| 97 |
- Files: []util.File{"file1", "pkg/file2"},
|
|
| 98 |
- }, |
|
| 99 |
- {
|
|
| 100 |
- Sha: "aaa0001", |
|
| 101 |
- Summary: "UPSTREAM: commit 2", |
|
| 102 |
- Files: []util.File{
|
|
| 103 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 104 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 105 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file", |
|
| 106 |
- }, |
|
| 107 |
- }, |
|
| 108 |
- {
|
|
| 109 |
- Sha: "aaa0002", |
|
| 110 |
- Summary: "UPSTREAM: commit 3", |
|
| 111 |
- Files: []util.File{
|
|
| 112 |
- "Godeps/_workspace/src/k8s.io/heapster/file1", |
|
| 113 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 114 |
- }, |
|
| 115 |
- }, |
|
| 116 |
- }, |
|
| 117 |
- errorExpected: true, |
|
| 118 |
- }, |
|
| 119 |
- } |
|
| 120 |
- for _, test := range tests {
|
|
| 121 |
- t.Logf("evaluating test %q", test.name)
|
|
| 122 |
- err := ValidateUpstreamCommitModifiesSingleGodepsRepo(test.commits) |
|
| 123 |
- if err != nil {
|
|
| 124 |
- if test.errorExpected {
|
|
| 125 |
- t.Logf("got expected error:\n%s", err)
|
|
| 126 |
- continue |
|
| 127 |
- } else {
|
|
| 128 |
- t.Fatalf("unexpected error:\n%s", err)
|
|
| 129 |
- } |
|
| 130 |
- } else {
|
|
| 131 |
- if test.errorExpected {
|
|
| 132 |
- t.Fatalf("expected an error, got none")
|
|
| 133 |
- } |
|
| 134 |
- } |
|
| 135 |
- } |
|
| 136 |
-} |
|
| 137 |
- |
|
| 138 |
-func TestValidateUpstreamCommitModifiesOnlyGodeps(t *testing.T) {
|
|
| 139 |
- tests := []struct {
|
|
| 140 |
- name string |
|
| 141 |
- commits []util.Commit |
|
| 142 |
- errorExpected bool |
|
| 143 |
- }{
|
|
| 144 |
- {
|
|
| 145 |
- name: "test 1", |
|
| 146 |
- commits: []util.Commit{
|
|
| 147 |
- {
|
|
| 148 |
- Sha: "aaa0000", |
|
| 149 |
- Summary: "commit 1", |
|
| 150 |
- Files: []util.File{"file1", "pkg/file2"},
|
|
| 151 |
- }, |
|
| 152 |
- {
|
|
| 153 |
- Sha: "aaa0001", |
|
| 154 |
- Summary: "UPSTREAM: commit 2", |
|
| 155 |
- Files: []util.File{
|
|
| 156 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 157 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 158 |
- "pkg/some_file", |
|
| 159 |
- }, |
|
| 160 |
- }, |
|
| 161 |
- }, |
|
| 162 |
- errorExpected: true, |
|
| 163 |
- }, |
|
| 164 |
- {
|
|
| 165 |
- name: "test 2", |
|
| 166 |
- commits: []util.Commit{
|
|
| 167 |
- {
|
|
| 168 |
- Sha: "aaa0000", |
|
| 169 |
- Summary: "commit 1", |
|
| 170 |
- Files: []util.File{"file1", "pkg/file2"},
|
|
| 171 |
- }, |
|
| 172 |
- {
|
|
| 173 |
- Sha: "aaa0001", |
|
| 174 |
- Summary: "UPSTREAM: commit 2", |
|
| 175 |
- Files: []util.File{
|
|
| 176 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 177 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 178 |
- }, |
|
| 179 |
- }, |
|
| 180 |
- }, |
|
| 181 |
- errorExpected: false, |
|
| 182 |
- }, |
|
| 183 |
- } |
|
| 184 |
- for _, test := range tests {
|
|
| 185 |
- t.Logf("evaluating test %q", test.name)
|
|
| 186 |
- err := ValidateUpstreamCommitModifiesOnlyGodeps(test.commits) |
|
| 187 |
- if err != nil {
|
|
| 188 |
- if test.errorExpected {
|
|
| 189 |
- t.Logf("got expected error:\n%s", err)
|
|
| 190 |
- continue |
|
| 191 |
- } else {
|
|
| 192 |
- t.Fatalf("unexpected error:\n%s", err)
|
|
| 193 |
- } |
|
| 194 |
- } else {
|
|
| 195 |
- if test.errorExpected {
|
|
| 196 |
- t.Fatalf("expected an error, got none")
|
|
| 197 |
- } |
|
| 198 |
- } |
|
| 199 |
- } |
|
| 200 |
-} |
|
| 201 |
- |
|
| 202 |
-func TestValidateUpstreamCommitSummaries(t *testing.T) {
|
|
| 203 |
- tests := []struct {
|
|
| 204 |
- summary string |
|
| 205 |
- valid bool |
|
| 206 |
- }{
|
|
| 207 |
- {valid: true, summary: "UPSTREAM: 12345: a change"},
|
|
| 208 |
- {valid: true, summary: "UPSTREAM: k8s.io/heapster: 12345: a change"},
|
|
| 209 |
- {valid: true, summary: "UPSTREAM: <carry>: a change"},
|
|
| 210 |
- {valid: true, summary: "UPSTREAM: <drop>: a change"},
|
|
| 211 |
- {valid: true, summary: "UPSTREAM: coreos/etcd: <carry>: a change"},
|
|
| 212 |
- {valid: true, summary: "UPSTREAM: coreos/etcd: <drop>: a change"},
|
|
| 213 |
- {valid: true, summary: "UPSTREAM: revert: abcd123: 12345: a change"},
|
|
| 214 |
- {valid: true, summary: "UPSTREAM: revert: abcd123: k8s.io/heapster: 12345: a change"},
|
|
| 215 |
- {valid: true, summary: "UPSTREAM: revert: abcd123: <carry>: a change"},
|
|
| 216 |
- {valid: true, summary: "UPSTREAM: revert: abcd123: <drop>: a change"},
|
|
| 217 |
- {valid: true, summary: "UPSTREAM: revert: abcd123: coreos/etcd: <carry>: a change"},
|
|
| 218 |
- {valid: true, summary: "UPSTREAM: revert: abcd123: coreos/etcd: <drop>: a change"},
|
|
| 219 |
- {valid: false, summary: "UPSTREAM: whoopsie daisy"},
|
|
| 220 |
- } |
|
| 221 |
- for _, test := range tests {
|
|
| 222 |
- commit := util.Commit{Summary: test.summary, Sha: "abcd000"}
|
|
| 223 |
- err := ValidateUpstreamCommitSummaries([]util.Commit{commit})
|
|
| 224 |
- if err != nil {
|
|
| 225 |
- if test.valid {
|
|
| 226 |
- t.Fatalf("unexpected error:\n%s", err)
|
|
| 227 |
- } else {
|
|
| 228 |
- t.Logf("got expected error:\n%s", err)
|
|
| 229 |
- } |
|
| 230 |
- } else {
|
|
| 231 |
- if !test.valid {
|
|
| 232 |
- t.Fatalf("expected an error, got none; summary: %s", test.summary)
|
|
| 233 |
- } |
|
| 234 |
- } |
|
| 235 |
- } |
|
| 236 |
-} |
|
| 237 |
- |
|
| 238 |
-func TestValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo(t *testing.T) {
|
|
| 239 |
- tests := []struct {
|
|
| 240 |
- name string |
|
| 241 |
- commits []util.Commit |
|
| 242 |
- errorExpected bool |
|
| 243 |
- }{
|
|
| 244 |
- {
|
|
| 245 |
- name: "test 1", |
|
| 246 |
- commits: []util.Commit{
|
|
| 247 |
- {
|
|
| 248 |
- Sha: "aaa0000", |
|
| 249 |
- Summary: "commit 1", |
|
| 250 |
- Files: []util.File{"file1", "pkg/file2"},
|
|
| 251 |
- }, |
|
| 252 |
- {
|
|
| 253 |
- Sha: "aaa0001", |
|
| 254 |
- Summary: "UPSTREAM: coreos/etcd: 12345: a change", |
|
| 255 |
- Files: []util.File{
|
|
| 256 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 257 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 258 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 259 |
- }, |
|
| 260 |
- }, |
|
| 261 |
- }, |
|
| 262 |
- errorExpected: true, |
|
| 263 |
- }, |
|
| 264 |
- {
|
|
| 265 |
- name: "test 2", |
|
| 266 |
- commits: []util.Commit{
|
|
| 267 |
- {
|
|
| 268 |
- Sha: "aaa0001", |
|
| 269 |
- Summary: "UPSTREAM: coreos/etcd: 12345: a change", |
|
| 270 |
- Files: []util.File{
|
|
| 271 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 272 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file2", |
|
| 273 |
- }, |
|
| 274 |
- }, |
|
| 275 |
- }, |
|
| 276 |
- errorExpected: false, |
|
| 277 |
- }, |
|
| 278 |
- {
|
|
| 279 |
- name: "test three segments", |
|
| 280 |
- commits: []util.Commit{
|
|
| 281 |
- {
|
|
| 282 |
- Sha: "aaa0001", |
|
| 283 |
- Summary: "UPSTREAM: coreos/etcd: 12345: a change", |
|
| 284 |
- Files: []util.File{
|
|
| 285 |
- "Godeps/_workspace/src/github.com/coreos/etcd/a/file1", |
|
| 286 |
- "Godeps/_workspace/src/github.com/coreos/etcd/b/file2", |
|
| 287 |
- }, |
|
| 288 |
- }, |
|
| 289 |
- }, |
|
| 290 |
- errorExpected: false, |
|
| 291 |
- }, |
|
| 292 |
- {
|
|
| 293 |
- name: "test 3", |
|
| 294 |
- commits: []util.Commit{
|
|
| 295 |
- {
|
|
| 296 |
- Sha: "aaa0001", |
|
| 297 |
- Summary: "UPSTREAM: 12345: a change", |
|
| 298 |
- Files: []util.File{
|
|
| 299 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 300 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 301 |
- }, |
|
| 302 |
- }, |
|
| 303 |
- }, |
|
| 304 |
- errorExpected: false, |
|
| 305 |
- }, |
|
| 306 |
- {
|
|
| 307 |
- name: "test 4", |
|
| 308 |
- commits: []util.Commit{
|
|
| 309 |
- {
|
|
| 310 |
- Sha: "aaa0001", |
|
| 311 |
- Summary: "UPSTREAM: 12345: a change", |
|
| 312 |
- Files: []util.File{
|
|
| 313 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 314 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file2", |
|
| 315 |
- }, |
|
| 316 |
- }, |
|
| 317 |
- }, |
|
| 318 |
- errorExpected: true, |
|
| 319 |
- }, |
|
| 320 |
- {
|
|
| 321 |
- name: "test 5", |
|
| 322 |
- commits: []util.Commit{
|
|
| 323 |
- {
|
|
| 324 |
- Sha: "aaa0001", |
|
| 325 |
- Summary: "UPSTREAM: revert: abcd000: 12345: a change", |
|
| 326 |
- Files: []util.File{
|
|
| 327 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 328 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 329 |
- }, |
|
| 330 |
- }, |
|
| 331 |
- }, |
|
| 332 |
- errorExpected: false, |
|
| 333 |
- }, |
|
| 334 |
- {
|
|
| 335 |
- name: "test 6", |
|
| 336 |
- commits: []util.Commit{
|
|
| 337 |
- {
|
|
| 338 |
- Sha: "aaa0001", |
|
| 339 |
- Summary: "UPSTREAM: revert: abcd000: coreos/etcd: 12345: a change", |
|
| 340 |
- Files: []util.File{
|
|
| 341 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 342 |
- "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 343 |
- }, |
|
| 344 |
- }, |
|
| 345 |
- }, |
|
| 346 |
- errorExpected: true, |
|
| 347 |
- }, |
|
| 348 |
- {
|
|
| 349 |
- name: "test 7", |
|
| 350 |
- commits: []util.Commit{
|
|
| 351 |
- {
|
|
| 352 |
- Sha: "aaa0001", |
|
| 353 |
- Summary: "UPSTREAM: revert: abcd000: coreos/etcd: 12345: a change", |
|
| 354 |
- Files: []util.File{
|
|
| 355 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 356 |
- "Godeps/_workspace/src/github.com/coreos/etcd/file2", |
|
| 357 |
- }, |
|
| 358 |
- }, |
|
| 359 |
- }, |
|
| 360 |
- errorExpected: false, |
|
| 361 |
- }, |
|
| 362 |
- } |
|
| 363 |
- for _, test := range tests {
|
|
| 364 |
- t.Logf("evaluating test %q", test.name)
|
|
| 365 |
- err := ValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo(test.commits) |
|
| 366 |
- if err != nil {
|
|
| 367 |
- if test.errorExpected {
|
|
| 368 |
- t.Logf("got expected error:\n%s", err)
|
|
| 369 |
- continue |
|
| 370 |
- } else {
|
|
| 371 |
- t.Fatalf("unexpected error:\n%s", err)
|
|
| 372 |
- } |
|
| 373 |
- } else {
|
|
| 374 |
- if test.errorExpected {
|
|
| 375 |
- t.Fatalf("expected an error, got none")
|
|
| 376 |
- } |
|
| 377 |
- } |
|
| 378 |
- } |
|
| 379 |
-} |
| 380 | 1 |
deleted file mode 100644 |
| ... | ... |
@@ -1,200 +0,0 @@ |
| 1 |
-package util |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "bytes" |
|
| 5 |
- "fmt" |
|
| 6 |
- "os" |
|
| 7 |
- "os/exec" |
|
| 8 |
- "regexp" |
|
| 9 |
- "strings" |
|
| 10 |
-) |
|
| 11 |
- |
|
| 12 |
-var UpstreamSummaryPattern = regexp.MustCompile(`UPSTREAM: (revert: [a-f0-9]{7,}: )?(([\w\.-]+\/[\w-]+)?: )?(\d+:|<carry>:|<drop>:)`)
|
|
| 13 |
- |
|
| 14 |
-// supportedHosts maps source hosts to the number of path segments that |
|
| 15 |
-// represent the account/repo for that host. This is necessary because we |
|
| 16 |
-// can't tell just by looking at an import path whether the repo is identified |
|
| 17 |
-// by the first 2 or 3 path segments. |
|
| 18 |
-// |
|
| 19 |
-// If dependencies are introduced from new hosts, they'll need to be added |
|
| 20 |
-// here. |
|
| 21 |
-var SupportedHosts = map[string]int{
|
|
| 22 |
- "bitbucket.org": 3, |
|
| 23 |
- "code.google.com": 3, |
|
| 24 |
- "github.com": 3, |
|
| 25 |
- "golang.org": 3, |
|
| 26 |
- "google.golang.org": 2, |
|
| 27 |
- "gopkg.in": 2, |
|
| 28 |
- "k8s.io": 2, |
|
| 29 |
- "speter.net": 2, |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-type Commit struct {
|
|
| 33 |
- Sha string |
|
| 34 |
- Summary string |
|
| 35 |
- Files []File |
|
| 36 |
-} |
|
| 37 |
- |
|
| 38 |
-func (c Commit) DeclaresUpstreamChange() bool {
|
|
| 39 |
- return strings.HasPrefix(strings.ToLower(c.Summary), "upstream") |
|
| 40 |
-} |
|
| 41 |
- |
|
| 42 |
-func (c Commit) MatchesUpstreamSummaryPattern() bool {
|
|
| 43 |
- return UpstreamSummaryPattern.MatchString(c.Summary) |
|
| 44 |
-} |
|
| 45 |
- |
|
| 46 |
-func (c Commit) DeclaredUpstreamRepo() (string, error) {
|
|
| 47 |
- if !c.DeclaresUpstreamChange() {
|
|
| 48 |
- return "", fmt.Errorf("commit declares no upstream changes")
|
|
| 49 |
- } |
|
| 50 |
- if !c.MatchesUpstreamSummaryPattern() {
|
|
| 51 |
- return "", fmt.Errorf("commit doesn't match the upstream commit summary pattern")
|
|
| 52 |
- } |
|
| 53 |
- groups := UpstreamSummaryPattern.FindStringSubmatch(c.Summary) |
|
| 54 |
- repo := groups[3] |
|
| 55 |
- if len(repo) == 0 {
|
|
| 56 |
- repo = "k8s.io/kubernetes" |
|
| 57 |
- } |
|
| 58 |
- return repo, nil |
|
| 59 |
-} |
|
| 60 |
- |
|
| 61 |
-func (c Commit) HasGodepsChanges() bool {
|
|
| 62 |
- for _, file := range c.Files {
|
|
| 63 |
- if file.HasGodepsChanges() {
|
|
| 64 |
- return true |
|
| 65 |
- } |
|
| 66 |
- } |
|
| 67 |
- return false |
|
| 68 |
-} |
|
| 69 |
- |
|
| 70 |
-func (c Commit) HasNonGodepsChanges() bool {
|
|
| 71 |
- for _, file := range c.Files {
|
|
| 72 |
- if !file.HasGodepsChanges() {
|
|
| 73 |
- return true |
|
| 74 |
- } |
|
| 75 |
- } |
|
| 76 |
- return false |
|
| 77 |
-} |
|
| 78 |
- |
|
| 79 |
-func (c Commit) GodepsReposChanged() ([]string, error) {
|
|
| 80 |
- repos := map[string]struct{}{}
|
|
| 81 |
- for _, file := range c.Files {
|
|
| 82 |
- if !file.HasGodepsChanges() {
|
|
| 83 |
- continue |
|
| 84 |
- } |
|
| 85 |
- repo, err := file.GodepsRepoChanged() |
|
| 86 |
- if err != nil {
|
|
| 87 |
- return nil, fmt.Errorf("problem with file %q in commit %s: %s", file, c.Sha, err)
|
|
| 88 |
- } |
|
| 89 |
- repos[repo] = struct{}{}
|
|
| 90 |
- } |
|
| 91 |
- changed := []string{}
|
|
| 92 |
- for repo := range repos {
|
|
| 93 |
- changed = append(changed, repo) |
|
| 94 |
- } |
|
| 95 |
- return changed, nil |
|
| 96 |
-} |
|
| 97 |
- |
|
| 98 |
-type File string |
|
| 99 |
- |
|
| 100 |
-func (f File) HasGodepsChanges() bool {
|
|
| 101 |
- return strings.HasPrefix(string(f), "Godeps") |
|
| 102 |
-} |
|
| 103 |
- |
|
| 104 |
-func (f File) GodepsRepoChanged() (string, error) {
|
|
| 105 |
- if !f.HasGodepsChanges() {
|
|
| 106 |
- return "", fmt.Errorf("file doesn't appear to be a Godeps change")
|
|
| 107 |
- } |
|
| 108 |
- // Find the _workspace path segment index. |
|
| 109 |
- workspaceIdx := -1 |
|
| 110 |
- parts := strings.Split(string(f), string(os.PathSeparator)) |
|
| 111 |
- for i, part := range parts {
|
|
| 112 |
- if part == "_workspace" {
|
|
| 113 |
- workspaceIdx = i |
|
| 114 |
- break |
|
| 115 |
- } |
|
| 116 |
- } |
|
| 117 |
- // Godeps path struture assumption: Godeps/_workspace/src/... |
|
| 118 |
- if workspaceIdx == -1 || len(parts) < (workspaceIdx+3) {
|
|
| 119 |
- return "", fmt.Errorf("file doesn't appear to be a Godeps workspace path")
|
|
| 120 |
- } |
|
| 121 |
- // Deal with repos which could be identified by either 2 or 3 path segments. |
|
| 122 |
- host := parts[workspaceIdx+2] |
|
| 123 |
- segments := -1 |
|
| 124 |
- for supportedHost, count := range SupportedHosts {
|
|
| 125 |
- if host == supportedHost {
|
|
| 126 |
- segments = count |
|
| 127 |
- break |
|
| 128 |
- } |
|
| 129 |
- } |
|
| 130 |
- if segments == -1 {
|
|
| 131 |
- return "", fmt.Errorf("file modifies an unsupported repo host %q", host)
|
|
| 132 |
- } |
|
| 133 |
- switch segments {
|
|
| 134 |
- case 2: |
|
| 135 |
- return fmt.Sprintf("%s/%s", host, parts[workspaceIdx+3]), nil
|
|
| 136 |
- case 3: |
|
| 137 |
- return fmt.Sprintf("%s/%s/%s", host, parts[workspaceIdx+3], parts[workspaceIdx+4]), nil
|
|
| 138 |
- } |
|
| 139 |
- return "", fmt.Errorf("file modifies an unsupported repo host %q", host)
|
|
| 140 |
-} |
|
| 141 |
- |
|
| 142 |
-func CommitsBetween(a, b string) ([]Commit, error) {
|
|
| 143 |
- commits := []Commit{}
|
|
| 144 |
- stdout, _, err := run("git", "log", "--oneline", fmt.Sprintf("%s..%s", a, b))
|
|
| 145 |
- if err != nil {
|
|
| 146 |
- return nil, fmt.Errorf("error executing git log: %s", err)
|
|
| 147 |
- } |
|
| 148 |
- for _, log := range strings.Split(stdout, "\n") {
|
|
| 149 |
- if len(log) == 0 {
|
|
| 150 |
- continue |
|
| 151 |
- } |
|
| 152 |
- commit, err := NewCommitFromOnelineLog(log) |
|
| 153 |
- if err != nil {
|
|
| 154 |
- return nil, err |
|
| 155 |
- } |
|
| 156 |
- commits = append(commits, commit) |
|
| 157 |
- } |
|
| 158 |
- return commits, nil |
|
| 159 |
-} |
|
| 160 |
- |
|
| 161 |
-func NewCommitFromOnelineLog(log string) (Commit, error) {
|
|
| 162 |
- var commit Commit |
|
| 163 |
- parts := strings.Split(log, " ") |
|
| 164 |
- if len(parts) < 2 {
|
|
| 165 |
- return commit, fmt.Errorf("invalid log entry: %s", log)
|
|
| 166 |
- } |
|
| 167 |
- commit.Sha = parts[0] |
|
| 168 |
- commit.Summary = strings.Join(parts[1:], " ") |
|
| 169 |
- files, err := filesInCommit(commit.Sha) |
|
| 170 |
- if err != nil {
|
|
| 171 |
- return commit, err |
|
| 172 |
- } |
|
| 173 |
- commit.Files = files |
|
| 174 |
- return commit, nil |
|
| 175 |
-} |
|
| 176 |
- |
|
| 177 |
-func filesInCommit(sha string) ([]File, error) {
|
|
| 178 |
- files := []File{}
|
|
| 179 |
- stdout, _, err := run("git", "diff-tree", "--no-commit-id", "--name-only", "-r", sha)
|
|
| 180 |
- if err != nil {
|
|
| 181 |
- return nil, err |
|
| 182 |
- } |
|
| 183 |
- for _, filename := range strings.Split(stdout, "\n") {
|
|
| 184 |
- if len(filename) == 0 {
|
|
| 185 |
- continue |
|
| 186 |
- } |
|
| 187 |
- files = append(files, File(filename)) |
|
| 188 |
- } |
|
| 189 |
- return files, nil |
|
| 190 |
-} |
|
| 191 |
- |
|
| 192 |
-func run(args ...string) (string, string, error) {
|
|
| 193 |
- cmd := exec.Command(args[0], args[1:]...) |
|
| 194 |
- var stdout bytes.Buffer |
|
| 195 |
- var stderr bytes.Buffer |
|
| 196 |
- cmd.Stdout = &stdout |
|
| 197 |
- cmd.Stderr = &stderr |
|
| 198 |
- err := cmd.Run() |
|
| 199 |
- return stdout.String(), stderr.String(), err |
|
| 200 |
-} |
| ... | ... |
@@ -32,7 +32,7 @@ if [[ ! -d "${UPSTREAM_REPO_LOCATION}" ]]; then
|
| 32 | 32 |
fi |
| 33 | 33 |
|
| 34 | 34 |
if [[ -z "${NO_REBASE-}" ]]; then
|
| 35 |
- lastrev="$(go run ${OS_ROOT}/hack/version.go ${OS_ROOT}/Godeps/Godeps.json ${repo}/${package})"
|
|
| 35 |
+ lastrev="$(go run ${OS_ROOT}/tools/godepversion/godepversion.go ${OS_ROOT}/Godeps/Godeps.json ${repo}/${package})"
|
|
| 36 | 36 |
fi |
| 37 | 37 |
|
| 38 | 38 |
pushd "${UPSTREAM_REPO_LOCATION}" > /dev/null
|
| ... | ... |
@@ -518,8 +518,8 @@ os::build::os_version_vars() {
|
| 518 | 518 |
# os::build::kube_version_vars returns the version of Kubernetes we have |
| 519 | 519 |
# vendored. |
| 520 | 520 |
os::build::kube_version_vars() {
|
| 521 |
- KUBE_GIT_VERSION=$(go run "${OS_ROOT}/hack/version.go" "${OS_ROOT}/Godeps/Godeps.json" "k8s.io/kubernetes/pkg/api" "comment")
|
|
| 522 |
- KUBE_GIT_COMMIT=$(go run "${OS_ROOT}/hack/version.go" "${OS_ROOT}/Godeps/Godeps.json" "k8s.io/kubernetes/pkg/api")
|
|
| 521 |
+ KUBE_GIT_VERSION=$(go run "${OS_ROOT}/tools/godepversion/godepversion.go" "${OS_ROOT}/Godeps/Godeps.json" "k8s.io/kubernetes/pkg/api" "comment")
|
|
| 522 |
+ KUBE_GIT_COMMIT=$(go run "${OS_ROOT}/tools/godepversion/godepversion.go" "${OS_ROOT}/Godeps/Godeps.json" "k8s.io/kubernetes/pkg/api")
|
|
| 523 | 523 |
} |
| 524 | 524 |
|
| 525 | 525 |
# Saves the environment flags to $1 |
| ... | ... |
@@ -10,7 +10,7 @@ OS_ROOT=$(dirname "${BASH_SOURCE}")/..
|
| 10 | 10 |
source "${OS_ROOT}/hack/util.sh"
|
| 11 | 11 |
os::log::install_errexit |
| 12 | 12 |
|
| 13 |
-etcd_version=$(go run ${OS_ROOT}/hack/version.go ${OS_ROOT}/Godeps/Godeps.json github.com/coreos/etcd/etcdserver)
|
|
| 13 |
+etcd_version=$(go run ${OS_ROOT}/tools/godepversion/godepversion.go ${OS_ROOT}/Godeps/Godeps.json github.com/coreos/etcd/etcdserver)
|
|
| 14 | 14 |
|
| 15 | 15 |
mkdir -p "${OS_ROOT}/_tools"
|
| 16 | 16 |
cd "${OS_ROOT}/_tools"
|
| ... | ... |
@@ -25,7 +25,7 @@ if [[ ! -d "${relativedir}" ]]; then
|
| 25 | 25 |
fi |
| 26 | 26 |
|
| 27 | 27 |
if [[ -z "${NO_REBASE-}" ]]; then
|
| 28 |
- lastrev="$(go run ${OS_ROOT}/hack/version.go ${OS_ROOT}/Godeps/Godeps.json ${repo}/${package})"
|
|
| 28 |
+ lastrev="$(go run ${OS_ROOT}/tools/godepversion/godepversion.go ${OS_ROOT}/Godeps/Godeps.json ${repo}/${package})"
|
|
| 29 | 29 |
fi |
| 30 | 30 |
|
| 31 | 31 |
branch="$(git rev-parse --abbrev-ref HEAD)" |
| ... | ... |
@@ -15,7 +15,7 @@ if [[ "${platform}" != "linux/amd64" ]]; then
|
| 15 | 15 |
exit 1 |
| 16 | 16 |
fi |
| 17 | 17 |
|
| 18 |
-"${OS_ROOT}/hack/build-go.sh" cmd/genbashcomp
|
|
| 18 |
+"${OS_ROOT}/hack/build-go.sh" tools/genbashcomp
|
|
| 19 | 19 |
|
| 20 | 20 |
# Find binary |
| 21 | 21 |
genbashcomp="$(os::build::find-binary genbashcomp)" |
| ... | ... |
@@ -25,7 +25,7 @@ if [[ ! "$genbashcomp" ]]; then |
| 25 | 25 |
echo "It looks as if you don't have a compiled genbashcomp binary" |
| 26 | 26 |
echo |
| 27 | 27 |
echo "If you are running from a clone of the git repo, please run" |
| 28 |
- echo "'./hack/build-go.sh cmd/genbashcomp'." |
|
| 28 |
+ echo "'./hack/build-go.sh tools/genbashcomp'." |
|
| 29 | 29 |
} >&2 |
| 30 | 30 |
exit 1 |
| 31 | 31 |
fi |
| ... | ... |
@@ -24,7 +24,7 @@ package ${version}
|
| 24 | 24 |
// AUTO-GENERATED FUNCTIONS START HERE |
| 25 | 25 |
EOF |
| 26 | 26 |
|
| 27 |
- go run cmd/genconversion/conversion.go -v ${version} -f - >> $TMPFILE
|
|
| 27 |
+ go run tools/genconversion/conversion.go -v ${version} -f - >> $TMPFILE
|
|
| 28 | 28 |
|
| 29 | 29 |
cat >> $TMPFILE <<EOF |
| 30 | 30 |
// AUTO-GENERATED FUNCTIONS END HERE |
| ... | ... |
@@ -35,7 +35,7 @@ package ${version}
|
| 35 | 35 |
// AUTO-GENERATED FUNCTIONS START HERE |
| 36 | 36 |
EOF |
| 37 | 37 |
|
| 38 |
- go run cmd/gendeepcopy/deep_copy.go -v ${version} -f - -o "${version}=" >> $TMPFILE
|
|
| 38 |
+ go run tools/gendeepcopy/deep_copy.go -v ${version} -f - -o "${version}=" >> $TMPFILE
|
|
| 39 | 39 |
|
| 40 | 40 |
cat >> $TMPFILE <<EOF |
| 41 | 41 |
// AUTO-GENERATED FUNCTIONS END HERE |
| ... | ... |
@@ -9,7 +9,7 @@ set -o pipefail |
| 9 | 9 |
OS_ROOT=$(dirname "${BASH_SOURCE}")/..
|
| 10 | 10 |
source "${OS_ROOT}/hack/common.sh"
|
| 11 | 11 |
|
| 12 |
-"${OS_ROOT}/hack/build-go.sh" cmd/gendocs
|
|
| 12 |
+"${OS_ROOT}/hack/build-go.sh" tools/gendocs
|
|
| 13 | 13 |
|
| 14 | 14 |
# Find binary |
| 15 | 15 |
gendocs="$(os::build::find-binary gendocs)" |
| ... | ... |
@@ -19,7 +19,7 @@ if [[ -z "$gendocs" ]]; then |
| 19 | 19 |
echo "It looks as if you don't have a compiled gendocs binary" |
| 20 | 20 |
echo |
| 21 | 21 |
echo "If you are running from a clone of the git repo, please run" |
| 22 |
- echo "'./hack/build-go.sh cmd/gendocs'." |
|
| 22 |
+ echo "'./hack/build-go.sh tools/gendocs'." |
|
| 23 | 23 |
} >&2 |
| 24 | 24 |
exit 1 |
| 25 | 25 |
fi |
| ... | ... |
@@ -11,7 +11,7 @@ cd "${OS_ROOT}"
|
| 11 | 11 |
|
| 12 | 12 |
echo "===== Verifying Generated Conversions =====" |
| 13 | 13 |
echo "Building genconversion binary..." |
| 14 |
-if ! buildout=`"${OS_ROOT}/hack/build-go.sh" cmd/genconversion 2>&1`
|
|
| 14 |
+if ! buildout=`"${OS_ROOT}/hack/build-go.sh" tools/genconversion 2>&1`
|
|
| 15 | 15 |
then |
| 16 | 16 |
echo "FAILURE: Building genconversion binary failed:" |
| 17 | 17 |
echo "$buildout" |
| ... | ... |
@@ -27,7 +27,7 @@ if [[ ! -x "$genconversion" ]]; then |
| 27 | 27 |
{
|
| 28 | 28 |
echo "FAILURE: It looks as if you don't have a compiled conversion binary." |
| 29 | 29 |
echo "If you are running from a clone of the git repo, please run:" |
| 30 |
- echo "'./hack/build-go.sh cmd/genconversion'." |
|
| 30 |
+ echo "'./hack/build-go.sh tools/genconversion'." |
|
| 31 | 31 |
} >&2 |
| 32 | 32 |
exit 1 |
| 33 | 33 |
fi |
| ... | ... |
@@ -11,7 +11,7 @@ cd "${OS_ROOT}"
|
| 11 | 11 |
|
| 12 | 12 |
echo "===== Verifying Generated Conversions =====" |
| 13 | 13 |
echo "Building gendeepcopy binary..." |
| 14 |
-if ! buildout=`"${OS_ROOT}/hack/build-go.sh" cmd/gendeepcopy 2>&1`
|
|
| 14 |
+if ! buildout=`"${OS_ROOT}/hack/build-go.sh" tools/gendeepcopy 2>&1`
|
|
| 15 | 15 |
then |
| 16 | 16 |
echo "FAILURE: Building gendeepcopy binary failed:" |
| 17 | 17 |
echo "$buildout" |
| ... | ... |
@@ -27,7 +27,7 @@ if [[ ! -x "$gendeepcopy" ]]; then |
| 27 | 27 |
{
|
| 28 | 28 |
echo "FAILURE: It looks as if you don't have a compiled conversion binary." |
| 29 | 29 |
echo "If you are running from a clone of the git repo, please run:" |
| 30 |
- echo "'./hack/build-go.sh cmd/gendeepcopy'." |
|
| 30 |
+ echo "'./hack/build-go.sh tools/gendeepcopy'." |
|
| 31 | 31 |
} >&2 |
| 32 | 32 |
exit 1 |
| 33 | 33 |
fi |
| ... | ... |
@@ -7,7 +7,7 @@ set -o pipefail |
| 7 | 7 |
OS_ROOT=$(dirname "${BASH_SOURCE}")/..
|
| 8 | 8 |
source "${OS_ROOT}/hack/common.sh"
|
| 9 | 9 |
|
| 10 |
-"${OS_ROOT}/hack/build-go.sh" cmd/rebasehelpers/commitchecker
|
|
| 10 |
+"${OS_ROOT}/hack/build-go.sh" tools/rebasehelpers/commitchecker
|
|
| 11 | 11 |
|
| 12 | 12 |
# Find binary |
| 13 | 13 |
commitchecker="$(os::build::find-binary commitchecker)" |
| 14 | 14 |
deleted file mode 100644 |
| ... | ... |
@@ -1,67 +0,0 @@ |
| 1 |
-package main |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "encoding/json" |
|
| 5 |
- "fmt" |
|
| 6 |
- "io/ioutil" |
|
| 7 |
- "os" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 |
-type Godep struct {
|
|
| 11 |
- Deps []Dep |
|
| 12 |
-} |
|
| 13 |
- |
|
| 14 |
-type Dep struct {
|
|
| 15 |
- ImportPath string |
|
| 16 |
- Comment string |
|
| 17 |
- Rev string |
|
| 18 |
-} |
|
| 19 |
- |
|
| 20 |
-func main() {
|
|
| 21 |
- comment := false |
|
| 22 |
- args := os.Args[1:] |
|
| 23 |
- if len(args) == 3 {
|
|
| 24 |
- if args[2] == "comment" {
|
|
| 25 |
- comment = true |
|
| 26 |
- } else {
|
|
| 27 |
- fmt.Fprintf(os.Stderr, "The third argument must be 'comment' or not specified.\n") |
|
| 28 |
- os.Exit(1) |
|
| 29 |
- } |
|
| 30 |
- args = args[:2] |
|
| 31 |
- } |
|
| 32 |
- if len(args) != 2 {
|
|
| 33 |
- fmt.Fprintf(os.Stderr, "Expects two arguments, a path to the Godep.json file and a package to get the commit for (and optionally, 'comment' as the third option)\n") |
|
| 34 |
- os.Exit(1) |
|
| 35 |
- } |
|
| 36 |
- |
|
| 37 |
- path := args[0] |
|
| 38 |
- pkg := args[1] |
|
| 39 |
- |
|
| 40 |
- data, err := ioutil.ReadFile(path) |
|
| 41 |
- if err != nil {
|
|
| 42 |
- fmt.Fprintf(os.Stderr, "Unable to read %s: %v\n", path, err) |
|
| 43 |
- os.Exit(1) |
|
| 44 |
- } |
|
| 45 |
- godeps := &Godep{}
|
|
| 46 |
- if err := json.Unmarshal(data, godeps); err != nil {
|
|
| 47 |
- fmt.Fprintf(os.Stderr, "Unable to read %s: %v\n", path, err) |
|
| 48 |
- os.Exit(1) |
|
| 49 |
- } |
|
| 50 |
- |
|
| 51 |
- for _, dep := range godeps.Deps {
|
|
| 52 |
- if dep.ImportPath != pkg {
|
|
| 53 |
- continue |
|
| 54 |
- } |
|
| 55 |
- if len(dep.Rev) > 7 {
|
|
| 56 |
- dep.Rev = dep.Rev[0:7] |
|
| 57 |
- } |
|
| 58 |
- if comment && len(dep.Comment) > 0 {
|
|
| 59 |
- dep.Rev = dep.Comment |
|
| 60 |
- } |
|
| 61 |
- fmt.Fprintf(os.Stdout, dep.Rev) |
|
| 62 |
- return |
|
| 63 |
- } |
|
| 64 |
- |
|
| 65 |
- fmt.Fprintf(os.Stderr, "Could not find %s in %s\n", pkg, path) |
|
| 66 |
- os.Exit(1) |
|
| 67 |
-} |
| 68 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,60 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "io/ioutil" |
|
| 6 |
+ "os" |
|
| 7 |
+ "path/filepath" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/openshift/origin/pkg/cmd/admin" |
|
| 10 |
+ "github.com/openshift/origin/pkg/cmd/cli" |
|
| 11 |
+ "github.com/openshift/origin/pkg/cmd/openshift" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+func OutDir(path string) (string, error) {
|
|
| 15 |
+ outDir, err := filepath.Abs(path) |
|
| 16 |
+ if err != nil {
|
|
| 17 |
+ return "", err |
|
| 18 |
+ } |
|
| 19 |
+ |
|
| 20 |
+ stat, err := os.Stat(outDir) |
|
| 21 |
+ if err != nil {
|
|
| 22 |
+ return "", err |
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ if !stat.IsDir() {
|
|
| 26 |
+ return "", fmt.Errorf("output directory %s is not a directory\n", outDir)
|
|
| 27 |
+ } |
|
| 28 |
+ outDir = outDir + "/" |
|
| 29 |
+ return outDir, nil |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+func main() {
|
|
| 33 |
+ // use os.Args instead of "flags" because "flags" will mess up the man pages! |
|
| 34 |
+ path := "contrib/completions/bash/" |
|
| 35 |
+ if len(os.Args) == 2 {
|
|
| 36 |
+ path = os.Args[1] |
|
| 37 |
+ } else if len(os.Args) > 2 {
|
|
| 38 |
+ fmt.Fprintf(os.Stderr, "usage: %s [output directory]\n", os.Args[0]) |
|
| 39 |
+ os.Exit(1) |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ outDir, err := OutDir(path) |
|
| 43 |
+ if err != nil {
|
|
| 44 |
+ fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err) |
|
| 45 |
+ os.Exit(1) |
|
| 46 |
+ } |
|
| 47 |
+ outFile_openshift := outDir + "openshift" |
|
| 48 |
+ openshift := openshift.NewCommandOpenShift("openshift")
|
|
| 49 |
+ openshift.GenBashCompletionFile(outFile_openshift) |
|
| 50 |
+ |
|
| 51 |
+ outFile_osc := outDir + "oc" |
|
| 52 |
+ out := os.Stdout |
|
| 53 |
+ oc := cli.NewCommandCLI("oc", "openshift cli", &bytes.Buffer{}, out, ioutil.Discard)
|
|
| 54 |
+ oc.GenBashCompletionFile(outFile_osc) |
|
| 55 |
+ |
|
| 56 |
+ outFile_osadm := outDir + "oadm" |
|
| 57 |
+ oadm := admin.NewCommandAdmin("oadm", "openshift admin", ioutil.Discard)
|
|
| 58 |
+ oadm.GenBashCompletionFile(outFile_osadm) |
|
| 59 |
+} |
| 0 | 60 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,71 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "io" |
|
| 5 |
+ "os" |
|
| 6 |
+ "runtime" |
|
| 7 |
+ "strings" |
|
| 8 |
+ |
|
| 9 |
+ "k8s.io/kubernetes/pkg/api" |
|
| 10 |
+ pkg_runtime "k8s.io/kubernetes/pkg/runtime" |
|
| 11 |
+ "k8s.io/kubernetes/pkg/util/sets" |
|
| 12 |
+ |
|
| 13 |
+ "github.com/golang/glog" |
|
| 14 |
+ flag "github.com/spf13/pflag" |
|
| 15 |
+ |
|
| 16 |
+ _ "github.com/openshift/origin/pkg/api" |
|
| 17 |
+ _ "github.com/openshift/origin/pkg/api/v1" |
|
| 18 |
+ _ "github.com/openshift/origin/pkg/api/v1beta3" |
|
| 19 |
+) |
|
| 20 |
+ |
|
| 21 |
+var ( |
|
| 22 |
+ functionDest = flag.StringP("funcDest", "f", "-", "Output for conversion functions; '-' means stdout")
|
|
| 23 |
+ version = flag.StringP("version", "v", "v1beta3", "Version for conversion.")
|
|
| 24 |
+) |
|
| 25 |
+ |
|
| 26 |
+func main() {
|
|
| 27 |
+ runtime.GOMAXPROCS(runtime.NumCPU()) |
|
| 28 |
+ flag.Parse() |
|
| 29 |
+ |
|
| 30 |
+ var funcOut io.Writer |
|
| 31 |
+ if *functionDest == "-" {
|
|
| 32 |
+ funcOut = os.Stdout |
|
| 33 |
+ } else {
|
|
| 34 |
+ file, err := os.Create(*functionDest) |
|
| 35 |
+ if err != nil {
|
|
| 36 |
+ glog.Fatalf("Couldn't open %v: %v", *functionDest, err)
|
|
| 37 |
+ } |
|
| 38 |
+ defer file.Close() |
|
| 39 |
+ funcOut = file |
|
| 40 |
+ } |
|
| 41 |
+ |
|
| 42 |
+ generator := pkg_runtime.NewConversionGenerator(api.Scheme.Raw(), "github.com/openshift/origin/pkg/api") |
|
| 43 |
+ apiShort := generator.AddImport("k8s.io/kubernetes/pkg/api")
|
|
| 44 |
+ generator.AddImport("k8s.io/kubernetes/pkg/api/resource")
|
|
| 45 |
+ generator.AssumePrivateConversions() |
|
| 46 |
+ // TODO(wojtek-t): Change the overwrites to a flag. |
|
| 47 |
+ generator.OverwritePackage(*version, "") |
|
| 48 |
+ for _, knownType := range api.Scheme.KnownTypes(*version) {
|
|
| 49 |
+ if !strings.Contains(knownType.PkgPath(), "openshift/origin") {
|
|
| 50 |
+ continue |
|
| 51 |
+ } |
|
| 52 |
+ if err := generator.GenerateConversionsForType(*version, knownType); err != nil {
|
|
| 53 |
+ glog.Errorf("error while generating conversion functions for %v: %v", knownType, err)
|
|
| 54 |
+ } |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ generator.RepackImports(sets.NewString("k8s.io/kubernetes/pkg/runtime"))
|
|
| 58 |
+ // the repack changes the name of the import |
|
| 59 |
+ apiShort = generator.AddImport("k8s.io/kubernetes/pkg/api")
|
|
| 60 |
+ |
|
| 61 |
+ if err := generator.WriteImports(funcOut); err != nil {
|
|
| 62 |
+ glog.Fatalf("error while writing imports: %v", err)
|
|
| 63 |
+ } |
|
| 64 |
+ if err := generator.WriteConversionFunctions(funcOut); err != nil {
|
|
| 65 |
+ glog.Fatalf("Error while writing conversion functions: %v", err)
|
|
| 66 |
+ } |
|
| 67 |
+ if err := generator.RegisterConversionFunctions(funcOut, fmt.Sprintf("%s.Scheme", apiShort)); err != nil {
|
|
| 68 |
+ glog.Fatalf("Error while writing conversion functions: %v", err)
|
|
| 69 |
+ } |
|
| 70 |
+} |
| 0 | 71 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,94 @@ |
| 0 |
+/* |
|
| 1 |
+Copyright 2015 The Kubernetes Authors All rights reserved. |
|
| 2 |
+ |
|
| 3 |
+Licensed under the Apache License, Version 2.0 (the "License"); |
|
| 4 |
+you may not use this file except in compliance with the License. |
|
| 5 |
+You may obtain a copy of the License at |
|
| 6 |
+ |
|
| 7 |
+ http://www.apache.org/licenses/LICENSE-2.0 |
|
| 8 |
+ |
|
| 9 |
+Unless required by applicable law or agreed to in writing, software |
|
| 10 |
+distributed under the License is distributed on an "AS IS" BASIS, |
|
| 11 |
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
| 12 |
+See the License for the specific language governing permissions and |
|
| 13 |
+limitations under the License. |
|
| 14 |
+*/ |
|
| 15 |
+ |
|
| 16 |
+package main |
|
| 17 |
+ |
|
| 18 |
+import ( |
|
| 19 |
+ "fmt" |
|
| 20 |
+ "io" |
|
| 21 |
+ "os" |
|
| 22 |
+ "runtime" |
|
| 23 |
+ "strings" |
|
| 24 |
+ |
|
| 25 |
+ "k8s.io/kubernetes/pkg/api" |
|
| 26 |
+ pkg_runtime "k8s.io/kubernetes/pkg/runtime" |
|
| 27 |
+ "k8s.io/kubernetes/pkg/util/sets" |
|
| 28 |
+ |
|
| 29 |
+ "github.com/golang/glog" |
|
| 30 |
+ flag "github.com/spf13/pflag" |
|
| 31 |
+ |
|
| 32 |
+ _ "github.com/openshift/origin/pkg/api" |
|
| 33 |
+ _ "github.com/openshift/origin/pkg/api/v1" |
|
| 34 |
+ _ "github.com/openshift/origin/pkg/api/v1beta3" |
|
| 35 |
+) |
|
| 36 |
+ |
|
| 37 |
+var ( |
|
| 38 |
+ functionDest = flag.StringP("func-dest", "f", "-", "Output for deep copy functions; '-' means stdout")
|
|
| 39 |
+ version = flag.StringP("version", "v", "v1beta3", "Version for deep copies.")
|
|
| 40 |
+ overwrites = flag.StringP("overwrites", "o", "", "Comma-separated overwrites for package names")
|
|
| 41 |
+) |
|
| 42 |
+ |
|
| 43 |
+func main() {
|
|
| 44 |
+ runtime.GOMAXPROCS(runtime.NumCPU()) |
|
| 45 |
+ flag.Parse() |
|
| 46 |
+ |
|
| 47 |
+ var funcOut io.Writer |
|
| 48 |
+ if *functionDest == "-" {
|
|
| 49 |
+ funcOut = os.Stdout |
|
| 50 |
+ } else {
|
|
| 51 |
+ file, err := os.Create(*functionDest) |
|
| 52 |
+ if err != nil {
|
|
| 53 |
+ glog.Fatalf("Couldn't open %v: %v", *functionDest, err)
|
|
| 54 |
+ } |
|
| 55 |
+ defer file.Close() |
|
| 56 |
+ funcOut = file |
|
| 57 |
+ } |
|
| 58 |
+ |
|
| 59 |
+ knownVersion := *version |
|
| 60 |
+ if knownVersion == "api" {
|
|
| 61 |
+ knownVersion = api.Scheme.Raw().InternalVersion |
|
| 62 |
+ } |
|
| 63 |
+ generator := pkg_runtime.NewDeepCopyGenerator(api.Scheme.Raw(), "github.com/openshift/origin/pkg/api", sets.NewString("github.com/openshift/origin"))
|
|
| 64 |
+ apiShort := generator.AddImport("k8s.io/kubernetes/pkg/api")
|
|
| 65 |
+ generator.ReplaceType("k8s.io/kubernetes/pkg/util/sets", "empty", struct{}{})
|
|
| 66 |
+ |
|
| 67 |
+ for _, overwrite := range strings.Split(*overwrites, ",") {
|
|
| 68 |
+ vals := strings.Split(overwrite, "=") |
|
| 69 |
+ generator.OverwritePackage(vals[0], vals[1]) |
|
| 70 |
+ } |
|
| 71 |
+ for _, knownType := range api.Scheme.KnownTypes(knownVersion) {
|
|
| 72 |
+ if !strings.Contains(knownType.PkgPath(), "openshift/origin") {
|
|
| 73 |
+ continue |
|
| 74 |
+ } |
|
| 75 |
+ if err := generator.AddType(knownType); err != nil {
|
|
| 76 |
+ glog.Errorf("error while generating deep copy functions for %v: %v", knownType, err)
|
|
| 77 |
+ } |
|
| 78 |
+ } |
|
| 79 |
+ |
|
| 80 |
+ generator.RepackImports() |
|
| 81 |
+ // the repack changes the name of the import |
|
| 82 |
+ apiShort = generator.AddImport("k8s.io/kubernetes/pkg/api")
|
|
| 83 |
+ |
|
| 84 |
+ if err := generator.WriteImports(funcOut); err != nil {
|
|
| 85 |
+ glog.Fatalf("error while writing imports: %v", err)
|
|
| 86 |
+ } |
|
| 87 |
+ if err := generator.WriteDeepCopyFunctions(funcOut); err != nil {
|
|
| 88 |
+ glog.Fatalf("error while writing deep copy functions: %v", err)
|
|
| 89 |
+ } |
|
| 90 |
+ if err := generator.RegisterDeepCopyFunctions(funcOut, fmt.Sprintf("%s.Scheme", apiShort)); err != nil {
|
|
| 91 |
+ glog.Fatalf("error while registering deep copy functions: %v", err)
|
|
| 92 |
+ } |
|
| 93 |
+} |
| 0 | 94 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,56 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "io/ioutil" |
|
| 6 |
+ "os" |
|
| 7 |
+ "path/filepath" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/openshift/origin/pkg/cmd/admin" |
|
| 10 |
+ "github.com/openshift/origin/pkg/cmd/cli" |
|
| 11 |
+ "github.com/openshift/origin/pkg/cmd/util/gendocs" |
|
| 12 |
+) |
|
| 13 |
+ |
|
| 14 |
+func OutDir(path string) (string, error) {
|
|
| 15 |
+ outDir, err := filepath.Abs(path) |
|
| 16 |
+ if err != nil {
|
|
| 17 |
+ return "", err |
|
| 18 |
+ } |
|
| 19 |
+ |
|
| 20 |
+ stat, err := os.Stat(outDir) |
|
| 21 |
+ if err != nil {
|
|
| 22 |
+ return "", err |
|
| 23 |
+ } |
|
| 24 |
+ |
|
| 25 |
+ if !stat.IsDir() {
|
|
| 26 |
+ return "", fmt.Errorf("output directory %s is not a directory\n", outDir)
|
|
| 27 |
+ } |
|
| 28 |
+ outDir = outDir + "/" |
|
| 29 |
+ return outDir, nil |
|
| 30 |
+} |
|
| 31 |
+ |
|
| 32 |
+func main() {
|
|
| 33 |
+ path := "docs/generated/" |
|
| 34 |
+ if len(os.Args) == 2 {
|
|
| 35 |
+ path = os.Args[1] |
|
| 36 |
+ } else if len(os.Args) > 2 {
|
|
| 37 |
+ fmt.Fprintf(os.Stderr, "usage: %s [output directory]\n", os.Args[0]) |
|
| 38 |
+ os.Exit(1) |
|
| 39 |
+ } |
|
| 40 |
+ |
|
| 41 |
+ outDir, err := OutDir(path) |
|
| 42 |
+ if err != nil {
|
|
| 43 |
+ fmt.Fprintf(os.Stderr, "failed to get output directory: %v\n", err) |
|
| 44 |
+ os.Exit(1) |
|
| 45 |
+ } |
|
| 46 |
+ |
|
| 47 |
+ outFile := outDir + "oc_by_example_content.adoc" |
|
| 48 |
+ out := os.Stdout |
|
| 49 |
+ cmd := cli.NewCommandCLI("oc", "oc", &bytes.Buffer{}, out, ioutil.Discard)
|
|
| 50 |
+ gendocs.GenDocs(cmd, outFile) |
|
| 51 |
+ |
|
| 52 |
+ outFile = outDir + "oadm_by_example_content.adoc" |
|
| 53 |
+ cmd = admin.NewCommandAdmin("oadm", "oadm", ioutil.Discard)
|
|
| 54 |
+ gendocs.GenDocs(cmd, outFile) |
|
| 55 |
+} |
| 0 | 56 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,67 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "encoding/json" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "io/ioutil" |
|
| 6 |
+ "os" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+type Godep struct {
|
|
| 10 |
+ Deps []Dep |
|
| 11 |
+} |
|
| 12 |
+ |
|
| 13 |
+type Dep struct {
|
|
| 14 |
+ ImportPath string |
|
| 15 |
+ Comment string |
|
| 16 |
+ Rev string |
|
| 17 |
+} |
|
| 18 |
+ |
|
| 19 |
+func main() {
|
|
| 20 |
+ comment := false |
|
| 21 |
+ args := os.Args[1:] |
|
| 22 |
+ if len(args) == 3 {
|
|
| 23 |
+ if args[2] == "comment" {
|
|
| 24 |
+ comment = true |
|
| 25 |
+ } else {
|
|
| 26 |
+ fmt.Fprintf(os.Stderr, "The third argument must be 'comment' or not specified.\n") |
|
| 27 |
+ os.Exit(1) |
|
| 28 |
+ } |
|
| 29 |
+ args = args[:2] |
|
| 30 |
+ } |
|
| 31 |
+ if len(args) != 2 {
|
|
| 32 |
+ fmt.Fprintf(os.Stderr, "Expects two arguments, a path to the Godep.json file and a package to get the commit for (and optionally, 'comment' as the third option)\n") |
|
| 33 |
+ os.Exit(1) |
|
| 34 |
+ } |
|
| 35 |
+ |
|
| 36 |
+ path := args[0] |
|
| 37 |
+ pkg := args[1] |
|
| 38 |
+ |
|
| 39 |
+ data, err := ioutil.ReadFile(path) |
|
| 40 |
+ if err != nil {
|
|
| 41 |
+ fmt.Fprintf(os.Stderr, "Unable to read %s: %v\n", path, err) |
|
| 42 |
+ os.Exit(1) |
|
| 43 |
+ } |
|
| 44 |
+ godeps := &Godep{}
|
|
| 45 |
+ if err := json.Unmarshal(data, godeps); err != nil {
|
|
| 46 |
+ fmt.Fprintf(os.Stderr, "Unable to read %s: %v\n", path, err) |
|
| 47 |
+ os.Exit(1) |
|
| 48 |
+ } |
|
| 49 |
+ |
|
| 50 |
+ for _, dep := range godeps.Deps {
|
|
| 51 |
+ if dep.ImportPath != pkg {
|
|
| 52 |
+ continue |
|
| 53 |
+ } |
|
| 54 |
+ if len(dep.Rev) > 7 {
|
|
| 55 |
+ dep.Rev = dep.Rev[0:7] |
|
| 56 |
+ } |
|
| 57 |
+ if comment && len(dep.Comment) > 0 {
|
|
| 58 |
+ dep.Rev = dep.Comment |
|
| 59 |
+ } |
|
| 60 |
+ fmt.Fprintf(os.Stdout, dep.Rev) |
|
| 61 |
+ return |
|
| 62 |
+ } |
|
| 63 |
+ |
|
| 64 |
+ fmt.Fprintf(os.Stderr, "Could not find %s in %s\n", pkg, path) |
|
| 65 |
+ os.Exit(1) |
|
| 66 |
+} |
| 0 | 67 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,46 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "flag" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "os" |
|
| 6 |
+ "strings" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/openshift/origin/tools/rebasehelpers/util" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+func main() {
|
|
| 12 |
+ var start, end string |
|
| 13 |
+ flag.StringVar(&start, "start", "master", "The start of the revision range for analysis") |
|
| 14 |
+ flag.StringVar(&end, "end", "HEAD", "The end of the revision range for analysis") |
|
| 15 |
+ flag.Parse() |
|
| 16 |
+ |
|
| 17 |
+ commits, err := util.CommitsBetween(start, end) |
|
| 18 |
+ if err != nil {
|
|
| 19 |
+ os.Stderr.WriteString(fmt.Sprintf("ERROR: couldn't find commits from %s..%s: %v\n", start, end, err))
|
|
| 20 |
+ os.Exit(1) |
|
| 21 |
+ } |
|
| 22 |
+ |
|
| 23 |
+ // TODO: Filter out bump commits for now until we decide how to deal with |
|
| 24 |
+ // them correctly. |
|
| 25 |
+ nonbumpCommits := []util.Commit{}
|
|
| 26 |
+ for _, commit := range commits {
|
|
| 27 |
+ if commit.DeclaresUpstreamChange() && |
|
| 28 |
+ !strings.HasPrefix(commit.Summary, "bump(") {
|
|
| 29 |
+ nonbumpCommits = append(nonbumpCommits, commit) |
|
| 30 |
+ } |
|
| 31 |
+ } |
|
| 32 |
+ |
|
| 33 |
+ errs := []string{}
|
|
| 34 |
+ for _, validate := range AllValidators {
|
|
| 35 |
+ err := validate(nonbumpCommits) |
|
| 36 |
+ if err != nil {
|
|
| 37 |
+ errs = append(errs, err.Error()) |
|
| 38 |
+ } |
|
| 39 |
+ } |
|
| 40 |
+ |
|
| 41 |
+ if len(errs) > 0 {
|
|
| 42 |
+ os.Stderr.WriteString(strings.Join(errs, "\n\n")) |
|
| 43 |
+ os.Exit(2) |
|
| 44 |
+ } |
|
| 45 |
+} |
| 0 | 46 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,185 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "regexp" |
|
| 6 |
+ "strings" |
|
| 7 |
+ "text/template" |
|
| 8 |
+ |
|
| 9 |
+ "github.com/openshift/origin/tools/rebasehelpers/util" |
|
| 10 |
+) |
|
| 11 |
+ |
|
| 12 |
+var CommitSummaryErrorTemplate = ` |
|
| 13 |
+The following UPSTREAM commits have invalid summaries: |
|
| 14 |
+ |
|
| 15 |
+{{ range .Commits }} [{{ .Sha }}] {{ .Summary }}
|
|
| 16 |
+{{ end }}
|
|
| 17 |
+UPSTREAM commit summaries should look like: |
|
| 18 |
+ |
|
| 19 |
+ UPSTREAM: [non-kube-repo/name: ]<PR number|carry|drop>: description |
|
| 20 |
+ |
|
| 21 |
+UPSTREAM commits which revert previous UPSTREAM commits should look like: |
|
| 22 |
+ |
|
| 23 |
+ UPSTREAM: revert: <sha>: <normal upstream format> |
|
| 24 |
+ |
|
| 25 |
+UPSTREAM commits are validated against the following regular expression: |
|
| 26 |
+ |
|
| 27 |
+ {{ .Pattern }}
|
|
| 28 |
+ |
|
| 29 |
+Examples of valid summaries: |
|
| 30 |
+ |
|
| 31 |
+ UPSTREAM: 12345: A kube fix |
|
| 32 |
+ UPSTREAM: coreos/etcd: 12345: An etcd fix |
|
| 33 |
+ UPSTREAM: <carry>: A carried kube change |
|
| 34 |
+ UPSTREAM: <drop>: A dropped kube change |
|
| 35 |
+ UPSTREAM: revert: abcd123: coreos/etcd: 12345: An etcd fix |
|
| 36 |
+ UPSTREAM: k8s.io/heapster: 12345: A heapster fix |
|
| 37 |
+ |
|
| 38 |
+` |
|
| 39 |
+ |
|
| 40 |
+var AllValidators = []func([]util.Commit) error{
|
|
| 41 |
+ ValidateUpstreamCommitSummaries, |
|
| 42 |
+ ValidateUpstreamCommitsWithoutGodepsChanges, |
|
| 43 |
+ ValidateUpstreamCommitModifiesSingleGodepsRepo, |
|
| 44 |
+ ValidateUpstreamCommitModifiesOnlyGodeps, |
|
| 45 |
+ ValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo, |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// ValidateUpstreamCommitsWithoutGodepsChanges returns an error if any |
|
| 49 |
+// upstream commits have no Godeps changes. |
|
| 50 |
+func ValidateUpstreamCommitsWithoutGodepsChanges(commits []util.Commit) error {
|
|
| 51 |
+ problemCommits := []util.Commit{}
|
|
| 52 |
+ for _, commit := range commits {
|
|
| 53 |
+ if commit.HasGodepsChanges() && !commit.DeclaresUpstreamChange() {
|
|
| 54 |
+ problemCommits = append(problemCommits, commit) |
|
| 55 |
+ } |
|
| 56 |
+ } |
|
| 57 |
+ if len(problemCommits) > 0 {
|
|
| 58 |
+ label := "The following commits contain Godeps changes but aren't declared as UPSTREAM" |
|
| 59 |
+ msg := renderGodepFilesError(label, problemCommits, RenderOnlyGodepsFiles) |
|
| 60 |
+ return fmt.Errorf(msg) |
|
| 61 |
+ } |
|
| 62 |
+ return nil |
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+// ValidateUpstreamCommitModifiesSingleGodepsRepo returns an error if any |
|
| 66 |
+// upstream commits have changes that span more than one Godeps repo. |
|
| 67 |
+func ValidateUpstreamCommitModifiesSingleGodepsRepo(commits []util.Commit) error {
|
|
| 68 |
+ problemCommits := []util.Commit{}
|
|
| 69 |
+ for _, commit := range commits {
|
|
| 70 |
+ godepsChanges, err := commit.GodepsReposChanged() |
|
| 71 |
+ if err != nil {
|
|
| 72 |
+ return err |
|
| 73 |
+ } |
|
| 74 |
+ if len(godepsChanges) > 1 {
|
|
| 75 |
+ problemCommits = append(problemCommits, commit) |
|
| 76 |
+ } |
|
| 77 |
+ } |
|
| 78 |
+ if len(problemCommits) > 0 {
|
|
| 79 |
+ label := "The following UPSTREAM commits modify more than one repo in their changelist" |
|
| 80 |
+ msg := renderGodepFilesError(label, problemCommits, RenderOnlyGodepsFiles) |
|
| 81 |
+ return fmt.Errorf(msg) |
|
| 82 |
+ } |
|
| 83 |
+ return nil |
|
| 84 |
+} |
|
| 85 |
+ |
|
| 86 |
+// ValidateUpstreamCommitSummaries ensures that any commits which declare to |
|
| 87 |
+// be upstream match the regular expressions for UPSTREAM summaries. |
|
| 88 |
+func ValidateUpstreamCommitSummaries(commits []util.Commit) error {
|
|
| 89 |
+ problemCommits := []util.Commit{}
|
|
| 90 |
+ for _, commit := range commits {
|
|
| 91 |
+ if commit.DeclaresUpstreamChange() && !commit.MatchesUpstreamSummaryPattern() {
|
|
| 92 |
+ problemCommits = append(problemCommits, commit) |
|
| 93 |
+ } |
|
| 94 |
+ } |
|
| 95 |
+ if len(problemCommits) > 0 {
|
|
| 96 |
+ tmpl, _ := template.New("problems").Parse(CommitSummaryErrorTemplate)
|
|
| 97 |
+ data := struct {
|
|
| 98 |
+ Pattern *regexp.Regexp |
|
| 99 |
+ Commits []util.Commit |
|
| 100 |
+ }{
|
|
| 101 |
+ Pattern: util.UpstreamSummaryPattern, |
|
| 102 |
+ Commits: problemCommits, |
|
| 103 |
+ } |
|
| 104 |
+ buffer := &bytes.Buffer{}
|
|
| 105 |
+ tmpl.Execute(buffer, data) |
|
| 106 |
+ return fmt.Errorf(buffer.String()) |
|
| 107 |
+ } |
|
| 108 |
+ return nil |
|
| 109 |
+} |
|
| 110 |
+ |
|
| 111 |
+// ValidateUpstreamCommitModifiesOnlyGodeps ensures that any Godeps commits |
|
| 112 |
+// modify ONLY Godeps files. |
|
| 113 |
+func ValidateUpstreamCommitModifiesOnlyGodeps(commits []util.Commit) error {
|
|
| 114 |
+ problemCommits := []util.Commit{}
|
|
| 115 |
+ for _, commit := range commits {
|
|
| 116 |
+ if commit.HasGodepsChanges() && commit.HasNonGodepsChanges() {
|
|
| 117 |
+ problemCommits = append(problemCommits, commit) |
|
| 118 |
+ } |
|
| 119 |
+ } |
|
| 120 |
+ if len(problemCommits) > 0 {
|
|
| 121 |
+ label := "The following UPSTREAM commits modify files outside Godeps" |
|
| 122 |
+ msg := renderGodepFilesError(label, problemCommits, RenderAllFiles) |
|
| 123 |
+ return fmt.Errorf(msg) |
|
| 124 |
+ } |
|
| 125 |
+ return nil |
|
| 126 |
+} |
|
| 127 |
+ |
|
| 128 |
+// ValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo ensures that an |
|
| 129 |
+// upstream commit only modifies the Godep repo the summary declares. |
|
| 130 |
+func ValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo(commits []util.Commit) error {
|
|
| 131 |
+ problemCommits := []util.Commit{}
|
|
| 132 |
+ for _, commit := range commits {
|
|
| 133 |
+ if commit.DeclaresUpstreamChange() {
|
|
| 134 |
+ declaredRepo, err := commit.DeclaredUpstreamRepo() |
|
| 135 |
+ if err != nil {
|
|
| 136 |
+ return err |
|
| 137 |
+ } |
|
| 138 |
+ reposChanged, err := commit.GodepsReposChanged() |
|
| 139 |
+ if err != nil {
|
|
| 140 |
+ return err |
|
| 141 |
+ } |
|
| 142 |
+ for _, changedRepo := range reposChanged {
|
|
| 143 |
+ if !strings.Contains(changedRepo, declaredRepo) {
|
|
| 144 |
+ problemCommits = append(problemCommits, commit) |
|
| 145 |
+ } |
|
| 146 |
+ } |
|
| 147 |
+ } |
|
| 148 |
+ } |
|
| 149 |
+ if len(problemCommits) > 0 {
|
|
| 150 |
+ label := "The following UPSTREAM commits modify Godeps repos other than the repo the commit declares" |
|
| 151 |
+ msg := renderGodepFilesError(label, problemCommits, RenderAllFiles) |
|
| 152 |
+ return fmt.Errorf(msg) |
|
| 153 |
+ } |
|
| 154 |
+ return nil |
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+type CommitFilesRenderOption int |
|
| 158 |
+ |
|
| 159 |
+const ( |
|
| 160 |
+ RenderNoFiles CommitFilesRenderOption = iota |
|
| 161 |
+ RenderOnlyGodepsFiles |
|
| 162 |
+ RenderOnlyNonGodepsFiles |
|
| 163 |
+ RenderAllFiles |
|
| 164 |
+) |
|
| 165 |
+ |
|
| 166 |
+// renderGodepFilesError formats commits and their file lists into readable |
|
| 167 |
+// output prefixed with label. |
|
| 168 |
+func renderGodepFilesError(label string, commits []util.Commit, opt CommitFilesRenderOption) string {
|
|
| 169 |
+ msg := fmt.Sprintf("%s:\n\n", label)
|
|
| 170 |
+ for _, commit := range commits {
|
|
| 171 |
+ msg += fmt.Sprintf("[%s] %s\n", commit.Sha, commit.Summary)
|
|
| 172 |
+ if opt == RenderNoFiles {
|
|
| 173 |
+ continue |
|
| 174 |
+ } |
|
| 175 |
+ for _, file := range commit.Files {
|
|
| 176 |
+ if opt == RenderAllFiles || |
|
| 177 |
+ (opt == RenderOnlyGodepsFiles && file.HasGodepsChanges()) || |
|
| 178 |
+ (opt == RenderOnlyNonGodepsFiles && !file.HasGodepsChanges()) {
|
|
| 179 |
+ msg += fmt.Sprintf(" - %s\n", file)
|
|
| 180 |
+ } |
|
| 181 |
+ } |
|
| 182 |
+ } |
|
| 183 |
+ return msg |
|
| 184 |
+} |
| 0 | 185 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,379 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "testing" |
|
| 4 |
+ |
|
| 5 |
+ "github.com/openshift/origin/tools/rebasehelpers/util" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 8 |
+func TestValidateUpstreamCommitsWithoutGodepsChanges(t *testing.T) {
|
|
| 9 |
+ tests := []struct {
|
|
| 10 |
+ name string |
|
| 11 |
+ commits []util.Commit |
|
| 12 |
+ errorExpected bool |
|
| 13 |
+ }{
|
|
| 14 |
+ {
|
|
| 15 |
+ name: "test 1", |
|
| 16 |
+ commits: []util.Commit{
|
|
| 17 |
+ {
|
|
| 18 |
+ Sha: "aaa0000", |
|
| 19 |
+ Summary: "commit 1", |
|
| 20 |
+ Files: []util.File{"file1", "pkg/file2"},
|
|
| 21 |
+ }, |
|
| 22 |
+ {
|
|
| 23 |
+ Sha: "aaa0001", |
|
| 24 |
+ Summary: "commit 2", |
|
| 25 |
+ Files: []util.File{"Godeps/file1", "pkg/file2"},
|
|
| 26 |
+ }, |
|
| 27 |
+ }, |
|
| 28 |
+ errorExpected: true, |
|
| 29 |
+ }, |
|
| 30 |
+ {
|
|
| 31 |
+ name: "test 2", |
|
| 32 |
+ commits: []util.Commit{
|
|
| 33 |
+ {
|
|
| 34 |
+ Sha: "aaa0000", |
|
| 35 |
+ Summary: "commit 1", |
|
| 36 |
+ Files: []util.File{"file1", "pkg/file2"},
|
|
| 37 |
+ }, |
|
| 38 |
+ {
|
|
| 39 |
+ Sha: "aaa0001", |
|
| 40 |
+ Summary: "UPSTREAM: commit 2", |
|
| 41 |
+ Files: []util.File{"Godeps/file1", "pkg/file2"},
|
|
| 42 |
+ }, |
|
| 43 |
+ }, |
|
| 44 |
+ errorExpected: false, |
|
| 45 |
+ }, |
|
| 46 |
+ } |
|
| 47 |
+ for _, test := range tests {
|
|
| 48 |
+ t.Logf("evaluating test %q", test.name)
|
|
| 49 |
+ err := ValidateUpstreamCommitsWithoutGodepsChanges(test.commits) |
|
| 50 |
+ if err != nil {
|
|
| 51 |
+ if test.errorExpected {
|
|
| 52 |
+ t.Logf("got expected error:\n%s", err)
|
|
| 53 |
+ continue |
|
| 54 |
+ } else {
|
|
| 55 |
+ t.Fatalf("unexpected error:\n%s", err)
|
|
| 56 |
+ } |
|
| 57 |
+ } else {
|
|
| 58 |
+ if test.errorExpected {
|
|
| 59 |
+ t.Fatalf("expected an error, got none")
|
|
| 60 |
+ } |
|
| 61 |
+ } |
|
| 62 |
+ } |
|
| 63 |
+} |
|
| 64 |
+ |
|
| 65 |
+func TestValidateUpstreamCommitModifiesSingleGodepsRepo(t *testing.T) {
|
|
| 66 |
+ tests := []struct {
|
|
| 67 |
+ name string |
|
| 68 |
+ commits []util.Commit |
|
| 69 |
+ errorExpected bool |
|
| 70 |
+ }{
|
|
| 71 |
+ {
|
|
| 72 |
+ name: "test 1", |
|
| 73 |
+ commits: []util.Commit{
|
|
| 74 |
+ {
|
|
| 75 |
+ Sha: "aaa0000", |
|
| 76 |
+ Summary: "commit 1", |
|
| 77 |
+ Files: []util.File{"file1", "pkg/file2"},
|
|
| 78 |
+ }, |
|
| 79 |
+ {
|
|
| 80 |
+ Sha: "aaa0001", |
|
| 81 |
+ Summary: "commit 2", |
|
| 82 |
+ Files: []util.File{
|
|
| 83 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 84 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 85 |
+ }, |
|
| 86 |
+ }, |
|
| 87 |
+ }, |
|
| 88 |
+ errorExpected: false, |
|
| 89 |
+ }, |
|
| 90 |
+ {
|
|
| 91 |
+ name: "test 2", |
|
| 92 |
+ commits: []util.Commit{
|
|
| 93 |
+ {
|
|
| 94 |
+ Sha: "aaa0000", |
|
| 95 |
+ Summary: "commit 1", |
|
| 96 |
+ Files: []util.File{"file1", "pkg/file2"},
|
|
| 97 |
+ }, |
|
| 98 |
+ {
|
|
| 99 |
+ Sha: "aaa0001", |
|
| 100 |
+ Summary: "UPSTREAM: commit 2", |
|
| 101 |
+ Files: []util.File{
|
|
| 102 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 103 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 104 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file", |
|
| 105 |
+ }, |
|
| 106 |
+ }, |
|
| 107 |
+ {
|
|
| 108 |
+ Sha: "aaa0002", |
|
| 109 |
+ Summary: "UPSTREAM: commit 3", |
|
| 110 |
+ Files: []util.File{
|
|
| 111 |
+ "Godeps/_workspace/src/k8s.io/heapster/file1", |
|
| 112 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 113 |
+ }, |
|
| 114 |
+ }, |
|
| 115 |
+ }, |
|
| 116 |
+ errorExpected: true, |
|
| 117 |
+ }, |
|
| 118 |
+ } |
|
| 119 |
+ for _, test := range tests {
|
|
| 120 |
+ t.Logf("evaluating test %q", test.name)
|
|
| 121 |
+ err := ValidateUpstreamCommitModifiesSingleGodepsRepo(test.commits) |
|
| 122 |
+ if err != nil {
|
|
| 123 |
+ if test.errorExpected {
|
|
| 124 |
+ t.Logf("got expected error:\n%s", err)
|
|
| 125 |
+ continue |
|
| 126 |
+ } else {
|
|
| 127 |
+ t.Fatalf("unexpected error:\n%s", err)
|
|
| 128 |
+ } |
|
| 129 |
+ } else {
|
|
| 130 |
+ if test.errorExpected {
|
|
| 131 |
+ t.Fatalf("expected an error, got none")
|
|
| 132 |
+ } |
|
| 133 |
+ } |
|
| 134 |
+ } |
|
| 135 |
+} |
|
| 136 |
+ |
|
| 137 |
+func TestValidateUpstreamCommitModifiesOnlyGodeps(t *testing.T) {
|
|
| 138 |
+ tests := []struct {
|
|
| 139 |
+ name string |
|
| 140 |
+ commits []util.Commit |
|
| 141 |
+ errorExpected bool |
|
| 142 |
+ }{
|
|
| 143 |
+ {
|
|
| 144 |
+ name: "test 1", |
|
| 145 |
+ commits: []util.Commit{
|
|
| 146 |
+ {
|
|
| 147 |
+ Sha: "aaa0000", |
|
| 148 |
+ Summary: "commit 1", |
|
| 149 |
+ Files: []util.File{"file1", "pkg/file2"},
|
|
| 150 |
+ }, |
|
| 151 |
+ {
|
|
| 152 |
+ Sha: "aaa0001", |
|
| 153 |
+ Summary: "UPSTREAM: commit 2", |
|
| 154 |
+ Files: []util.File{
|
|
| 155 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 156 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 157 |
+ "pkg/some_file", |
|
| 158 |
+ }, |
|
| 159 |
+ }, |
|
| 160 |
+ }, |
|
| 161 |
+ errorExpected: true, |
|
| 162 |
+ }, |
|
| 163 |
+ {
|
|
| 164 |
+ name: "test 2", |
|
| 165 |
+ commits: []util.Commit{
|
|
| 166 |
+ {
|
|
| 167 |
+ Sha: "aaa0000", |
|
| 168 |
+ Summary: "commit 1", |
|
| 169 |
+ Files: []util.File{"file1", "pkg/file2"},
|
|
| 170 |
+ }, |
|
| 171 |
+ {
|
|
| 172 |
+ Sha: "aaa0001", |
|
| 173 |
+ Summary: "UPSTREAM: commit 2", |
|
| 174 |
+ Files: []util.File{
|
|
| 175 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 176 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 177 |
+ }, |
|
| 178 |
+ }, |
|
| 179 |
+ }, |
|
| 180 |
+ errorExpected: false, |
|
| 181 |
+ }, |
|
| 182 |
+ } |
|
| 183 |
+ for _, test := range tests {
|
|
| 184 |
+ t.Logf("evaluating test %q", test.name)
|
|
| 185 |
+ err := ValidateUpstreamCommitModifiesOnlyGodeps(test.commits) |
|
| 186 |
+ if err != nil {
|
|
| 187 |
+ if test.errorExpected {
|
|
| 188 |
+ t.Logf("got expected error:\n%s", err)
|
|
| 189 |
+ continue |
|
| 190 |
+ } else {
|
|
| 191 |
+ t.Fatalf("unexpected error:\n%s", err)
|
|
| 192 |
+ } |
|
| 193 |
+ } else {
|
|
| 194 |
+ if test.errorExpected {
|
|
| 195 |
+ t.Fatalf("expected an error, got none")
|
|
| 196 |
+ } |
|
| 197 |
+ } |
|
| 198 |
+ } |
|
| 199 |
+} |
|
| 200 |
+ |
|
| 201 |
+func TestValidateUpstreamCommitSummaries(t *testing.T) {
|
|
| 202 |
+ tests := []struct {
|
|
| 203 |
+ summary string |
|
| 204 |
+ valid bool |
|
| 205 |
+ }{
|
|
| 206 |
+ {valid: true, summary: "UPSTREAM: 12345: a change"},
|
|
| 207 |
+ {valid: true, summary: "UPSTREAM: k8s.io/heapster: 12345: a change"},
|
|
| 208 |
+ {valid: true, summary: "UPSTREAM: <carry>: a change"},
|
|
| 209 |
+ {valid: true, summary: "UPSTREAM: <drop>: a change"},
|
|
| 210 |
+ {valid: true, summary: "UPSTREAM: coreos/etcd: <carry>: a change"},
|
|
| 211 |
+ {valid: true, summary: "UPSTREAM: coreos/etcd: <drop>: a change"},
|
|
| 212 |
+ {valid: true, summary: "UPSTREAM: revert: abcd123: 12345: a change"},
|
|
| 213 |
+ {valid: true, summary: "UPSTREAM: revert: abcd123: k8s.io/heapster: 12345: a change"},
|
|
| 214 |
+ {valid: true, summary: "UPSTREAM: revert: abcd123: <carry>: a change"},
|
|
| 215 |
+ {valid: true, summary: "UPSTREAM: revert: abcd123: <drop>: a change"},
|
|
| 216 |
+ {valid: true, summary: "UPSTREAM: revert: abcd123: coreos/etcd: <carry>: a change"},
|
|
| 217 |
+ {valid: true, summary: "UPSTREAM: revert: abcd123: coreos/etcd: <drop>: a change"},
|
|
| 218 |
+ {valid: false, summary: "UPSTREAM: whoopsie daisy"},
|
|
| 219 |
+ } |
|
| 220 |
+ for _, test := range tests {
|
|
| 221 |
+ commit := util.Commit{Summary: test.summary, Sha: "abcd000"}
|
|
| 222 |
+ err := ValidateUpstreamCommitSummaries([]util.Commit{commit})
|
|
| 223 |
+ if err != nil {
|
|
| 224 |
+ if test.valid {
|
|
| 225 |
+ t.Fatalf("unexpected error:\n%s", err)
|
|
| 226 |
+ } else {
|
|
| 227 |
+ t.Logf("got expected error:\n%s", err)
|
|
| 228 |
+ } |
|
| 229 |
+ } else {
|
|
| 230 |
+ if !test.valid {
|
|
| 231 |
+ t.Fatalf("expected an error, got none; summary: %s", test.summary)
|
|
| 232 |
+ } |
|
| 233 |
+ } |
|
| 234 |
+ } |
|
| 235 |
+} |
|
| 236 |
+ |
|
| 237 |
+func TestValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo(t *testing.T) {
|
|
| 238 |
+ tests := []struct {
|
|
| 239 |
+ name string |
|
| 240 |
+ commits []util.Commit |
|
| 241 |
+ errorExpected bool |
|
| 242 |
+ }{
|
|
| 243 |
+ {
|
|
| 244 |
+ name: "test 1", |
|
| 245 |
+ commits: []util.Commit{
|
|
| 246 |
+ {
|
|
| 247 |
+ Sha: "aaa0000", |
|
| 248 |
+ Summary: "commit 1", |
|
| 249 |
+ Files: []util.File{"file1", "pkg/file2"},
|
|
| 250 |
+ }, |
|
| 251 |
+ {
|
|
| 252 |
+ Sha: "aaa0001", |
|
| 253 |
+ Summary: "UPSTREAM: coreos/etcd: 12345: a change", |
|
| 254 |
+ Files: []util.File{
|
|
| 255 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 256 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 257 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 258 |
+ }, |
|
| 259 |
+ }, |
|
| 260 |
+ }, |
|
| 261 |
+ errorExpected: true, |
|
| 262 |
+ }, |
|
| 263 |
+ {
|
|
| 264 |
+ name: "test 2", |
|
| 265 |
+ commits: []util.Commit{
|
|
| 266 |
+ {
|
|
| 267 |
+ Sha: "aaa0001", |
|
| 268 |
+ Summary: "UPSTREAM: coreos/etcd: 12345: a change", |
|
| 269 |
+ Files: []util.File{
|
|
| 270 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 271 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file2", |
|
| 272 |
+ }, |
|
| 273 |
+ }, |
|
| 274 |
+ }, |
|
| 275 |
+ errorExpected: false, |
|
| 276 |
+ }, |
|
| 277 |
+ {
|
|
| 278 |
+ name: "test three segments", |
|
| 279 |
+ commits: []util.Commit{
|
|
| 280 |
+ {
|
|
| 281 |
+ Sha: "aaa0001", |
|
| 282 |
+ Summary: "UPSTREAM: coreos/etcd: 12345: a change", |
|
| 283 |
+ Files: []util.File{
|
|
| 284 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/a/file1", |
|
| 285 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/b/file2", |
|
| 286 |
+ }, |
|
| 287 |
+ }, |
|
| 288 |
+ }, |
|
| 289 |
+ errorExpected: false, |
|
| 290 |
+ }, |
|
| 291 |
+ {
|
|
| 292 |
+ name: "test 3", |
|
| 293 |
+ commits: []util.Commit{
|
|
| 294 |
+ {
|
|
| 295 |
+ Sha: "aaa0001", |
|
| 296 |
+ Summary: "UPSTREAM: 12345: a change", |
|
| 297 |
+ Files: []util.File{
|
|
| 298 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 299 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 300 |
+ }, |
|
| 301 |
+ }, |
|
| 302 |
+ }, |
|
| 303 |
+ errorExpected: false, |
|
| 304 |
+ }, |
|
| 305 |
+ {
|
|
| 306 |
+ name: "test 4", |
|
| 307 |
+ commits: []util.Commit{
|
|
| 308 |
+ {
|
|
| 309 |
+ Sha: "aaa0001", |
|
| 310 |
+ Summary: "UPSTREAM: 12345: a change", |
|
| 311 |
+ Files: []util.File{
|
|
| 312 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 313 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file2", |
|
| 314 |
+ }, |
|
| 315 |
+ }, |
|
| 316 |
+ }, |
|
| 317 |
+ errorExpected: true, |
|
| 318 |
+ }, |
|
| 319 |
+ {
|
|
| 320 |
+ name: "test 5", |
|
| 321 |
+ commits: []util.Commit{
|
|
| 322 |
+ {
|
|
| 323 |
+ Sha: "aaa0001", |
|
| 324 |
+ Summary: "UPSTREAM: revert: abcd000: 12345: a change", |
|
| 325 |
+ Files: []util.File{
|
|
| 326 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 327 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 328 |
+ }, |
|
| 329 |
+ }, |
|
| 330 |
+ }, |
|
| 331 |
+ errorExpected: false, |
|
| 332 |
+ }, |
|
| 333 |
+ {
|
|
| 334 |
+ name: "test 6", |
|
| 335 |
+ commits: []util.Commit{
|
|
| 336 |
+ {
|
|
| 337 |
+ Sha: "aaa0001", |
|
| 338 |
+ Summary: "UPSTREAM: revert: abcd000: coreos/etcd: 12345: a change", |
|
| 339 |
+ Files: []util.File{
|
|
| 340 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file1", |
|
| 341 |
+ "Godeps/_workspace/src/k8s.io/kubernetes/file2", |
|
| 342 |
+ }, |
|
| 343 |
+ }, |
|
| 344 |
+ }, |
|
| 345 |
+ errorExpected: true, |
|
| 346 |
+ }, |
|
| 347 |
+ {
|
|
| 348 |
+ name: "test 7", |
|
| 349 |
+ commits: []util.Commit{
|
|
| 350 |
+ {
|
|
| 351 |
+ Sha: "aaa0001", |
|
| 352 |
+ Summary: "UPSTREAM: revert: abcd000: coreos/etcd: 12345: a change", |
|
| 353 |
+ Files: []util.File{
|
|
| 354 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file1", |
|
| 355 |
+ "Godeps/_workspace/src/github.com/coreos/etcd/file2", |
|
| 356 |
+ }, |
|
| 357 |
+ }, |
|
| 358 |
+ }, |
|
| 359 |
+ errorExpected: false, |
|
| 360 |
+ }, |
|
| 361 |
+ } |
|
| 362 |
+ for _, test := range tests {
|
|
| 363 |
+ t.Logf("evaluating test %q", test.name)
|
|
| 364 |
+ err := ValidateUpstreamCommitModifiesOnlyDeclaredGodepRepo(test.commits) |
|
| 365 |
+ if err != nil {
|
|
| 366 |
+ if test.errorExpected {
|
|
| 367 |
+ t.Logf("got expected error:\n%s", err)
|
|
| 368 |
+ continue |
|
| 369 |
+ } else {
|
|
| 370 |
+ t.Fatalf("unexpected error:\n%s", err)
|
|
| 371 |
+ } |
|
| 372 |
+ } else {
|
|
| 373 |
+ if test.errorExpected {
|
|
| 374 |
+ t.Fatalf("expected an error, got none")
|
|
| 375 |
+ } |
|
| 376 |
+ } |
|
| 377 |
+ } |
|
| 378 |
+} |
| 0 | 379 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,200 @@ |
| 0 |
+package util |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "bytes" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ "os" |
|
| 6 |
+ "os/exec" |
|
| 7 |
+ "regexp" |
|
| 8 |
+ "strings" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+var UpstreamSummaryPattern = regexp.MustCompile(`UPSTREAM: (revert: [a-f0-9]{7,}: )?(([\w\.-]+\/[\w-]+)?: )?(\d+:|<carry>:|<drop>:)`)
|
|
| 12 |
+ |
|
| 13 |
+// supportedHosts maps source hosts to the number of path segments that |
|
| 14 |
+// represent the account/repo for that host. This is necessary because we |
|
| 15 |
+// can't tell just by looking at an import path whether the repo is identified |
|
| 16 |
+// by the first 2 or 3 path segments. |
|
| 17 |
+// |
|
| 18 |
+// If dependencies are introduced from new hosts, they'll need to be added |
|
| 19 |
+// here. |
|
| 20 |
+var SupportedHosts = map[string]int{
|
|
| 21 |
+ "bitbucket.org": 3, |
|
| 22 |
+ "code.google.com": 3, |
|
| 23 |
+ "github.com": 3, |
|
| 24 |
+ "golang.org": 3, |
|
| 25 |
+ "google.golang.org": 2, |
|
| 26 |
+ "gopkg.in": 2, |
|
| 27 |
+ "k8s.io": 2, |
|
| 28 |
+ "speter.net": 2, |
|
| 29 |
+} |
|
| 30 |
+ |
|
| 31 |
+type Commit struct {
|
|
| 32 |
+ Sha string |
|
| 33 |
+ Summary string |
|
| 34 |
+ Files []File |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func (c Commit) DeclaresUpstreamChange() bool {
|
|
| 38 |
+ return strings.HasPrefix(strings.ToLower(c.Summary), "upstream") |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+func (c Commit) MatchesUpstreamSummaryPattern() bool {
|
|
| 42 |
+ return UpstreamSummaryPattern.MatchString(c.Summary) |
|
| 43 |
+} |
|
| 44 |
+ |
|
| 45 |
+func (c Commit) DeclaredUpstreamRepo() (string, error) {
|
|
| 46 |
+ if !c.DeclaresUpstreamChange() {
|
|
| 47 |
+ return "", fmt.Errorf("commit declares no upstream changes")
|
|
| 48 |
+ } |
|
| 49 |
+ if !c.MatchesUpstreamSummaryPattern() {
|
|
| 50 |
+ return "", fmt.Errorf("commit doesn't match the upstream commit summary pattern")
|
|
| 51 |
+ } |
|
| 52 |
+ groups := UpstreamSummaryPattern.FindStringSubmatch(c.Summary) |
|
| 53 |
+ repo := groups[3] |
|
| 54 |
+ if len(repo) == 0 {
|
|
| 55 |
+ repo = "k8s.io/kubernetes" |
|
| 56 |
+ } |
|
| 57 |
+ return repo, nil |
|
| 58 |
+} |
|
| 59 |
+ |
|
| 60 |
+func (c Commit) HasGodepsChanges() bool {
|
|
| 61 |
+ for _, file := range c.Files {
|
|
| 62 |
+ if file.HasGodepsChanges() {
|
|
| 63 |
+ return true |
|
| 64 |
+ } |
|
| 65 |
+ } |
|
| 66 |
+ return false |
|
| 67 |
+} |
|
| 68 |
+ |
|
| 69 |
+func (c Commit) HasNonGodepsChanges() bool {
|
|
| 70 |
+ for _, file := range c.Files {
|
|
| 71 |
+ if !file.HasGodepsChanges() {
|
|
| 72 |
+ return true |
|
| 73 |
+ } |
|
| 74 |
+ } |
|
| 75 |
+ return false |
|
| 76 |
+} |
|
| 77 |
+ |
|
| 78 |
+func (c Commit) GodepsReposChanged() ([]string, error) {
|
|
| 79 |
+ repos := map[string]struct{}{}
|
|
| 80 |
+ for _, file := range c.Files {
|
|
| 81 |
+ if !file.HasGodepsChanges() {
|
|
| 82 |
+ continue |
|
| 83 |
+ } |
|
| 84 |
+ repo, err := file.GodepsRepoChanged() |
|
| 85 |
+ if err != nil {
|
|
| 86 |
+ return nil, fmt.Errorf("problem with file %q in commit %s: %s", file, c.Sha, err)
|
|
| 87 |
+ } |
|
| 88 |
+ repos[repo] = struct{}{}
|
|
| 89 |
+ } |
|
| 90 |
+ changed := []string{}
|
|
| 91 |
+ for repo := range repos {
|
|
| 92 |
+ changed = append(changed, repo) |
|
| 93 |
+ } |
|
| 94 |
+ return changed, nil |
|
| 95 |
+} |
|
| 96 |
+ |
|
| 97 |
+type File string |
|
| 98 |
+ |
|
| 99 |
+func (f File) HasGodepsChanges() bool {
|
|
| 100 |
+ return strings.HasPrefix(string(f), "Godeps") |
|
| 101 |
+} |
|
| 102 |
+ |
|
| 103 |
+func (f File) GodepsRepoChanged() (string, error) {
|
|
| 104 |
+ if !f.HasGodepsChanges() {
|
|
| 105 |
+ return "", fmt.Errorf("file doesn't appear to be a Godeps change")
|
|
| 106 |
+ } |
|
| 107 |
+ // Find the _workspace path segment index. |
|
| 108 |
+ workspaceIdx := -1 |
|
| 109 |
+ parts := strings.Split(string(f), string(os.PathSeparator)) |
|
| 110 |
+ for i, part := range parts {
|
|
| 111 |
+ if part == "_workspace" {
|
|
| 112 |
+ workspaceIdx = i |
|
| 113 |
+ break |
|
| 114 |
+ } |
|
| 115 |
+ } |
|
| 116 |
+ // Godeps path struture assumption: Godeps/_workspace/src/... |
|
| 117 |
+ if workspaceIdx == -1 || len(parts) < (workspaceIdx+3) {
|
|
| 118 |
+ return "", fmt.Errorf("file doesn't appear to be a Godeps workspace path")
|
|
| 119 |
+ } |
|
| 120 |
+ // Deal with repos which could be identified by either 2 or 3 path segments. |
|
| 121 |
+ host := parts[workspaceIdx+2] |
|
| 122 |
+ segments := -1 |
|
| 123 |
+ for supportedHost, count := range SupportedHosts {
|
|
| 124 |
+ if host == supportedHost {
|
|
| 125 |
+ segments = count |
|
| 126 |
+ break |
|
| 127 |
+ } |
|
| 128 |
+ } |
|
| 129 |
+ if segments == -1 {
|
|
| 130 |
+ return "", fmt.Errorf("file modifies an unsupported repo host %q", host)
|
|
| 131 |
+ } |
|
| 132 |
+ switch segments {
|
|
| 133 |
+ case 2: |
|
| 134 |
+ return fmt.Sprintf("%s/%s", host, parts[workspaceIdx+3]), nil
|
|
| 135 |
+ case 3: |
|
| 136 |
+ return fmt.Sprintf("%s/%s/%s", host, parts[workspaceIdx+3], parts[workspaceIdx+4]), nil
|
|
| 137 |
+ } |
|
| 138 |
+ return "", fmt.Errorf("file modifies an unsupported repo host %q", host)
|
|
| 139 |
+} |
|
| 140 |
+ |
|
| 141 |
+func CommitsBetween(a, b string) ([]Commit, error) {
|
|
| 142 |
+ commits := []Commit{}
|
|
| 143 |
+ stdout, _, err := run("git", "log", "--oneline", fmt.Sprintf("%s..%s", a, b))
|
|
| 144 |
+ if err != nil {
|
|
| 145 |
+ return nil, fmt.Errorf("error executing git log: %s", err)
|
|
| 146 |
+ } |
|
| 147 |
+ for _, log := range strings.Split(stdout, "\n") {
|
|
| 148 |
+ if len(log) == 0 {
|
|
| 149 |
+ continue |
|
| 150 |
+ } |
|
| 151 |
+ commit, err := NewCommitFromOnelineLog(log) |
|
| 152 |
+ if err != nil {
|
|
| 153 |
+ return nil, err |
|
| 154 |
+ } |
|
| 155 |
+ commits = append(commits, commit) |
|
| 156 |
+ } |
|
| 157 |
+ return commits, nil |
|
| 158 |
+} |
|
| 159 |
+ |
|
| 160 |
+func NewCommitFromOnelineLog(log string) (Commit, error) {
|
|
| 161 |
+ var commit Commit |
|
| 162 |
+ parts := strings.Split(log, " ") |
|
| 163 |
+ if len(parts) < 2 {
|
|
| 164 |
+ return commit, fmt.Errorf("invalid log entry: %s", log)
|
|
| 165 |
+ } |
|
| 166 |
+ commit.Sha = parts[0] |
|
| 167 |
+ commit.Summary = strings.Join(parts[1:], " ") |
|
| 168 |
+ files, err := filesInCommit(commit.Sha) |
|
| 169 |
+ if err != nil {
|
|
| 170 |
+ return commit, err |
|
| 171 |
+ } |
|
| 172 |
+ commit.Files = files |
|
| 173 |
+ return commit, nil |
|
| 174 |
+} |
|
| 175 |
+ |
|
| 176 |
+func filesInCommit(sha string) ([]File, error) {
|
|
| 177 |
+ files := []File{}
|
|
| 178 |
+ stdout, _, err := run("git", "diff-tree", "--no-commit-id", "--name-only", "-r", sha)
|
|
| 179 |
+ if err != nil {
|
|
| 180 |
+ return nil, err |
|
| 181 |
+ } |
|
| 182 |
+ for _, filename := range strings.Split(stdout, "\n") {
|
|
| 183 |
+ if len(filename) == 0 {
|
|
| 184 |
+ continue |
|
| 185 |
+ } |
|
| 186 |
+ files = append(files, File(filename)) |
|
| 187 |
+ } |
|
| 188 |
+ return files, nil |
|
| 189 |
+} |
|
| 190 |
+ |
|
| 191 |
+func run(args ...string) (string, string, error) {
|
|
| 192 |
+ cmd := exec.Command(args[0], args[1:]...) |
|
| 193 |
+ var stdout bytes.Buffer |
|
| 194 |
+ var stderr bytes.Buffer |
|
| 195 |
+ cmd.Stdout = &stdout |
|
| 196 |
+ cmd.Stderr = &stderr |
|
| 197 |
+ err := cmd.Run() |
|
| 198 |
+ return stdout.String(), stderr.String(), err |
|
| 199 |
+} |