Home Home > GIT Browse
summaryrefslogtreecommitdiff
blob: fb9ca36956e0995bdcc3f16db289ced4c8435416 (plain)
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env python
"""
xen-port-patches.py [git dir]
Create custom patches for xen from custom patches that affect x86.
Turned out to be a little functional programming exercise for the author.
(c) 2005-04-06, Kurt Garloff <garloff@suse.de>
"""

import re, glob, sys, os, filecmp

# List of replacement rules
replrules = [(r"(.*)-xen(\.[^/\s])", r"\1\2"),
	   (r"include/asm-([^/\s]+86[^/\s]*)/mach-xen/asm/", r"include/asm-\1/"),
	   (r"arch/([^/\s]+86[^/\s]*)/include/mach-xen/asm/", r"arch/\1/include/asm/")]
# List of compiled rules (speed reasons)
#comprules = map(lambda(x): (x[0], x[1], re.compile(x[0])), replrules)
comprules = [ (x[0], x[1], re.compile(x[0])) for x in replrules ]

def applCorrFwd(path):
	"Try to apply replrules, return void elem if none applied, otherwise \
	 corresponding old and new name"
	# Maximal functional programming obfusc^W elegance
		# Drop element 2 from each tupel
	return map(lambda(x): (x[0], x[1]), \
		# Filter out non-matched path combinations
		filter(lambda(x): x[2], \
		# Try all replacement rules
		map(lambda(x): (path, 
			re.sub(x[0], x[1], path), x[2].search(path)),
			comprules)))


def createReplList(patch):
	"Creates a list of files to watch and their corresp xen file names"
	pfile = open(patch, "r")
	srch = re.compile(r"^\+\+\+ [^/\s]+/([\S]*)")
	# Again illegi^W beautiful functional programming
	# return matched string no 1
	matches = map(lambda(m): m.group(1), \
		# filter out non-matches
		filter(lambda(m): m, \
		# find matches
		map(lambda(line): srch.search(line), pfile)))
	pfile.close()
	#print matches
	# Try path replacements, drop empty elements and one nesting level
	return map(lambda(x): (x[0][0], x[0][1]), \
			filter(lambda(x): x, map(applCorrFwd, matches)))

def findPatchFiles(kgit):
	"Returns a list of all files in patches.*/ on below kgit"
	list = glob.glob(kgit + "/patches.*/*")
	# Avoid patches in patches.xen, backup files
	filterout = re.compile("(patches\.xen|~$|\.#)")
	return filter(lambda(x): not filterout.search(x), list)

def writePatch(fname, hdr, body):
	"Create xen patch corresponding to other patch"
	xenrepl = re.compile(r"^.*\/([^\/]*)$")
	xenfname = re.sub(xenrepl, r"xen3-\1", fname)
	shortrepl = re.compile(r"^.*\/([^\/]*\/[^\/]*)$")
	shortname = re.sub(shortrepl, r"\1", fname)
	origname = ".".join([xenfname, "orig"])
	print "%s -> %s" % (shortname, xenfname)
	if os.access(xenfname, os.F_OK):
		os.rename(xenfname, origname)
	pfile = open(xenfname, "w")
	pfile.write(hdr)
	pfile.write("Automatically created from \"%s\" by " \
			"xen-port-patches.py\n\n" % shortname)
	pfile.write(body)
	pfile.close()
	if os.access(origname, os.F_OK):
		if filecmp.cmp(xenfname, origname):
			os.remove(xenfname)
	else:
		ser = open("xen3-series.conf", "a")
		ser.write("\t\t%s\n" % xenfname)
		ser.close()

def decorateSubject(subject):
	m = re.search(r"^(Subject:\s*(?:\[.*\])?\s*)(.*)", subject);
	if not m:
		return subject
	if re.search(r"^[^\s]*:[^:]*$", m.group(2)):
		# subsystem: text -> xen/subsystem: text
		tag = "xen/"
	else:
		# text -> xen: text
		tag = "xen: "
	return m.group(1) + tag + m.group(2) + "\n"

def mayCreatePatch(fname, repls):
	"Try to apply the replacement rules to fname"
	if fname.endswith(".gz"):
		decomp ="gzip"
	elif fname.endswith(".bz2"):
		decomp = "bzip2"
	elif fname.endswith(".xz"):
		decomp = "xz"
	else:
		decomp = ""
	if decomp == "":
		pfile = open(fname, "r")
	else:
		pfile = os.popen(" ".join([decomp, "-dc", fname]), "r")
		parts = fname.split(".")
		del parts[-1]
		fname = ".".join(parts)
	# Again an unelegant loop with an ugly state machine
	active = 0; header = 0
	patch = ""; rule = ()
	patchheader = ""; pheaderactive = 1
	endmarker = re.compile(r"^(Index|diff|CVS|RCS|\-\-\-|\+\+\+|===)")
	subj = re.compile(r"^Subject:\s")
	commit = re.compile(r"^Git-[Cc]ommit:\s")
	mainline = re.compile(r"^Patch-[Mm]ainline:\s")
	for line in pfile:
		hmark = endmarker.search(line)
		if pheaderactive:
			if hmark:
				pheaderactive = 0
			else:
				if subj and subj.search(line):
					subj = None
					line = decorateSubject(line)
				elif commit.search(line):
					continue
				elif mainline.search(line):
					line = "Patch-mainline: Never, SUSE-Xen specific\n"
				patchheader += line
				continue
		# If we get here, we're past the patch file header
		if active:
			if header:
				if not hmark:
					header = 0
				#else:
				patch += re.sub(rule[1], rule[0], line)
			else:
				if hmark:
					active = 0
				else:
					patch += line
		# else is no good, need to test again
		if not active and hmark:
			matches = filter(lambda(x): x[2],
				map(lambda(x): (x[0], x[1], x[2].search(line)), repls))
			if matches:
				active = 1; header = 1
				# There should never be more than one match ...
				rule = (matches[0][0], matches[0][1])
				patch += re.sub(rule[1], rule[0], line)
	pfile.close()
	if patch:
		writePatch(fname, patchheader, patch)

def createXenPatches(filelist, repls):
	"For each file in the list, find hunks that may be needed for Xen"
	# We could do this again with functional programming, but the
	# memory requirements may be significant, so let's create a
	# loop on the per patchfile level.
	for pfile in filelist:
		mayCreatePatch(pfile, repls)

def main(args):
	"Main program"
	# Allow overriding kernel git dir
	if len(args) > 1 and args[1] != ".":
		kerngit = args[1]
	else:
		kerngit = re.sub(r"^(.*)/[^/]+/[^/]+$", r"\1", os.path.abspath(args[0]))
	print "Using kernel git at '%s'" % (kerngit)
	# Create list of replacements
	repllist = createReplList(kerngit + "/patches.xen/xen3-auto-xen-arch.diff")
	#print repllist
	# ... and compile
	complrepl = map(lambda(x): (x[0], x[1], re.compile(x[1])), repllist)
	# Create a list of patch files
	patchfiles = findPatchFiles(kerngit)
	#print patchfiles
	createXenPatches(patchfiles + args[2:], complrepl)

# Entry point
if __name__ == '__main__':
	main(sys.argv)