Statistics
| Branch: | Tag: | Revision:

root / devflow / autopkg.py @ 866bb9c1

History | View | Annotate | Download (7.6 kB)

1
# Copyright 2012 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
import git
35
import os
36
import sys
37
from sh import mktemp, cd, rm, git_dch, python
38
from optparse import OptionParser
39

    
40
from devflow.versioning import (get_python_version,
41
                                debian_version_from_python_version)
42

    
43
try:
44
    from colors import red, green
45
except ImportError:
46
    red = lambda x: x
47
    green = lambda x: x
48

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

    
52
AVAILABLE_MODES = ["release", "snapshot"]
53

    
54
# TODO: Make the PACKAGES tuple configurable,
55
# read it from autopkg.conf in the git toplevel directory.
56
PACKAGES = ("devflow", )
57

    
58

    
59
def main():
60
    from devflow.version import __version__
61
    parser = OptionParser(usage="usage: %prog [options] mode",
62
                          version="devflow %s" % __version__)
63
    parser.add_option("-k", "--keep-repo",
64
                      action="store_true",
65
                      dest="keep_repo",
66
                      default=False,
67
                      help="Do not delete the cloned repository")
68
    parser.add_option("-b", "--build-dir",
69
                      dest="build_dir",
70
                      default=None,
71
                      help="Directory to store created pacakges")
72
    parser.add_option("-r", "--repo-dir",
73
                      dest="repo_dir",
74
                      default=None,
75
                      help="Directory to clone repository")
76
    parser.add_option("-d", "--dirty",
77
                      dest="force_dirty",
78
                      default=False,
79
                      action="store_true",
80
                      help="Do not check if working directory is dirty")
81

    
82
    (options, args) = parser.parse_args()
83

    
84
    try:
85
        mode = args[0]
86
    except IndexError:
87
        raise ValueError("Mode argument is mandatory. Usage: %s"
88
                         % parser.usage)
89
    if mode not in AVAILABLE_MODES:
90
        raise ValueError(red("Invalid argument! Mode must be one: %s"
91
                         % ", ".join(AVAILABLE_MODES)))
92

    
93
    # Do not prompt for merge message. Required for some Git versions
94
    os.environ["GITFLOW_BUILD_MODE"] = mode
95

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

    
101
    if original_repo.is_dirty() and not options.force_dirty:
102
        toplevel = original_repo.working_dir
103
        raise RuntimeError(red("Repository %s is dirty." % toplevel))
104

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

    
111
    repo = original_repo.clone(repo_dir)
112
    print_green("Cloned current repository to '%s'." % repo_dir)
113

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

    
117
    branch = repo.head.reference.name
118
    if branch == "master":
119
        debian_branch = "debian"
120
    else:
121
        debian_branch = "debian-" + branch
122

    
123
    try:
124
        repo.references[debian_branch]
125
    except IndexError:
126
        # Branch does not exist
127
        repo.git.branch("--track", debian_branch, "origin/" + debian_branch)
128

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

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

    
135
    cd(repo_dir)
136
    python_version = get_python_version()
137
    debian_version = debian_version_from_python_version(python_version)
138
    print_green("The new debian version will be: '%s'" % debian_version)
139

    
140
    dch = git_dch("--debian-branch=%s" % debian_branch,
141
            "--git-author",
142
            "--ignore-regex=\".*\"",
143
            "--multimaint-merge",
144
            "--since=HEAD",
145
            "--new-version=%s" % debian_version)
146
    print_green("Successfully ran '%s'" % " ".join(dch.cmd))
147

    
148
    repo.git.add("debian/changelog")
149

    
150
    if mode == "release":
151
        os.system("vim debian/changelog")
152
        repo.git.add("debian/changelog")
153
        repo.git.commit("-s", "-a", "-m", "Bump new upstream version")
154
        python_tag = python_version
155
        debian_tag = "debian/" + python_tag
156
        repo.git.tag(debian_tag)
157
        repo.git.tag(python_tag, branch)
158

    
159
    for package in PACKAGES:
160
        # python setup.py should run in its directory
161
        cd(package)
162
        package_dir = repo_dir + "/" + package
163
        res = python(package_dir + "/setup.py", "sdist", _out=sys.stdout)
164
        print res.stdout
165
        if package != ".":
166
            cd("../")
167

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

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

    
177
    cd(repo_dir)
178
    os.system("git-buildpackage --git-export-dir=%s --git-upstream-branch=%s"
179
              " --git-debian-branch=%s --git-export=INDEX --git-ignore-new -sa"
180
              % (build_dir, branch, debian_branch))
181

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

    
188
    print_green("Completed. Version '%s', build area: '%s'"
189
                % (debian_version, build_dir))
190

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

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

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

    
202
        print_green(UPDATE_MSG % (origin_url, repo_dir, debian_branch,
203
                    debian_tag, python_tag))
204
        print_green(UPDATE_MSG % (remote_url, original_repo.working_dir,
205
                    debian_branch, debian_tag, python_tag))
206

    
207

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