~andrewjbeach/juju-ci-tools/make-local-patcher

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#!/usr/bin/python
"""Merge gating script for git go projects."""

from __future__ import print_function

import argparse
import os
import subprocess
import sys

from utility import (
    print_now,
    temp_dir,
)


class SubcommandError(Exception):

    def __init__(self, command, subcommand, error):
        self.command = command
        self.subcommand = subcommand
        self.error = error

    def __str__(self):
        return "Subprocess {} {} failed with code {}".format(
            self.command, self.subcommand, self.error.returncode)


class SubcommandRunner(object):

    def __init__(self, command, environ=None):
        self.command = command
        self.subprocess_kwargs = {}
        if environ is not None:
            self.subprocess_kwargs["env"] = environ

    def __call__(self, subcommand, *args):
        cmdline = [self.command, subcommand]
        cmdline.extend(args)
        try:
            subprocess.check_call(cmdline, **self.subprocess_kwargs)
        except subprocess.CalledProcessError as e:
            raise SubcommandError(self.command, subcommand, e)


def go_test(args, gopath):
    """Download, build and test a go package."""
    goenv = dict(os.environ)
    goenv["GOPATH"] = gopath
    go = SubcommandRunner("go", goenv)
    git = SubcommandRunner("git")
    project_ellipsis = args.project + "/..."
    directory = os.path.join(gopath, "src", args.project)
    if args.tsv_path:
        print_now("Getting and installing godeps")
        go("get", "-v", "-d", "launchpad.net/godeps/...")
        go("install", "launchpad.net/godeps/...")
    if args.project_url:
        print_now("Cloning {} from {}".format(args.project, args.project_url))
        git("clone", args.project_url, directory)
    if args.go_get_all:
        print_now("Getting {} and dependencies using go".format(args.project))
        go("get", "-v", "-d", "-t", project_ellipsis)
    os.chdir(directory)
    if args.project_ref:
        print_now("Switching repository to {}".format(args.project_ref))
        git("checkout", args.project_ref)
    if args.merge_url:
        print_now("Merging {} ref {}".format(args.merge_url, args.merge_ref))
        git("fetch", args.merge_url, args.merge_ref)
        git("merge", "--no-ff", "-m", "Merged " + args.merge_ref, "FETCH_HEAD")
    if args.dependencies:
        for dep in args.dependencies:
            print_now("Getting {} and dependencies using go".format(dep))
            go("get", "-v", "-d", dep)
    if args.tsv_path:
        tsv_path = os.path.join(gopath, "src", args.tsv_path)
        print_now("Getting dependencies using godeps from {}".format(tsv_path))
        godeps = SubcommandRunner(os.path.join(gopath, "bin", "godeps"), goenv)
        godeps("-u", tsv_path)
    go("build", project_ellipsis)
    go("test", project_ellipsis)


def parse_args(args=None):
    """Parse arguments for gating script."""
    parser = argparse.ArgumentParser()
    project_group = parser.add_argument_group()
    project_group.add_argument(
        "--keep", action="store_true",
        help="Do not remove working dir after testing.")
    project_group.add_argument(
        "--project", required=True, help="Go import path of package to test.")
    project_group.add_argument(
        "--project-url", help="URL to git repository of package.")
    project_group.add_argument(
        "--project-ref", help="Branch name or tag to use as basis.")
    merge_group = parser.add_argument_group()
    merge_group.add_argument(
        "--merge-url", help="URL to git repository to merge before testing.")
    merge_group.add_argument(
        "--merge-ref", default="HEAD",
        help="Branch name or tag to merge before testing.")
    dep_group = parser.add_mutually_exclusive_group()
    dep_group.add_argument(
        "--dependencies", nargs="+",
        help="Any number of package import paths needed for build or testing.")
    dep_group.add_argument(
        "--go-get-all", action="store_true",
        help="Go import path of package needed to for build or testing.")
    dep_group.add_argument(
        "--tsv-path",
        help="Path to dependencies.tsv file for project relative to src dir.")
    args = parser.parse_args(args)
    if args.project_url is None and not args.go_get_all:
        parser.error("Must supply either --project-url or --go-get-all")
    return args


def main():
    args = parse_args()
    with temp_dir(keep=args.keep) as d:
        try:
            go_test(args, d)
        except SubcommandError as err:
            print(err, file=sys.stderr)
            return 1
    return 0


if __name__ == '__main__':
    sys.exit(main())