root / devflow / flow.py @ c3c33dd0
History | View | Annotate | Download (5.7 kB)
1 |
import os |
---|---|
2 |
|
3 |
import logging |
4 |
logging.basicConfig() |
5 |
from optparse import OptionParser |
6 |
|
7 |
os.environ["GIT_PYTHON_TRACE"] = "full" |
8 |
from devflow import utils, versioning |
9 |
from devflow.version import __version__ |
10 |
from devflow.autopkg import call |
11 |
from functools import wraps |
12 |
from contextlib import contextmanager |
13 |
from git.exc import GitCommandError |
14 |
|
15 |
|
16 |
def cleanup(func): |
17 |
@wraps(func)
|
18 |
def wrapper(self, *args, **kwargs): |
19 |
try:
|
20 |
return func(self, *args, **kwargs) |
21 |
except:
|
22 |
self.log.debug("Unexpected ERROR. Cleaning up repository...") |
23 |
self.repo.git.reset("--hard", "HEAD") |
24 |
self.repo.git.checkout(self.start_branch) |
25 |
self.repo.git.reset("--hard", self.start_hex) |
26 |
for branch in self.new_branches: |
27 |
self.repo.git.branch("-D", branch) |
28 |
for tag in self.new_tags: |
29 |
self.repo.git.tag("-D", tag) |
30 |
raise
|
31 |
return wrapper
|
32 |
|
33 |
|
34 |
@contextmanager
|
35 |
def conflicts(): |
36 |
try:
|
37 |
yield
|
38 |
except GitCommandError as e: |
39 |
if e.status != 128: |
40 |
print "An error occured. Resolve it and type 'exit'" |
41 |
call("bash")
|
42 |
else:
|
43 |
raise
|
44 |
|
45 |
|
46 |
class GitManager(object): |
47 |
def __init__(self): |
48 |
self.repo = utils.get_repository()
|
49 |
self.start_branch = self.repo.active_branch.name |
50 |
self.start_hex = self.repo.head.log()[-1].newhexsha |
51 |
self.log = logging.getLogger("") |
52 |
self.log.setLevel(logging.DEBUG)
|
53 |
self.log.info("Repository: %s. HEAD: %s", self.repo, self.start_hex) |
54 |
self.new_branches = []
|
55 |
self.new_tags = []
|
56 |
self.repo.git.pull("origin") |
57 |
|
58 |
@cleanup
|
59 |
def start_release(self, version): |
60 |
self.start_common("release", version) |
61 |
|
62 |
@cleanup
|
63 |
def start_hotfix(self, version): |
64 |
self.start_common("hotfix", version) |
65 |
|
66 |
@cleanup
|
67 |
def end_release(self, version): |
68 |
self.end_common("release", version) |
69 |
|
70 |
@cleanup
|
71 |
def end_hotfix(self, version): |
72 |
self.end_common("hotfix", version) |
73 |
|
74 |
def start_common(self, mode, version): |
75 |
if mode not in ["release", "hotfix"]: |
76 |
raise ValueError("Unknown mode: %s" % mode) |
77 |
repo = self.repo
|
78 |
upstream = "develop" if mode == "release" else "master" |
79 |
debian = "debian-develop" if mode == "release" else "debian" |
80 |
upstream_branch = "%s-%s" % (mode, version)
|
81 |
debian_branch = "debian-%s-%s" % (mode, version)
|
82 |
repo.git.checkout(upstream) |
83 |
repo.git.branch(upstream_branch, upstream) |
84 |
self.new_branches.append(upstream_branch)
|
85 |
versioning.bump_version("%snext" % version)
|
86 |
repo.git.checkout(upstream_branch) |
87 |
versioning.bump_version("%src1" % version)
|
88 |
repo.git.checkout(debian) |
89 |
repo.git.branch(debian_branch, debian) |
90 |
self.new_branches.append(debian_branch)
|
91 |
repo.git.checkout(upstream_branch) |
92 |
repo.git.checkout(debian) |
93 |
|
94 |
@cleanup
|
95 |
def start_feature(self, feature_name): |
96 |
repo = self.repo
|
97 |
feature_upstream = "feature-%s" % feature_name
|
98 |
feature_debian = "debian-%s" % feature_upstream
|
99 |
repo.git.branch(feature_upstream, "develop")
|
100 |
self.new_branches.append(feature_upstream)
|
101 |
repo.git.branch(feature_debian, "debian-develop")
|
102 |
self.new_branches.append(feature_debian)
|
103 |
|
104 |
@cleanup
|
105 |
def end_feature(self, feature_name): |
106 |
repo = self.repo
|
107 |
feature_upstream = "feature-%s" % feature_name
|
108 |
if not feature_upstream in repo.branches: |
109 |
raise ValueError("Branch %s does not exist." % feature_upstream) |
110 |
feature_debian = "debian-%s" % feature_upstream
|
111 |
repo.git.checkout("develop")
|
112 |
with conflicts():
|
113 |
repo.git.merge(feature_upstream) |
114 |
repo.git.checkout("debian-develop")
|
115 |
if feature_debian in repo.branches: |
116 |
with conflicts():
|
117 |
repo.git.merge(feature_debian) |
118 |
repo.git.checkout("develop")
|
119 |
print "To remove obsolete branches run:" |
120 |
print "git branch -D %s" % feature_upstream |
121 |
if feature_debian in repo.branches: |
122 |
print "git branch -D %s" % feature_debian |
123 |
|
124 |
def end_common(self, mode, version): |
125 |
if mode not in ["release", "hotfix"]: |
126 |
raise ValueError("Unknown mode: %s" % mode) |
127 |
repo = self.repo
|
128 |
master = "master"
|
129 |
upstream = "develop" if mode == "release" else "master" |
130 |
debian = "debian-develop" if mode == "release" else "debian" |
131 |
upstream_branch = "%s-%s" % (mode, version)
|
132 |
debian_branch = "debian-%s-%s" % (mode, version)
|
133 |
repo.git.checkout(upstream) |
134 |
with conflicts():
|
135 |
repo.git.merge("--no-ff", upstream_branch)
|
136 |
repo.git.checkout(master) |
137 |
with conflicts():
|
138 |
repo.git.merge("--no-ff", upstream_branch)
|
139 |
repo.git.checkout(debian) |
140 |
with conflicts():
|
141 |
repo.git.merge("--no-ff", debian_branch)
|
142 |
repo.git.checkout(upstream) |
143 |
print "To remove obsolete branches run:" |
144 |
print "git branch -d %s" % upstream_branch |
145 |
print "git branch -d %s" % debian_branch |
146 |
|
147 |
|
148 |
def refhead(repo): |
149 |
return repo.head.log[-1].newhexsha |
150 |
|
151 |
|
152 |
def main(): |
153 |
HELP_MSG = "usage: %prog mode=[release|hotfix|feature]"\
|
154 |
" [version|name]"
|
155 |
parser = OptionParser(usage=HELP_MSG, |
156 |
version="devflow-flow %s" % __version__,
|
157 |
add_help_option=True)
|
158 |
options, args = parser.parse_args() |
159 |
if len(args) != 3: |
160 |
parser.error("Invalid number of arguments.")
|
161 |
mode, action, version = args |
162 |
gm = GitManager() |
163 |
func = "%s_%s" % (action, mode)
|
164 |
try:
|
165 |
getattr(gm, func)(version)
|
166 |
except AttributeError: |
167 |
parser.error("Invalid arguments.")
|
168 |
|
169 |
if __name__ == "__main__": |
170 |
main() |