blob: 06fec4e0d7fa6a5078d9295192040ada90a35ec9 [file] [log] [blame]
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001#! /usr/bin/python
2
3# Basic instructions
4#
5# 1. Save patch email to file [patch.email]
6#
7# 2. Go to the svn directory to which you want to apply the patch.
8#
9# 3. Run "selinux-maint split patch.email". This will run vi on the
10# logmsg (pulled out of the email) to allow you to add anything (ack
11# messages). When you quit vi the current directory will have files
12# called "patch" and "logmsg".
13#
14# 4. Run "selinux-maint apply" (optionally with a strip level as
15# the last argument). This will do a dry run of applying the patch
16# showing the results and ask if you want to apply the patch. If you
17# say yes it will apply the patch and attempt to detect file adds (by
18# comparing svn status and the output of patch). If it finds adds it
19# will ask if you want to add each file.
20#
21# 5. Run "selinux-maint commit" to commit that patch with the log
22# message.
23#
24# 6. Repeat 4 and 5 as often as necessary for a set of patch emails.
25#
26# 7. Run "selinux-maint rev packagename" where packagename is
27# something like "libsepol". This will prompt for the new version
28# number (showing the current), update VERSION, add a Changelog entry
29# with the version and date, and vi the changelog for you to add
30# entries.
31#
32# 8. Run "selinux-maint commit" again to commit the revision change
33# (rev adds a simple log message - I just fixed this as my last
34# checkin had the wrong log message).
35
36import sys
37import subprocess
38import shutil
39import os
40import os.path
41import datetime
42
43dir = "/tmp/selinux-maint/"
44
45def usage():
46 print "selinux-maint [command] [options]"
47 print ""
48 print "commands:"
49 print "\tsplit patch-email: split patch-email into a patch and log message"
50 print "\tapply [patch-level]: apply the patch and logmsg with optional level"
51 print "\tcommit username: commit the changes"
52 print "\trev package: update the version number and changelog of package"
53 print "\tmerge reva:revb source-branch: merge changes to the current branch"
54
55def create_tmpdir():
56 try:
57 os.mkdir(dir)
58 except OSError:
59 if not os.path.isdir(dir):
60 print "path %s exists and is not a directory" % dir
61 sys.exit(1)
62
63def split_email(args):
64 # Get an absolute path for the patch email since we are going to
65 # change the working directory
66 patch_path = os.path.abspath(args[0])
67
68 create_tmpdir()
69 prevdir = os.getcwd()
70 os.chdir(dir)
71
72 infd = open(patch_path)
73 outfd = open("info", "w")
74 retcode = subprocess.call(["git-mailinfo", "msg", "patch"], stdin=infd,
75 stdout=outfd)
76 if retcode != 0:
77 sys.exit(1)
78
79 msgfd = open("logmsg", "w")
80 retcode = subprocess.call(["cat", "info", "msg"], stdout=msgfd)
81
82 msgfd.close()
83
84 retcode = subprocess.call(["vi", "logmsg"])
85
86 shutil.copyfile("logmsg", prevdir + "/logmsg")
87 shutil.copyfile("patch", prevdir + "/patch")
88
89def apply(args):
90 if len(args) >= 1:
91 patch_level = "-p%d" % int(args[0])
92 else:
93 patch_level = "-p1"
94
95 if len(args) == 2:
96 patch_name = "../patch"
97 patch_dir = args[1]
98 else:
99 patch_name = "patch"
100 patch_dir = None
101
102 print "Test applying patch:"
103 if patch_dir:
104 os.chdir(patch_dir)
105
106 patchfd = open(patch_name)
107 retcode = subprocess.call(["patch", patch_level, "--dry-run", "-l"], stdin=patchfd)
108 resp = raw_input("apply [y/n]: ")
109 if resp != "y":
110 sys.exit(0)
111
112 patchfd = open(patch_name)
113 patch_output = subprocess.Popen(["patch", patch_level, "-l"], stdin=patchfd,
114 stdout=subprocess.PIPE).communicate()[0]
115
116 status_output = subprocess.Popen(["svn", "status"], stdout=subprocess.PIPE).communicate()[0]
117
118
119 # Detect adds
120 unknown_files = []
121 for status_line in status_output.split("\n"):
122 try:
123 status, fname = status_line.split()
124 except ValueError:
125 continue
126 if status == "?":
127 unknown_files.append(fname)
128
129 added_files = []
130 for patch_line in patch_output.split("\n"):
131 try:
132 patched_fname = patch_line.split(" ")[2]
133 except:
134 continue
135 if patched_fname in unknown_files:
136 added_files.append(patched_fname)
137
138 for fname in added_files:
139 input = raw_input("add file %s [y/n]: " % fname)
140 if input == "y":
141 subprocess.call(["svn", "add", fname])
142
143def commit(args):
144 if len(args) == 1:
145 retcode = subprocess.call(["svn", "commit", "--username", args[0], "-F", "logmsg"])
146 else:
147 retcode = subprocess.call(["svn", "commit", "-F", "logmsg"])
148
149
150def rev(args):
151 if len(args) != 1:
152 print "you must provide a package name"
153 usage()
154 sys.exit(1)
155 package = args[0]
156
157 ver_fd = open("%s/VERSION" % package, "r")
158 cur = ver_fd.read()
159 cur = cur.split("\n")[0]
160 ver_fd.close()
161 input = raw_input("new version [current is %s]: " % cur)
162 new_fd = open("%s/VERSION.new" % package, "w")
163 new_fd.write(input + "\n")
164 new_fd.close()
165 shutil.copyfile("%s/VERSION.new" % package, "%s/VERSION" % package)
166
167 old_changelog = "%s/ChangeLog" % package
168 new_changelog = "%s/ChangeLog.new" % package
169
170 n = open(new_changelog, "w")
171
172 entry = "%s %s\n" % (input, str(datetime.date.today()))
173 n.write(entry)
174 n.write("\t*\n\n")
175 o = open(old_changelog)
176 n.write(o.read())
177 n.close()
178 o.close()
179
180 subprocess.call(["vi", new_changelog])
181 shutil.copyfile(new_changelog, old_changelog)
182
183 logmsg = open("logmsg", "w")
184 logmsg.write("updated %s to version %s\n" % (package, input))
185
186def merge(args):
187 if len(args) != 2:
188 print "you must provide a revision pair and source branch"
189 usage()
190 sys.exit(1)
191
192 rev = args[0]
193 branch = args[1]
194
195 if branch == "trunk":
196 url = "https://selinux.svn.sourceforge.net/svnroot/selinux/trunk"
197 elif branch == "stable":
198 url = "https://selinux.svn.sourceforge.net/svnroot/selinux/branches/stable/1_0"
199 else:
200 url = "https://selinux.svn.sourceforge.net/svnroot/selinux/branches/%s" % branch
201
202 subprocess.call(["svn", "diff", "-r%s" % rev, url])
203 input = raw_input("apply these changes [y/n]? ")
204 if input != "y":
205 sys.exit(0)
206
207 subprocess.call(["svn", "merge", "-r%s" % rev, url])
208
209 logmsg = open("logmsg", "w")
210 logmsg.write("applied r%s from %s\n" % (rev, branch))
211
212
213def main():
214 if len(sys.argv) < 2:
215 usage()
216 sys.exit(1)
217
218 command = sys.argv[1]
219 if command == "split":
220 split_email(sys.argv[2:])
221 elif command == "apply":
222 apply(sys.argv[2:])
223 elif command == "commit":
224 commit(sys.argv[2:])
225 elif command == "rev":
226 rev(sys.argv[2:])
227 elif command == "merge":
228 merge(sys.argv[2:])
229 else:
230 usage()
231
232main()