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()) |