Merge lp:~pfalcon/linaro-android-build-tools/uniseed into lp:linaro-android-build-tools

Proposed by Paul Sokolovsky
Status: Merged
Approved by: James Tunnicliffe
Approved revision: 399
Merged at revision: 398
Proposed branch: lp:~pfalcon/linaro-android-build-tools/uniseed
Merge into: lp:linaro-android-build-tools
Diff against target: 155 lines (+146/-0)
2 files modified
utils/seeded-builds/manifest-union (+127/-0)
utils/seeded-builds/seed-update (+19/-0)
To merge this branch: bzr merge lp:~pfalcon/linaro-android-build-tools/uniseed
Reviewer Review Type Date Requested Status
James Tunnicliffe (community) Approve
Review via email: mp+89923@code.launchpad.net

Description of the change

Tools to prepare and manage universal seed ("uniseed") for Android platform builds.

To post a comment you must log in.
Revision history for this message
James Tunnicliffe (dooferlad) wrote :

Looks fine. You could add comments/documentation if you wanted :-)

review: Approve
400. By Paul Sokolovsky

Add comments/descriptions for new scripts.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'utils/seeded-builds/manifest-union'
2--- utils/seeded-builds/manifest-union 1970-01-01 00:00:00 +0000
3+++ utils/seeded-builds/manifest-union 2012-01-24 22:35:27 +0000
4@@ -0,0 +1,127 @@
5+#!/usr/bin/env python
6+"""
7+Produce set-theorhetic union of several Android manifests. Each project
8+appearing in any manifest gets output once, and at most once, to the
9+resulting manifest. Differences in checkout path/branch are ignored -
10+values from a random occurance are output in result. The output is
11+mostly intended for usage with "repo init --mirror", to produce mirror
12+which contains all repositories used by a number of manifests.
13+"""
14+import sys
15+import optparse
16+from xml.dom import minidom
17+
18+
19+class Manifest:
20+
21+ def __init__(self):
22+ self.remote_map = {}
23+ self.project_map = {}
24+ self.default_node = None
25+
26+ @staticmethod
27+ def compare_attr_wise(node1, node2):
28+ if node1.attributes.length != node2.attributes.length:
29+ return False
30+ for i in xrange(node1.attributes.length):
31+ a1 = node1.attributes.item(i)
32+ if a1.value != node2.attributes[a1.name].value:
33+ return False
34+ return True
35+
36+ def add_default(self, default_node):
37+ if self.default_node:
38+ if not self.compare_attr_wise(default_node, self.default_node):
39+ raise ValueError("default collision: %s vs %s" % (default_node.toxml(), self.default_node.toxml()))
40+ return
41+ self.default_node = default_node
42+
43+ def add_remote(self, remote_node):
44+ name = remote_node.getAttribute("name")
45+ if name in self.remote_map:
46+ if not self.compare_attr_wise(remote_node, self.remote_map[name]):
47+ raise ValueError("remote collision: %s vs %s" % (remote_node.toxml(), self.remote_map[name].toxml()))
48+ return False
49+ self.remote_map[name] = remote_node
50+ return True
51+
52+ def add_project(self, project_node):
53+ remote = project_node.getAttribute("remote")
54+ name = project_node.getAttribute("name")
55+ revision = project_node.getAttribute("revision")
56+ path = project_node.getAttribute("path")
57+# key = (remote, name, revision, path)
58+ key = (remote, name)
59+ if key in self.project_map:
60+ return False
61+ self.project_map[key] = project_node
62+ return True
63+
64+ def get_default(self):
65+ return self.default_node
66+
67+ def get_remotes(self):
68+ return self.remote_map.values()
69+
70+ def get_projects(self):
71+ return self.project_map.values()
72+
73+
74+def union(manifest_files):
75+ manifest = Manifest()
76+ first = True
77+ for f in manifest_files:
78+ print >>sys.stderr, "Processing: %s" % f
79+ dom = minidom.parse(f)
80+ default = dom.getElementsByTagName("default")
81+ assert len(default) == 1
82+ manifest.add_default(default[0])
83+ for r in dom.getElementsByTagName("remote"):
84+ manifest.add_remote(r)
85+ for p in dom.getElementsByTagName("project"):
86+ added = manifest.add_project(p)
87+ if not first and added:
88+ print >>sys.stderr, "Added new project: %s" % p.toxml()
89+
90+ first = False
91+
92+ return manifest
93+
94+
95+def dump(manifest, out):
96+
97+ def sort_by_name(n1, n2):
98+ return cmp(n1.getAttribute("name"), n2.getAttribute("name"))
99+
100+ out.write("""\
101+<?xml version="1.0" encoding="UTF-8"?>
102+<manifest>
103+
104+""")
105+ for r in sorted(manifest.get_remotes(), sort_by_name):
106+ out.write(r.toxml())
107+ out.write("\n")
108+ out.write("\n")
109+
110+ out.write(manifest.get_default().toxml())
111+ out.write("\n\n")
112+
113+ for p in sorted(manifest.get_projects(), sort_by_name):
114+ out.write(p.toxml())
115+ out.write("\n")
116+ out.write("""\
117+
118+</manifest>
119+""")
120+
121+optparser = optparse.OptionParser(usage="%prog -o <union.xml> <manifest.xml>...")
122+optparser.add_option("-o", metavar="FILE", help="Output file")
123+options, args = optparser.parse_args(sys.argv[1:])
124+if len(args) < 1:
125+ optparser.error("Wrong number of arguments")
126+
127+m = union(args)
128+out = sys.stdout
129+if options.o:
130+ out = open(options.o, "w")
131+dump(m, out)
132
133=== added file 'utils/seeded-builds/seed-update'
134--- utils/seeded-builds/seed-update 1970-01-01 00:00:00 +0000
135+++ utils/seeded-builds/seed-update 2012-01-24 22:35:27 +0000
136@@ -0,0 +1,19 @@
137+#!/bin/bash
138+#
139+# Update and repack an Android Build seed tarball.
140+# This is intended to be run from a crontab, once a week or so
141+# (takes ~1hr to run, produces ~15Gb tarball as of writing).
142+#
143+
144+set -e
145+
146+BASE_DIR=/mnt
147+OUT_DIR=/mnt2/seed
148+SEED=$1
149+
150+cd $BASE_DIR/$SEED
151+time repo sync --quiet -j2
152+cd $BASE_DIR
153+time tar c $SEED/ | gzip -c -1 >$OUT_DIR/$SEED.tar.gz.new
154+[ -f $OUT_DIR/$SEED.tar.gz ] && mv $OUT_DIR/$SEED.tar.gz $OUT_DIR/$SEED.tar.gz.old
155+mv $OUT_DIR/$SEED.tar.gz.new $OUT_DIR/$SEED.tar.gz

Subscribers

People subscribed via source and target branches