autopkg.py 8.18 KB
Newer Older
Vangelis Koukis's avatar
Vangelis Koukis committed
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
# Copyright 2012 GRNET S.A. All rights reserved.
#
# Redistribution and use in source and binary forms, with or
# without modification, are permitted provided that the following
# conditions are met:
#
#   1. Redistributions of source code must retain the above
#      copyright notice, this list of conditions and the following
#      disclaimer.
#
#   2. Redistributions in binary form must reproduce the above
#      copyright notice, this list of conditions and the following
#      disclaimer in the documentation and/or other materials
#      provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# The views and conclusions contained in the software and
# documentation are those of the authors and should not be
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.

import git
import os
import sys
from sh import mktemp, cd, rm, git_dch, python
from optparse import OptionParser

Christos Stavrakakis's avatar
Christos Stavrakakis committed
40
41
42
from devflow.versioning import (get_python_version,
                                debian_version_from_python_version)

Vangelis Koukis's avatar
Vangelis Koukis committed
43
44
45
46
47
48
49
50
51
52
53
try:
    from colors import red, green
except ImportError:
    red = lambda x: x
    green = lambda x: x

print_red = lambda x: sys.stdout.write(red(x) + "\n")
print_green = lambda x: sys.stdout.write(green(x) + "\n")

AVAILABLE_MODES = ["release", "snapshot"]

Christos Stavrakakis's avatar
Christos Stavrakakis committed
54
55
56
57
58
59
60
61
62
63
64
65

def get_packages_to_build(toplevel_dir):
    conf_file = os.path.join(toplevel_dir, "autopkg.conf")
    try:
        f = open(conf_file)
    except IOError:
        raise RuntimeError("Configuration file %s does not exist!" % conf_file)

    lines = [l.strip() for l in f.readlines()]
    l = [l for l in lines if not l.startswith("#")]
    f.close()
    return l
Vangelis Koukis's avatar
Vangelis Koukis committed
66
67
68
69
70


def main():
    from devflow.version import __version__
    parser = OptionParser(usage="usage: %prog [options] mode",
Christos Stavrakakis's avatar
Christos Stavrakakis committed
71
                          version="devflow %s" % __version__)
Vangelis Koukis's avatar
Vangelis Koukis committed
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    parser.add_option("-k", "--keep-repo",
                      action="store_true",
                      dest="keep_repo",
                      default=False,
                      help="Do not delete the cloned repository")
    parser.add_option("-b", "--build-dir",
                      dest="build_dir",
                      default=None,
                      help="Directory to store created pacakges")
    parser.add_option("-r", "--repo-dir",
                      dest="repo_dir",
                      default=None,
                      help="Directory to clone repository")
    parser.add_option("-d", "--dirty",
                      dest="force_dirty",
                      default=False,
                      action="store_true",
                      help="Do not check if working directory is dirty")

    (options, args) = parser.parse_args()

Christos Stavrakakis's avatar
Christos Stavrakakis committed
93
94
95
96
97
    try:
        mode = args[0]
    except IndexError:
        raise ValueError("Mode argument is mandatory. Usage: %s"
                         % parser.usage)
Vangelis Koukis's avatar
Vangelis Koukis committed
98
99
100
101
102
103
104
105
106
107
108
    if mode not in AVAILABLE_MODES:
        raise ValueError(red("Invalid argument! Mode must be one: %s"
                         % ", ".join(AVAILABLE_MODES)))

    os.environ["GITFLOW_BUILD_MODE"] = mode

    try:
        original_repo = git.Repo(".")
    except git.git.InvalidGitRepositoryError:
        raise RuntimeError(red("Current directory is not git repository."))

Christos Stavrakakis's avatar
Christos Stavrakakis committed
109
    toplevel = original_repo.working_dir
Vangelis Koukis's avatar
Vangelis Koukis committed
110
111
112
113
114
115
116
117
118
    if original_repo.is_dirty() and not options.force_dirty:
        raise RuntimeError(red("Repository %s is dirty." % toplevel))

    repo_dir = options.repo_dir
    if not repo_dir:
        repo_dir = mktemp("-d", "/tmp/devflow-build-repo-XXX").stdout.strip()
        print_green("Created temporary directory '%s' for the cloned repo."
                    % repo_dir)

Christos Stavrakakis's avatar
Christos Stavrakakis committed
119
120
121
122
123
124
125
126
    packages = get_packages_to_build(toplevel)
    if packages:
        print_green("Will build the following packages:\n" + \
                    "\n".join(packages))
    else:
        raise RuntimeError("Configuration file is empty."
                           " No packages to build.")

Vangelis Koukis's avatar
Vangelis Koukis committed
127
128
129
130
131
132
133
134
135
136
137
138
    repo = original_repo.clone(repo_dir)
    print_green("Cloned current repository to '%s'." % repo_dir)

    reflog_hexsha = repo.head.log()[-1].newhexsha
    print "Latest Reflog entry is %s" % reflog_hexsha

    branch = repo.head.reference.name
    if branch == "master":
        debian_branch = "debian"
    else:
        debian_branch = "debian-" + branch

139
140
141
142
143
144
145
    if not debian_branch in repo.references:
        # Branch does not exist!
        if "origin/" + debian_branch in repo.references:
            remote = "origin/" + debian_branch
        else:
            remote = "origin/debian-develop"
        repo.git.branch("--track", debian_branch, remote)
Vangelis Koukis's avatar
Vangelis Koukis committed
146
147
148
149
150
151
152
153

    repo.git.checkout(debian_branch)
    print_green("Changed to branch '%s'" % debian_branch)

    repo.git.merge(branch)
    print_green("Merged branch '%s' into '%s'" % (branch, debian_branch))

    cd(repo_dir)
Christos Stavrakakis's avatar
Christos Stavrakakis committed
154
155
156
    python_version = get_python_version()
    debian_version = debian_version_from_python_version(python_version)
    print_green("The new debian version will be: '%s'" % debian_version)
Vangelis Koukis's avatar
Vangelis Koukis committed
157
158
159
160
161
162

    dch = git_dch("--debian-branch=%s" % debian_branch,
            "--git-author",
            "--ignore-regex=\".*\"",
            "--multimaint-merge",
            "--since=HEAD",
Christos Stavrakakis's avatar
Christos Stavrakakis committed
163
            "--new-version=%s" % debian_version)
Vangelis Koukis's avatar
Vangelis Koukis committed
164
165
    print_green("Successfully ran '%s'" % " ".join(dch.cmd))

166
    os.system("vim debian/changelog")
Vangelis Koukis's avatar
Vangelis Koukis committed
167
168
169
    repo.git.add("debian/changelog")

    if mode == "release":
Christos Stavrakakis's avatar
Christos Stavrakakis committed
170
171
        os.system("vim debian/changelog")
        repo.git.add("debian/changelog")
Vangelis Koukis's avatar
Vangelis Koukis committed
172
        repo.git.commit("-s", "-a", "-m", "Bump new upstream version")
Christos Stavrakakis's avatar
Christos Stavrakakis committed
173
174
175
176
        python_tag = python_version
        debian_tag = "debian/" + python_tag
        repo.git.tag(debian_tag)
        repo.git.tag(python_tag, branch)
Vangelis Koukis's avatar
Vangelis Koukis committed
177

Christos Stavrakakis's avatar
Christos Stavrakakis committed
178
    for package in packages:
Vangelis Koukis's avatar
Vangelis Koukis committed
179
180
181
182
183
        # python setup.py should run in its directory
        cd(package)
        package_dir = repo_dir + "/" + package
        res = python(package_dir + "/setup.py", "sdist", _out=sys.stdout)
        print res.stdout
Christos Stavrakakis's avatar
Christos Stavrakakis committed
184
185
        if package != ".":
            cd("../")
Vangelis Koukis's avatar
Vangelis Koukis committed
186
187
188
189
190
191
192
193
194
195

    # Add version.py files to repo
    os.system("grep \"__version_vcs\" -r . -l -I | xargs git add -f")

    build_dir = options.build_dir
    if not options.build_dir:
        build_dir = mktemp("-d", "/tmp/devflow-build-XXX").stdout.strip()
        print_green("Created directory '%s' to store the .deb files." %
                     build_dir)

Christos Stavrakakis's avatar
Christos Stavrakakis committed
196
    cd(repo_dir)
Vangelis Koukis's avatar
Vangelis Koukis committed
197
198
199
200
201
202
203
204
205
206
207
    os.system("git-buildpackage --git-export-dir=%s --git-upstream-branch=%s"
              " --git-debian-branch=%s --git-export=INDEX --git-ignore-new -sa"
              % (build_dir, branch, debian_branch))

    if not options.keep_repo:
        print_green("Removing cloned repo '%s'." % repo_dir)
        rm("-r", repo_dir)
    else:
        print_green("Repository dir '%s'" % repo_dir)

    print_green("Completed. Version '%s', build area: '%s'"
Christos Stavrakakis's avatar
Christos Stavrakakis committed
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
                % (debian_version, build_dir))

    if mode == "release":
        TAG_MSG = "Tagged branch %s with tag %s\n"
        print_green(TAG_MSG % (branch, python_tag))
        print_green(TAG_MSG % (debian_branch, debian_tag))

        UPDATE_MSG = "To update repository %s, go to %s, and run the"\
                     " following commands:\n" + "git_push origin %s\n" * 3

        origin_url = repo.remotes['origin'].url
        remote_url = original_repo.remotes['origin'].url

        print_green(UPDATE_MSG % (origin_url, repo_dir, debian_branch,
                    debian_tag, python_tag))
        print_green(UPDATE_MSG % (remote_url, original_repo.working_dir,
                    debian_branch, debian_tag, python_tag))
Vangelis Koukis's avatar
Vangelis Koukis committed
225
226
227
228


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